Changed: #970 Move all window and input related methods to a new file from OpenGL driver
This commit is contained in:
parent
a6d55108f2
commit
d16356fefe
7 changed files with 346 additions and 290 deletions
|
@ -207,9 +207,9 @@ CDriverGL::CDriverGL()
|
|||
NL3D::MAC::ctor();
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
cursor = None;
|
||||
win = 0;
|
||||
dpy = 0;
|
||||
_cursor = None;
|
||||
_win = 0;
|
||||
_dpy = 0;
|
||||
|
||||
# ifdef XF86VIDMODE
|
||||
// zero the old screen mode
|
||||
|
@ -220,6 +220,7 @@ CDriverGL::CDriverGL()
|
|||
|
||||
_OffScreen = false;
|
||||
_FullScreen = false;
|
||||
_Resizable = false;
|
||||
|
||||
_CurrentMaterial=NULL;
|
||||
_Initialized = false;
|
||||
|
@ -341,72 +342,6 @@ CDriverGL::~CDriverGL()
|
|||
#endif
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::stretchRect(ITexture * /* srcText */, NLMISC::CRect &/* srcRect */, ITexture * /* destText */, NLMISC::CRect &/* destRect */)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_stretchRect)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::supportBloomEffect() const
|
||||
{
|
||||
return (isVertexProgramSupported() && supportFrameBufferObject() && supportPackedDepthStencil() && supportTextureRectangle());
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::supportNonPowerOfTwoTextures() const
|
||||
{
|
||||
return _Extensions.ARBTextureNonPowerOfTwo;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::isTextureRectangle(ITexture * tex) const
|
||||
{
|
||||
return (supportTextureRectangle() && tex->isBloomTexture() && tex->mipMapOff()
|
||||
&& (!isPowerOf2(tex->getWidth()) || !isPowerOf2(tex->getHeight())));
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::activeFrameBufferObject(ITexture * tex)
|
||||
{
|
||||
if(supportFrameBufferObject()/* && supportPackedDepthStencil()*/)
|
||||
{
|
||||
if(tex)
|
||||
{
|
||||
CTextureDrvInfosGL* gltext = (CTextureDrvInfosGL*)(ITextureDrvInfos*)(tex->TextureDrvShare->DrvTexture);
|
||||
return gltext->activeFrameBufferObject(tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void CDriverGL::disableHardwareVertexProgram()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareVertexProgram)
|
||||
_Extensions.DisableHardwareVertexProgram= true;
|
||||
}
|
||||
|
||||
void CDriverGL::disableHardwareVertexArrayAGP()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareVertexArrayAGP)
|
||||
_Extensions.DisableHardwareVertexArrayAGP= true;
|
||||
}
|
||||
|
||||
void CDriverGL::disableHardwareTextureShader()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareTextureShader)
|
||||
_Extensions.DisableHardwareTextureShader= true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
bool CDriverGL::setupDisplay()
|
||||
{
|
||||
|
@ -682,6 +617,74 @@ bool CDriverGL::setupDisplay()
|
|||
return true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::stretchRect(ITexture * /* srcText */, NLMISC::CRect &/* srcRect */, ITexture * /* destText */, NLMISC::CRect &/* destRect */)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_stretchRect)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::supportBloomEffect() const
|
||||
{
|
||||
return (isVertexProgramSupported() && supportFrameBufferObject() && supportPackedDepthStencil() && supportTextureRectangle());
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::supportNonPowerOfTwoTextures() const
|
||||
{
|
||||
return _Extensions.ARBTextureNonPowerOfTwo;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::isTextureRectangle(ITexture * tex) const
|
||||
{
|
||||
return (supportTextureRectangle() && tex->isBloomTexture() && tex->mipMapOff()
|
||||
&& (!isPowerOf2(tex->getWidth()) || !isPowerOf2(tex->getHeight())));
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::activeFrameBufferObject(ITexture * tex)
|
||||
{
|
||||
if(supportFrameBufferObject()/* && supportPackedDepthStencil()*/)
|
||||
{
|
||||
if(tex)
|
||||
{
|
||||
CTextureDrvInfosGL* gltext = (CTextureDrvInfosGL*)(ITextureDrvInfos*)(tex->TextureDrvShare->DrvTexture);
|
||||
return gltext->activeFrameBufferObject(tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void CDriverGL::disableHardwareVertexProgram()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareVertexProgram)
|
||||
_Extensions.DisableHardwareVertexProgram= true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void CDriverGL::disableHardwareVertexArrayAGP()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareVertexArrayAGP)
|
||||
_Extensions.DisableHardwareVertexArrayAGP= true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
void CDriverGL::disableHardwareTextureShader()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_disableHardwareTextureShader)
|
||||
_Extensions.DisableHardwareTextureShader= true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void CDriverGL::resetTextureShaders()
|
||||
{
|
||||
|
@ -863,7 +866,7 @@ bool CDriverGL::swapBuffers()
|
|||
NL3D::MAC::swapBuffers();
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
glXSwapBuffers(dpy, win);
|
||||
glXSwapBuffers(_dpy, _win);
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
|
@ -977,7 +980,7 @@ bool CDriverGL::release()
|
|||
|
||||
if(_FullScreen)
|
||||
{
|
||||
switchBackToOldMode();
|
||||
restoreScreenMode();
|
||||
_FullScreen= false;
|
||||
}
|
||||
}
|
||||
|
@ -1012,22 +1015,22 @@ bool CDriverGL::release()
|
|||
#elif defined (NL_OS_UNIX)
|
||||
if (_FullScreen)
|
||||
{
|
||||
switchBackToOldMode();
|
||||
restoreScreenMode();
|
||||
|
||||
// Ungrab the keyboard (probably not necessary);
|
||||
XUnmapWindow(dpy, win);
|
||||
XSync(dpy, True);
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
XUnmapWindow(_dpy, _win);
|
||||
XSync(_dpy, True);
|
||||
XUngrabKeyboard(_dpy, CurrentTime);
|
||||
}
|
||||
|
||||
if (ctx)
|
||||
if (_ctx)
|
||||
{
|
||||
glXDestroyContext(dpy, ctx);
|
||||
ctx = NULL;
|
||||
glXDestroyContext(_dpy, _ctx);
|
||||
_ctx = NULL;
|
||||
}
|
||||
|
||||
XCloseDisplay(dpy);
|
||||
dpy = NULL;
|
||||
XCloseDisplay(_dpy);
|
||||
_dpy = NULL;
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
|
||||
|
@ -1056,7 +1059,7 @@ void CDriverGL::setupViewport (const class CViewport& viewport)
|
|||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
XWindowAttributes win_attributes;
|
||||
if (!XGetWindowAttributes(dpy, win, &win_attributes))
|
||||
if (!XGetWindowAttributes(_dpy, _win, &win_attributes))
|
||||
throw EBadDisplay("Can't get window attributes.");
|
||||
|
||||
// Setup gl viewport
|
||||
|
@ -1130,7 +1133,7 @@ void CDriverGL::setupScissor (const class CScissor& scissor)
|
|||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
XWindowAttributes win_attributes;
|
||||
if (!XGetWindowAttributes(dpy, win, &win_attributes))
|
||||
if (!XGetWindowAttributes(_dpy, _win, &win_attributes))
|
||||
throw EBadDisplay("Can't get window attributes.");
|
||||
|
||||
// Setup gl viewport
|
||||
|
@ -2729,7 +2732,7 @@ void CDriverGL::stencilFunc(TStencilFunc stencilFunc, int ref, uint mask)
|
|||
{
|
||||
H_AUTO_OGL(CDriverGL_CDriverGL)
|
||||
|
||||
GLenum glstencilFunc;
|
||||
GLenum glstencilFunc = 0;
|
||||
|
||||
switch(stencilFunc)
|
||||
{
|
||||
|
@ -2752,7 +2755,7 @@ void CDriverGL::stencilOp(TStencilOp fail, TStencilOp zfail, TStencilOp zpass)
|
|||
{
|
||||
H_AUTO_OGL(CDriverGL_CDriverGL)
|
||||
|
||||
GLenum glFail, glZFail, glZPass;
|
||||
GLenum glFail = 0, glZFail = 0, glZPass = 0;
|
||||
|
||||
switch(fail)
|
||||
{
|
||||
|
|
|
@ -310,7 +310,7 @@ public:
|
|||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
return NULL;
|
||||
#elif defined(NL_OS_UNIX)
|
||||
return win;
|
||||
return _win;
|
||||
#endif // NL_OS_WINDOWS
|
||||
}
|
||||
|
||||
|
@ -659,6 +659,7 @@ private:
|
|||
|
||||
bool _FullScreen;
|
||||
bool _OffScreen;
|
||||
bool _Resizable;
|
||||
uint _Interval;
|
||||
|
||||
sint32 _WindowWidth, _WindowHeight, _WindowX, _WindowY;
|
||||
|
@ -684,10 +685,10 @@ private:
|
|||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
Display *dpy;
|
||||
GLXContext ctx;
|
||||
Window win;
|
||||
Cursor cursor;
|
||||
Display* _dpy;
|
||||
GLXContext _ctx;
|
||||
Window _win;
|
||||
Cursor _cursor;
|
||||
NLMISC::CUnixEventEmitter _EventEmitter;
|
||||
|
||||
#ifdef XF86VIDMODE
|
||||
|
@ -841,9 +842,11 @@ private:
|
|||
bool _CurrentGlNormalize;
|
||||
|
||||
private:
|
||||
void switchBackToOldMode();
|
||||
bool setupDisplay();
|
||||
|
||||
bool restoreScreenMode();
|
||||
bool saveScreenMode();
|
||||
|
||||
// Get the proj matrix setupped in GL
|
||||
void refreshProjMatrixFromGL();
|
||||
|
||||
|
|
|
@ -416,9 +416,9 @@ PFNWGLFREEMEMORYNVPROC nwglFreeMemoryNV;
|
|||
|
||||
// Pbuffer extension
|
||||
PFNWGLCREATEPBUFFERARBPROC nwglCreatePbufferARB;
|
||||
PFNWGLGETPUFFERDCARBPROC nwglGetPbufferDCARB;
|
||||
PFNWGLRELEASEPUFFERDCARBPROC nwglReleasePbufferDCARB;
|
||||
PFNWGLDESTROYPUFFERARBPROC nwglDestroyPbufferARB;
|
||||
PFNWGLGETPBUFFERDCARBPROC nwglGetPbufferDCARB;
|
||||
PFNWGLRELEASEPBUFFERDCARBPROC nwglReleasePbufferDCARB;
|
||||
PFNWGLDESTROYPBUFFERARBPROC nwglDestroyPbufferARB;
|
||||
PFNWGLQUERYPBUFFERARBPROC nwglQueryPbufferARB;
|
||||
|
||||
// Get Pixel format extension
|
||||
|
@ -431,10 +431,9 @@ PFNWGLSWAPINTERVALEXTPROC nwglSwapIntervalEXT;
|
|||
PFNWGLGETSWAPINTERVALEXTPROC nwglGetSwapIntervalEXT;
|
||||
|
||||
// WGL_ARB_extensions_string
|
||||
PFNWGFGETEXTENSIONSSTRINGARB nwglGetExtensionsStringARB;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
|
||||
#endif
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
// ***************************************************************************
|
||||
|
@ -857,9 +856,9 @@ static bool setupWGLARBPBuffer(const char *glext)
|
|||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
CHECK_ADDRESS(PFNWGLCREATEPBUFFERARBPROC, wglCreatePbufferARB);
|
||||
CHECK_ADDRESS(PFNWGLGETPUFFERDCARBPROC, wglGetPbufferDCARB);
|
||||
CHECK_ADDRESS(PFNWGLRELEASEPUFFERDCARBPROC, wglReleasePbufferDCARB);
|
||||
CHECK_ADDRESS(PFNWGLDESTROYPUFFERARBPROC, wglDestroyPbufferARB);
|
||||
CHECK_ADDRESS(PFNWGLGETPBUFFERDCARBPROC, wglGetPbufferDCARB);
|
||||
CHECK_ADDRESS(PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB);
|
||||
CHECK_ADDRESS(PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB);
|
||||
CHECK_ADDRESS(PFNWGLQUERYPBUFFERARBPROC, wglQueryPbufferARB);
|
||||
#endif
|
||||
|
||||
|
@ -1411,7 +1410,7 @@ bool registerWGlExtensions(CGlExtensions &ext, HDC hDC)
|
|||
{
|
||||
H_AUTO_OGL(registerWGlExtensions);
|
||||
// Get proc address
|
||||
CHECK_ADDRESS(PFNWGFGETEXTENSIONSSTRINGARB, wglGetExtensionsStringARB);
|
||||
CHECK_ADDRESS(PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB);
|
||||
|
||||
// Get extension string
|
||||
const char *glext = nwglGetExtensionsStringARB (hDC);
|
||||
|
|
|
@ -158,7 +158,15 @@ public:
|
|||
ARBFragmentProgram = false;
|
||||
ARBVertexBufferObject = false;
|
||||
ARBVertexProgram = false;
|
||||
NVTextureRectangle = false;
|
||||
EXTTextureRectangle = false;
|
||||
ARBTextureRectangle = false;
|
||||
ARBTextureNonPowerOfTwo = false;
|
||||
NVOcclusionQuery = false;
|
||||
FrameBufferObject = false;
|
||||
PackedDepthStencil = false;
|
||||
NVVertexArrayRange2 = false;
|
||||
NVStateVARWithoutFlush = 0;
|
||||
|
||||
/// \name Disable Hardware feature. False by default. setuped by IDriver
|
||||
DisableHardwareVertexProgram= false;
|
||||
|
@ -167,6 +175,7 @@ public:
|
|||
|
||||
// misc
|
||||
IsATI9500OrAbove = false;
|
||||
IsGeforceFXOrAbove = false;
|
||||
};
|
||||
|
||||
std::string toString()
|
||||
|
@ -643,9 +652,9 @@ extern NEL_PFNGLGETOCCLUSIONQUERYUIVNVPROC nglGetOcclusionQueryuivNV;
|
|||
// Pbuffer extension
|
||||
//==================
|
||||
extern PFNWGLCREATEPBUFFERARBPROC nwglCreatePbufferARB;
|
||||
extern PFNWGLGETPUFFERDCARBPROC nwglGetPbufferDCARB;
|
||||
extern PFNWGLRELEASEPUFFERDCARBPROC nwglReleasePbufferDCARB;
|
||||
extern PFNWGLDESTROYPUFFERARBPROC nwglDestroyPbufferARB;
|
||||
extern PFNWGLGETPBUFFERDCARBPROC nwglGetPbufferDCARB;
|
||||
extern PFNWGLRELEASEPBUFFERDCARBPROC nwglReleasePbufferDCARB;
|
||||
extern PFNWGLDESTROYPBUFFERARBPROC nwglDestroyPbufferARB;
|
||||
extern PFNWGLQUERYPBUFFERARBPROC nwglQueryPbufferARB;
|
||||
|
||||
|
||||
|
@ -663,7 +672,7 @@ extern PFNWGLGETSWAPINTERVALEXTPROC nwglGetSwapIntervalEXT;
|
|||
|
||||
|
||||
// WGL_ARB_extensions_string
|
||||
extern PFNWGFGETEXTENSIONSSTRINGARB nwglGetExtensionsStringARB;
|
||||
extern PFNWGLGETEXTENSIONSSTRINGARBPROC nwglGetExtensionsStringARB;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ DECLARE_HANDLE (HPBUFFERARB);
|
|||
typedef void *(APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
|
||||
typedef void *(APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer);
|
||||
typedef HPBUFFERARB (APIENTRY * PFNWGLCREATEPBUFFERARBPROC) (HDC hdc, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
|
||||
typedef HDC (APIENTRY * PFNWGLGETPUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef int (APIENTRY * PFNWGLRELEASEPUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC);
|
||||
typedef BOOL (APIENTRY * PFNWGLDESTROYPUFFERARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef HDC (APIENTRY * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef int (APIENTRY * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC);
|
||||
typedef BOOL (APIENTRY * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
|
||||
typedef BOOL (APIENTRY * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
|
||||
|
||||
typedef BOOL (APIENTRY * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC, int, int, UINT, const int *, int *);
|
||||
|
@ -67,7 +67,7 @@ typedef BOOL (APIENTRY * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC, const int *, con
|
|||
typedef BOOL (APIENTRY * PFNWGLSWAPINTERVALEXTPROC) (int);
|
||||
typedef int (APIENTRY * PFNWGLGETSWAPINTERVALEXTPROC) (void);
|
||||
|
||||
typedef const char* (APIENTRY * PFNWGFGETEXTENSIONSSTRINGARB) (HDC);
|
||||
typedef const char* (APIENTRY * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,10 @@ CTextureDrvInfosGL::CTextureDrvInfosGL(IDriver *drv, ItTexDrvInfoPtrMap it, CDri
|
|||
|
||||
TextureMode = isRectangleTexture?GL_TEXTURE_RECTANGLE_NV:GL_TEXTURE_2D;
|
||||
|
||||
FBOId = 0;
|
||||
DepthFBOId = 0;
|
||||
StencilFBOId = 0;
|
||||
|
||||
InitFBO = false;
|
||||
AttachDepthStencil = true;
|
||||
UsePackedDepthStencil = drvGl->supportPackedDepthStencil();
|
||||
|
@ -157,33 +161,41 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
|
|||
InitFBO = true;
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
nlwarning("Unsupported framebuffer format\n");
|
||||
nlwarning("Unsupported framebuffer format");
|
||||
break;
|
||||
#if GL_GLEXT_VERSION > 24
|
||||
#ifdef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
nlwarning("Framebuffer incomplete attachment\n");
|
||||
nlwarning("Framebuffer incomplete attachment");
|
||||
break;
|
||||
#endif
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
nlwarning("Framebuffer incomplete, missing attachment\n");
|
||||
nlwarning("Framebuffer incomplete, missing attachment");
|
||||
break;
|
||||
#if GL_GLEXT_VERSION < 39
|
||||
#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
|
||||
nlwarning("Framebuffer incomplete, duplicate attachment\n");
|
||||
nlwarning("Framebuffer incomplete, duplicate attachment");
|
||||
break;
|
||||
#endif
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
nlwarning("Framebuffer incomplete, attached images must have same dimensions\n");
|
||||
nlwarning("Framebuffer incomplete, attached images must have same dimensions");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
nlwarning("Framebuffer incomplete, attached images must have same format\n");
|
||||
nlwarning("Framebuffer incomplete, attached images must have same format");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
nlwarning("Framebuffer incomplete, missing draw buffer\n");
|
||||
nlwarning("Framebuffer incomplete, missing draw buffer");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
nlwarning("Framebuffer incomplete, missing read buffer\n");
|
||||
nlwarning("Framebuffer incomplete, missing read buffer");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_BINDING_EXT:
|
||||
nlwarning("Framebuffer BINDING_EXT");
|
||||
break;
|
||||
#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||
nlwarning("Framebuffer incomplete multisample");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
nlwarning("Framebuffer incomplete\n");
|
||||
//nlassert(0);
|
||||
|
@ -237,7 +249,6 @@ static inline CTextureDrvInfosGL* getTextureGl(ITexture& tex)
|
|||
return gltex;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Translation of TexFmt mode.
|
||||
GLint CDriverGL::getGlTextureFormat(ITexture& tex, bool &compressed)
|
||||
|
@ -268,7 +279,6 @@ GLint CDriverGL::getGlTextureFormat(ITexture& tex, bool &compressed)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Get gl tex format, try S3TC compressed ones.
|
||||
if(_Extensions.EXTTextureCompressionS3TC)
|
||||
{
|
||||
|
@ -284,7 +294,6 @@ GLint CDriverGL::getGlTextureFormat(ITexture& tex, bool &compressed)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Get standard gl tex format.
|
||||
compressed= false;
|
||||
switch(texfmt)
|
||||
|
@ -313,7 +322,6 @@ GLint CDriverGL::getGlTextureFormat(ITexture& tex, bool &compressed)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
static GLint getGlSrcTextureFormat(ITexture &tex, GLint glfmt)
|
||||
{
|
||||
|
@ -392,7 +400,6 @@ uint CDriverGL::computeMipMapMemoryUsage(uint w, uint h, GLint glfmt) const
|
|||
return w*h* 4;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// Translation of Wrap mode.
|
||||
static inline GLenum translateWrapToGl(ITexture::TWrapMode mode, const CGlExtensions &extensions)
|
||||
|
@ -409,7 +416,6 @@ static inline GLenum translateWrapToGl(ITexture::TWrapMode mode, const CGlExtens
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
static inline GLenum translateMagFilterToGl(CTextureDrvInfosGL *glText)
|
||||
{
|
||||
|
@ -472,7 +478,6 @@ static inline GLenum translateMinFilterToGl(CTextureDrvInfosGL *glText)
|
|||
#endif // NEL_FORCE_NEAREST
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
static inline bool sameDXTCFormat(ITexture &tex, GLint glfmt)
|
||||
{
|
||||
|
@ -489,7 +494,6 @@ static inline bool sameDXTCFormat(ITexture &tex, GLint glfmt)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
static inline bool isDXTCFormat(GLint glfmt)
|
||||
{
|
||||
|
@ -506,7 +510,6 @@ static inline bool isDXTCFormat(GLint glfmt)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::setupTexture (ITexture& tex)
|
||||
{
|
||||
|
@ -515,8 +518,6 @@ bool CDriverGL::setupTexture (ITexture& tex)
|
|||
return setupTextureEx (tex, true, nTmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
#ifndef NL_DEBUG
|
||||
inline
|
||||
|
@ -624,15 +625,12 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
return true; // Do not do anything
|
||||
}
|
||||
|
||||
|
||||
// 1. If modified, may (re)load texture part or all of the texture.
|
||||
//=================================================================
|
||||
|
||||
|
||||
bool mustLoadAll= false;
|
||||
bool mustLoadPart= false;
|
||||
|
||||
|
||||
// To avoid any delete/new ptr problem, disable all texturing.
|
||||
/* If an old texture is deleted, _CurrentTexture[*] and _CurrentTextureInfoGL[*] are invalid.
|
||||
But this is grave only if a new texture is created, with the same pointer (bad luck).
|
||||
|
@ -643,7 +641,6 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
activateTexture(stage, NULL);
|
||||
}
|
||||
|
||||
|
||||
// A. Share mgt.
|
||||
//==============
|
||||
if(tex.supportSharing())
|
||||
|
@ -786,7 +783,6 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
glTexImage2D (NLCubeFaceToGLCubeFace[nText], i, glfmt, w, h, 0, glSrcFmt, glSrcType, ptr);
|
||||
bAllUploaded = true;
|
||||
NEL_MEASURE_UPLOAD_TIME_END
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -915,7 +911,6 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
}
|
||||
//printf("%d,%d,%d\n", tex.getMipMapCount(), tex.getWidth(0), tex.getHeight(0));
|
||||
|
||||
|
||||
// profiling. add new TextureMemory usage.
|
||||
_AllocatedTextureMemory+= gltext->TextureMemory;
|
||||
}
|
||||
|
@ -983,8 +978,6 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
else
|
||||
glTexSubImage2D (GL_TEXTURE_2D, i, x0, y0, x1-x0, y1-y0, glSrcFmt,glSrcType, NULL);
|
||||
|
||||
|
||||
|
||||
// Next mipmap!!
|
||||
// floor .
|
||||
x0= x0/2;
|
||||
|
@ -999,12 +992,9 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Release, if wanted.
|
||||
if(tex.getReleasable())
|
||||
tex.release();
|
||||
|
@ -1019,13 +1009,11 @@ bool CDriverGL::setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded,
|
|||
_DriverGLStates.setTextureMode(CDriverGLStates::TextureDisabled);
|
||||
}
|
||||
|
||||
|
||||
// The texture is correctly setuped.
|
||||
tex.clearTouched();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
|
||||
{
|
||||
|
@ -1067,14 +1055,11 @@ bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
|
|||
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
|
||||
|
||||
bool dummy;
|
||||
GLint glfmt = getGlTextureFormat (tex, dummy);
|
||||
GLint glSrcFmt = getGlSrcTextureFormat (tex, glfmt);
|
||||
GLenum glSrcType= getGlSrcTextureComponentType(glSrcFmt);
|
||||
|
||||
|
||||
// If DXTC format
|
||||
if (_Extensions.EXTTextureCompressionS3TC && sameDXTCFormat(tex, glfmt))
|
||||
{
|
||||
|
@ -1116,7 +1101,6 @@ bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
nlassert (((x0&3) == 0) && ((y0&3) == 0));
|
||||
if ((w>=4) && (h>=4))
|
||||
{
|
||||
|
@ -1132,8 +1116,6 @@ bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
|
|||
nglCompressedTexImage2DARB (GL_TEXTURE_2D, nNumMipMap-decalMipMapResize,
|
||||
glfmt, w, h, 0, imageSize, ptr);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1150,8 +1132,6 @@ bool CDriverGL::uploadTexture (ITexture& tex, CRect& rect, uint8 nNumMipMap)
|
|||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Disable texture 0
|
||||
|
@ -1195,7 +1175,6 @@ bool CDriverGL::activateTexture(uint stage, ITexture *tex)
|
|||
_TextureUsed.insert (gltext);
|
||||
}
|
||||
|
||||
|
||||
if(tex->isTextureCube())
|
||||
{
|
||||
// setup texture mode, after activeTextureARB()
|
||||
|
@ -1215,7 +1194,6 @@ bool CDriverGL::activateTexture(uint stage, ITexture *tex)
|
|||
// setup this texture
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, gltext->ID);
|
||||
|
||||
|
||||
// Change parameters of texture, if necessary.
|
||||
//============================================
|
||||
if(gltext->MagFilter!= tex->getMagFilter())
|
||||
|
@ -1228,8 +1206,6 @@ bool CDriverGL::activateTexture(uint stage, ITexture *tex)
|
|||
gltext->MinFilter= tex->getMinFilter();
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER, translateMinFilterToGl(gltext));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1320,7 +1296,6 @@ static void forceActivateTexEnvModeEnvCombine4(const CMaterial::CTexEnv &env)
|
|||
H_AUTO_OGL(forceActivateTexEnvModeEnvCombine4)
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
|
||||
|
||||
|
||||
//== RGB ==
|
||||
switch(env.Env.OpRGB)
|
||||
{
|
||||
|
@ -1683,7 +1658,6 @@ void CDriverGL::forceActivateTexEnvMode(uint stage, const CMaterial::CTexEnv &
|
|||
//=====
|
||||
if (env.Env.OpAlpha == CMaterial::Mad)
|
||||
{
|
||||
|
||||
if (_Extensions.ATITextureEnvCombine3)
|
||||
{
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE_ADD_ATI);
|
||||
|
@ -1737,12 +1711,8 @@ void CDriverGL::forceActivateTexEnvMode(uint stage, const CMaterial::CTexEnv &
|
|||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
void CDriverGL::activateTexEnvColor(uint stage, NLMISC::CRGBA col)
|
||||
{
|
||||
|
@ -1753,7 +1723,6 @@ void CDriverGL::activateTexEnvColor(uint stage, NLMISC::CRGBA col)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
void CDriverGL::activateTexEnvMode(uint stage, const CMaterial::CTexEnv &env)
|
||||
{
|
||||
|
@ -1825,7 +1794,13 @@ void CDriverGL::swapTextureHandle(ITexture &tex0, ITexture &tex1)
|
|||
swap(t0->WrapT, t1->WrapT);
|
||||
swap(t0->MagFilter, t1->MagFilter);
|
||||
swap(t0->MinFilter, t1->MinFilter);
|
||||
|
||||
swap(t0->TextureMode, t1->TextureMode);
|
||||
swap(t0->FBOId, t1->FBOId);
|
||||
swap(t0->DepthFBOId, t1->DepthFBOId);
|
||||
swap(t0->StencilFBOId, t1->StencilFBOId);
|
||||
swap(t0->InitFBO, t1->InitFBO);
|
||||
swap(t0->AttachDepthStencil, t1->AttachDepthStencil);
|
||||
swap(t0->UsePackedDepthStencil, t1->UsePackedDepthStencil);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1879,6 +1854,7 @@ bool CDriverGL::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width
|
|||
getWindowSize(w, h);
|
||||
|
||||
getViewport(_OldViewport);
|
||||
|
||||
CViewport newVP;
|
||||
newVP.init(0, 0, ((float)width/(float)w), ((float)height/(float)h));
|
||||
setupViewport(newVP);
|
||||
|
@ -1972,7 +1948,7 @@ bool CDriverGL::getRenderTargetSize (uint32 &width, uint32 &height)
|
|||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
XWindowAttributes win_attributes;
|
||||
if (!XGetWindowAttributes(dpy, win, &win_attributes))
|
||||
if (!XGetWindowAttributes(_dpy, _win, &win_attributes))
|
||||
throw EBadDisplay("Can't get window attributes.");
|
||||
|
||||
// Setup gl viewport
|
||||
|
|
|
@ -153,7 +153,7 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
|
|||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.hIcon = (HICON)windowIcon;
|
||||
wc.hCursor = LoadCursorW(NULL,(LPCWSTR)IDC_ARROW);
|
||||
wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = WHITE_BRUSH;
|
||||
wc.lpszClassName = L"NLClass";
|
||||
wc.lpszMenuName = NULL;
|
||||
|
@ -186,8 +186,9 @@ bool CDriverGL::init (uint windowIcon, emptyProc exitFunc)
|
|||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
dpy = XOpenDisplay(NULL);
|
||||
if (dpy == NULL)
|
||||
_dpy = XOpenDisplay(NULL);
|
||||
|
||||
if (_dpy == NULL)
|
||||
{
|
||||
nlerror ("XOpenDisplay failed on '%s'", getenv("DISPLAY"));
|
||||
}
|
||||
|
@ -656,9 +657,12 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
|
|||
{
|
||||
_EventEmitter.removeEmitter(_EventEmitter.getEmitter(_EventEmitter.getNumEmitters() - 1));
|
||||
}
|
||||
|
||||
NLMISC::CWinEventEmitter *we = new NLMISC::CWinEventEmitter;
|
||||
|
||||
// setup the event emitter, and try to retrieve a direct input interface
|
||||
_EventEmitter.addEmitter(we, true /*must delete*/); // the main emitter
|
||||
|
||||
/// try to get direct input
|
||||
try
|
||||
{
|
||||
|
@ -706,56 +710,44 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
|
|||
};
|
||||
|
||||
// first try 24bpp and if that fails 16bpp
|
||||
XVisualInfo *visual_info = glXChooseVisual (dpy, DefaultScreen(dpy), sAttribList24bpp);
|
||||
XVisualInfo *visual_info = glXChooseVisual (_dpy, DefaultScreen(_dpy), sAttribList24bpp);
|
||||
if (visual_info == NULL)
|
||||
visual_info = glXChooseVisual(dpy, DefaultScreen(dpy), sAttribList16bpp);
|
||||
visual_info = glXChooseVisual(_dpy, DefaultScreen(_dpy), sAttribList16bpp);
|
||||
if(visual_info == NULL)
|
||||
{
|
||||
nlerror("glXChooseVisual() failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug("3D: glXChooseVisual OK");
|
||||
}
|
||||
|
||||
ctx = glXCreateContext (dpy, visual_info, None, GL_TRUE);
|
||||
if(ctx == NULL)
|
||||
_ctx = glXCreateContext (_dpy, visual_info, None, GL_TRUE);
|
||||
if(_ctx == NULL)
|
||||
{
|
||||
nlerror("glXCreateContext() failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug("3D: glXCreateContext() OK");
|
||||
}
|
||||
|
||||
XSetWindowAttributes attr;
|
||||
attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
|
||||
attr.background_pixel = BlackPixel(_dpy, DefaultScreen(_dpy));
|
||||
attr.override_redirect = False;
|
||||
|
||||
int attr_flags = CWOverrideRedirect | CWBackPixel;
|
||||
|
||||
if(wnd == EmptyWindow)
|
||||
{
|
||||
nlWindow root = RootWindow(dpy, DefaultScreen(dpy));
|
||||
nlWindow root = RootWindow(_dpy, DefaultScreen(_dpy));
|
||||
|
||||
attr.colormap = XCreateColormap(dpy, root, visual_info->visual, AllocNone);
|
||||
attr.colormap = XCreateColormap(_dpy, root, visual_info->visual, AllocNone);
|
||||
attr_flags |= CWColormap;
|
||||
|
||||
win = XCreateWindow (dpy, root, 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, attr_flags, &attr);
|
||||
_win = XCreateWindow (_dpy, root, 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, attr_flags, &attr);
|
||||
|
||||
if (win == EmptyWindow)
|
||||
if (_win == EmptyWindow)
|
||||
{
|
||||
nlerror("3D: XCreateWindow() failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
nldebug("3D: XCreateWindow() OK");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
win = wnd;
|
||||
XChangeWindowAttributes(dpy, win, attr_flags, &attr);
|
||||
_win = wnd;
|
||||
XChangeWindowAttributes(_dpy, _win, attr_flags, &attr);
|
||||
}
|
||||
|
||||
const char *title="NeL window";
|
||||
|
@ -772,21 +764,21 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re
|
|||
size_hints.max_height = height;
|
||||
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
Xutf8SetWMProperties (dpy, win, (char*)title, (char*)title, NULL, 0, &size_hints, NULL, NULL);
|
||||
Xutf8SetWMProperties (_dpy, _win, (char*)title, (char*)title, NULL, 0, &size_hints, NULL, NULL);
|
||||
#else
|
||||
XTextProperty text_property;
|
||||
XStringListToTextProperty((char**)&title, 1, &text_property);
|
||||
XSetWMProperties (dpy, win, &text_property, &text_property, 0, 0, &size_hints, 0, 0);
|
||||
XSetWMProperties (_dpy, _win, &text_property, &text_property, 0, 0, &size_hints, 0, 0);
|
||||
#endif
|
||||
|
||||
glXMakeCurrent (dpy, win, ctx);
|
||||
XMapRaised (dpy, win);
|
||||
glXMakeCurrent (_dpy, _win, _ctx);
|
||||
XMapRaised (_dpy, _win);
|
||||
|
||||
XSelectInput (dpy, win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask);
|
||||
XSelectInput (_dpy, _win, KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask);
|
||||
|
||||
XMapWindow(dpy, win);
|
||||
XMapWindow(_dpy, _win);
|
||||
|
||||
_EventEmitter.init (dpy, win);
|
||||
_EventEmitter.init (_dpy, _win);
|
||||
|
||||
// XEvent event;
|
||||
// XIfEvent(dpy, &event, WaitForNotify, (char *)this);
|
||||
|
@ -814,11 +806,47 @@ static void modifyStyle (HWND hWnd, int nStyleOffset, LONG_PTR dwRemove, LONG_PT
|
|||
#endif
|
||||
|
||||
// --------------------------------------------------
|
||||
void CDriverGL::switchBackToOldMode()
|
||||
bool CDriverGL::saveScreenMode()
|
||||
{
|
||||
#ifdef NL_OS_WINDOWS
|
||||
ChangeDisplaySettings(&_OldScreenMode, 0);
|
||||
#elif defined(XF86VIDMODE)
|
||||
H_AUTO_OGL(CDriverGL_saveScreenMode)
|
||||
|
||||
bool res = true;
|
||||
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
|
||||
// don't need to save it because Windows will use default desktop resolution
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
#if defined(XF86VIDMODE)
|
||||
|
||||
// Store old mode in order to restore it when leaving fullscreen
|
||||
memset(&_OldScreenMode, 0, sizeof(XF86VidModeModeLine));
|
||||
XF86VidModeGetModeLine(_dpy, DefaultScreen(_dpy), &_OldDotClock, &_OldScreenMode);
|
||||
res = XF86VidModeGetViewPort(_dpy, DefaultScreen(_dpy), &_OldX, &_OldY);
|
||||
|
||||
#endif // XF86VIDMODE
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
bool CDriverGL::restoreScreenMode()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_restoreScreenMode)
|
||||
|
||||
bool res = false;
|
||||
|
||||
#if defined(NL_OS_WINDOWS)
|
||||
|
||||
res = (ChangeDisplaySettings(NULL, 0) == DISP_CHANGE_SUCCESSFUL);
|
||||
|
||||
#elif defined(NL_OS_UNIX)
|
||||
|
||||
#if defined(XF86VIDMODE)
|
||||
|
||||
XF86VidModeModeInfo info;
|
||||
nlinfo("3D: Switching back to original mode");
|
||||
|
||||
|
@ -837,12 +865,16 @@ void CDriverGL::switchBackToOldMode()
|
|||
info.c_private = _OldScreenMode.c_private;
|
||||
|
||||
nlinfo("3D: Switching back mode to %dx%d", info.hdisplay, info.vdisplay);
|
||||
XF86VidModeSwitchToMode(dpy, DefaultScreen(dpy), &info);
|
||||
XF86VidModeSwitchToMode(_dpy, DefaultScreen(_dpy), &info);
|
||||
nlinfo("3D: Switching back viewport to %d,%d",_OldX, _OldY);
|
||||
XF86VidModeSetViewPort(dpy, DefaultScreen(dpy), _OldX, _OldY);
|
||||
#endif // XF86VIDMODE
|
||||
}
|
||||
res = XF86VidModeSetViewPort(_dpy, DefaultScreen(_dpy), _OldX, _OldY);
|
||||
|
||||
#endif // XF86VIDMODE
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
bool CDriverGL::setMode(const GfxMode& mode)
|
||||
|
@ -853,7 +885,7 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
{
|
||||
if (_FullScreen)
|
||||
{
|
||||
switchBackToOldMode();
|
||||
restoreScreenMode();
|
||||
modifyStyle(_hWnd, GWL_STYLE, WS_POPUP, WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS);
|
||||
}
|
||||
_WindowWidth = mode.Width;
|
||||
|
@ -863,14 +895,8 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
else
|
||||
{
|
||||
// get old mode.
|
||||
DEVMODE oldDevMode;
|
||||
if (!_FullScreen)
|
||||
{
|
||||
oldDevMode.dmSize= sizeof(DEVMODE);
|
||||
oldDevMode.dmDriverExtra= 0;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &oldDevMode);
|
||||
oldDevMode.dmFields= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY ;
|
||||
}
|
||||
saveScreenMode();
|
||||
|
||||
// setup new mode
|
||||
DEVMODE newDevMode;
|
||||
|
@ -900,9 +926,6 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
_WindowWidth = mode.Width;
|
||||
_WindowHeight = mode.Height;
|
||||
_Depth= mode.Depth;
|
||||
// bkup user mode
|
||||
if (!_FullScreen)
|
||||
_OldScreenMode= oldDevMode;
|
||||
|
||||
// if old mode was not fullscreen
|
||||
if (!_FullScreen)
|
||||
|
@ -944,28 +967,26 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
#ifdef XF86VIDMODE
|
||||
if (!mode.Windowed)
|
||||
{
|
||||
int screen = DefaultScreen(_dpy);
|
||||
|
||||
// Store old mdoe in order to restore it when leaving fullscreen
|
||||
if (mode.Windowed == _FullScreen)
|
||||
{
|
||||
memset(&_OldScreenMode, 0, sizeof(_OldScreenMode));
|
||||
XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &_OldDotClock, &_OldScreenMode);
|
||||
XF86VidModeGetViewPort(dpy, DefaultScreen(dpy), &_OldX, &_OldY);
|
||||
}
|
||||
saveScreenMode();
|
||||
|
||||
// Find the requested mode and use it
|
||||
XF86VidModeModeInfo **modes;
|
||||
int nmodes;
|
||||
if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &nmodes, &modes))
|
||||
if (XF86VidModeGetAllModeLines(_dpy, screen, &nmodes, &modes))
|
||||
{
|
||||
for (int i = 0; i < nmodes; i++)
|
||||
{
|
||||
nldebug("3D: Available mode - %dx%d", modes[i]->hdisplay, modes[i]->vdisplay);
|
||||
if(modes[i]->hdisplay == mode.Width && modes[i]->vdisplay == mode.Height)
|
||||
{
|
||||
if(XF86VidModeSwitchToMode(dpy, DefaultScreen(dpy), modes[i]))
|
||||
if(XF86VidModeSwitchToMode(_dpy, screen, modes[i]))
|
||||
{
|
||||
nlinfo("3D: Switching to mode %dx%d", modes[i]->hdisplay, modes[i]->vdisplay);
|
||||
XF86VidModeSetViewPort(dpy, DefaultScreen(dpy), 0, 0);
|
||||
XF86VidModeSetViewPort(_dpy, screen, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -973,7 +994,7 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
}
|
||||
}
|
||||
else if (mode.Windowed == _FullScreen)
|
||||
switchBackToOldMode();
|
||||
restoreScreenMode();
|
||||
#endif // XF86VIDMODE
|
||||
|
||||
// Update WM hints (update size and disallow resizing)
|
||||
|
@ -996,7 +1017,7 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
}
|
||||
#endif
|
||||
|
||||
XSetWMNormalHints(dpy, win, &size_hints);
|
||||
XSetWMNormalHints(_dpy, _win, &size_hints);
|
||||
|
||||
// x11 fullscreen is not working on mac os x
|
||||
#if !defined(NL_OS_MAC)
|
||||
|
@ -1006,13 +1027,13 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
XEvent xev;
|
||||
memset(&xev, 0, sizeof(xev));
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.window = win;
|
||||
xev.xclient.message_type = XInternAtom(dpy, "_NET_WM_STATE", false);
|
||||
xev.xclient.window = _win;
|
||||
xev.xclient.message_type = XInternAtom(_dpy, "_NET_WM_STATE", false);
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = !mode.Windowed;
|
||||
xev.xclient.data.l[1] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", false);
|
||||
xev.xclient.data.l[1] = XInternAtom(_dpy, "_NET_WM_STATE_FULLSCREEN", false);
|
||||
xev.xclient.data.l[2] = 0;
|
||||
XSendEvent(dpy, DefaultRootWindow(dpy), false, SubstructureNotifyMask, &xev);
|
||||
XSendEvent(_dpy, DefaultRootWindow(_dpy), false, SubstructureNotifyMask, &xev);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1023,8 +1044,8 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
#endif
|
||||
|
||||
// Resize and update the window
|
||||
XResizeWindow(dpy, win, mode.Width, mode.Height);
|
||||
XMapWindow(dpy, win);
|
||||
XResizeWindow(_dpy, _win, mode.Width, mode.Height);
|
||||
XMapWindow(_dpy, _win);
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
return true;
|
||||
|
@ -1065,7 +1086,7 @@ bool CDriverGL::getModes(std::vector<GfxMode> &modes)
|
|||
# ifdef XF86VIDMODE
|
||||
int nmodes;
|
||||
XF86VidModeModeInfo **ms;
|
||||
Bool ok = XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &nmodes, &ms);
|
||||
Bool ok = XF86VidModeGetAllModeLines(_dpy, DefaultScreen(_dpy), &nmodes, &ms);
|
||||
if(ok)
|
||||
{
|
||||
nldebug("3D: %d available modes:", nmodes);
|
||||
|
@ -1096,7 +1117,9 @@ bool CDriverGL::getModes(std::vector<GfxMode> &modes)
|
|||
bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_getCurrentScreenMode)
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
DEVMODE devmode;
|
||||
devmode.dmSize = sizeof(DEVMODE);
|
||||
devmode.dmDriverExtra = 0;
|
||||
|
@ -1108,6 +1131,7 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
|||
mode.Frequency = devmode.dmDisplayFrequency,
|
||||
mode.Width = (uint16)devmode.dmPelsWidth;
|
||||
mode.Height = (uint16)devmode.dmPelsHeight;
|
||||
mode.AntiAlias = -1;
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
# warning "OpenGL Driver: Temporary Mac Implementation"
|
||||
|
@ -1131,7 +1155,7 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
|||
sint pixelClock;
|
||||
XF86VidModeModeLine xmode;
|
||||
|
||||
if (!XF86VidModeGetModeLine(dpy, DefaultScreen(dpy), &pixelClock, &xmode))
|
||||
if (!XF86VidModeGetModeLine(_dpy, DefaultScreen(_dpy), &pixelClock, &xmode))
|
||||
{
|
||||
nlwarning("XF86VidModeGetModeLine returns 0, cannot get current video mode");
|
||||
return false;
|
||||
|
@ -1145,7 +1169,7 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
|||
#endif
|
||||
|
||||
mode.OffScreen = false;
|
||||
mode.Depth = (uint) DefaultDepth(dpy, DefaultScreen(dpy));
|
||||
mode.Depth = (uint) DefaultDepth(_dpy, DefaultScreen(_dpy));
|
||||
mode.Frequency = 1000 * pixelClock / (xmode.htotal * xmode.vtotal) ;
|
||||
mode.Width = xmode.hdisplay;
|
||||
mode.Height = xmode.vdisplay;
|
||||
|
@ -1161,16 +1185,23 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode)
|
|||
void CDriverGL::setWindowTitle(const ucstring &title)
|
||||
{
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
SetWindowTextW(_hWnd, (WCHAR*)title.c_str());
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::setWindowTitle(title);
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#ifdef X_HAVE_UTF8_STRING
|
||||
Xutf8SetWMProperties (_dpy, _win, (char*)title.toUtf8().c_str(), (char*)title.toUtf8().c_str(), NULL, 0, NULL, NULL, NULL);
|
||||
#else
|
||||
XTextProperty text_property;
|
||||
char *t = (char*)title.toUtf8().c_str();
|
||||
XStringListToTextProperty(&t, 1, &text_property);
|
||||
XSetWMName(dpy, win, &text_property);
|
||||
XStringListToTextProperty((char**)&title.toUtf8().c_str(), 1, &text_property);
|
||||
XSetWMProperties (_dpy, _win, &text_property, &text_property, 0, 0, NULL, 0, 0);
|
||||
#endif
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
}
|
||||
|
||||
|
@ -1179,14 +1210,18 @@ void CDriverGL::setWindowPos(uint32 x, uint32 y)
|
|||
{
|
||||
_WindowX = (sint32)x;
|
||||
_WindowY = (sint32)y;
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
SetWindowPos(_hWnd, NULL, _WindowX, _WindowY, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
|
||||
|
||||
SetWindowPos(_hWnd, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::setWindowPos(x, y);
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
XMoveWindow(dpy, win, _WindowX, _WindowY);
|
||||
|
||||
XMoveWindow(_dpy, _win, x, y);
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
}
|
||||
|
@ -1201,10 +1236,17 @@ void CDriverGL::showWindow(bool show)
|
|||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
if (show)
|
||||
XMapWindow(dpy, win);
|
||||
{
|
||||
XMapWindow(_dpy, _win);
|
||||
// XMapRaised(_dpy, _win);
|
||||
}
|
||||
else
|
||||
XUnmapWindow(dpy, win);
|
||||
{
|
||||
XUnmapWindow(_dpy, _win);
|
||||
}
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
}
|
||||
|
||||
|
@ -1224,25 +1266,26 @@ bool CDriverGL::activate()
|
|||
{
|
||||
H_AUTO_OGL(CDriverGL_activate)
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
HGLRC hglrc = wglGetCurrentContext();
|
||||
|
||||
|
||||
if (hglrc != _hRC)
|
||||
{
|
||||
wglMakeCurrent(_hDC, _hRC);
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
# warning "OpenGL Driver: Temporary Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Temporary Mac Implementation");
|
||||
|
||||
// already done in setDisplay, not needed here - unclean! FIXME
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
GLXContext nctx = glXGetCurrentContext();
|
||||
if (nctx != NULL && nctx!=ctx)
|
||||
{
|
||||
glXMakeCurrent(dpy, win,ctx);
|
||||
}
|
||||
|
||||
if (nctx != NULL && nctx != _ctx)
|
||||
glXMakeCurrent(_dpy, _win, _ctx);
|
||||
|
||||
#endif // NL_OS_WINDOWS
|
||||
return true;
|
||||
}
|
||||
|
@ -1294,7 +1337,9 @@ IDriver::TMessageBoxId CDriverGL::systemMessageBox (const char* message, const c
|
|||
void CDriverGL::showCursor(bool b)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_showCursor)
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
if (b)
|
||||
{
|
||||
while (ShowCursor(b) < 0)
|
||||
|
@ -1305,6 +1350,7 @@ void CDriverGL::showCursor(bool b)
|
|||
while (ShowCursor(b) >= 0)
|
||||
;
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::showCursor(b);
|
||||
|
@ -1313,36 +1359,38 @@ void CDriverGL::showCursor(bool b)
|
|||
|
||||
if (b)
|
||||
{
|
||||
if (cursor != None)
|
||||
if (_cursor != None)
|
||||
{
|
||||
XFreeCursor(dpy, cursor);
|
||||
cursor = None;
|
||||
XFreeCursor(_dpy, _cursor);
|
||||
_cursor = None;
|
||||
}
|
||||
XUndefineCursor(dpy, win);
|
||||
XUndefineCursor(_dpy, _win);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cursor == None)
|
||||
if (_cursor == None)
|
||||
{
|
||||
char bm_no_data[] = { 0,0,0,0, 0,0,0,0 };
|
||||
Pixmap pixmap_no_data = XCreateBitmapFromData (dpy, win, bm_no_data, 8, 8);
|
||||
Pixmap pixmap_no_data = XCreateBitmapFromData (_dpy, _win, bm_no_data, 8, 8);
|
||||
XColor black;
|
||||
memset(&black, 0, sizeof (XColor));
|
||||
black.flags = DoRed | DoGreen | DoBlue;
|
||||
cursor = XCreatePixmapCursor (dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0);
|
||||
XFreePixmap(dpy, pixmap_no_data);
|
||||
_cursor = XCreatePixmapCursor (_dpy, pixmap_no_data, pixmap_no_data, &black, &black, 0, 0);
|
||||
XFreePixmap(_dpy, pixmap_no_data);
|
||||
}
|
||||
XDefineCursor(dpy, win, cursor);
|
||||
}
|
||||
#endif // NL_OS_UNIX
|
||||
XDefineCursor(_dpy, _win, _cursor);
|
||||
}
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
void CDriverGL::setMousePos(float x, float y)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_setMousePos)
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
|
||||
if (_hWnd)
|
||||
{
|
||||
// NeL window coordinate to MSWindows coordinates
|
||||
|
@ -1352,24 +1400,29 @@ void CDriverGL::setMousePos(float x, float y)
|
|||
ClientToScreen (_hWnd, &pt);
|
||||
SetCursorPos(pt.x, pt.y);
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::setMousePos(x, y);
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (dpy, win, &xwa);
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
int x1 = (int)(x * (float) xwa.width);
|
||||
int y1 = (int)((1.0f - y) * (float) xwa.height);
|
||||
XWarpPointer (dpy, None, win, None, None, None, None, x1, y1);
|
||||
XWarpPointer (_dpy, None, _win, None, None, None, None, x1, y1);
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
}
|
||||
|
||||
void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_getWindowSize)
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
// Off-srceen rendering ?
|
||||
|
||||
// Off-screen rendering ?
|
||||
if (_OffScreen)
|
||||
{
|
||||
if (_PBuffer)
|
||||
|
@ -1386,23 +1439,28 @@ void CDriverGL::getWindowSize(uint32 &width, uint32 &height)
|
|||
height = (uint32)(_WindowHeight);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::getWindowSize(width, height);
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes (dpy, win, &xwa);
|
||||
XGetWindowAttributes (_dpy, _win, &xwa);
|
||||
width = (uint32) xwa.width;
|
||||
height = (uint32) xwa.height;
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
}
|
||||
|
||||
void CDriverGL::getWindowPos(uint32 &x, uint32 &y)
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_getWindowPos)
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
// Off-srceen rendering ?
|
||||
|
||||
// Off-screen rendering ?
|
||||
if (_OffScreen)
|
||||
{
|
||||
if (_PBuffer)
|
||||
|
@ -1414,16 +1472,19 @@ void CDriverGL::getWindowPos(uint32 &x, uint32 &y)
|
|||
{
|
||||
if (_hWnd)
|
||||
{
|
||||
x = (uint32)(_WindowX);
|
||||
y = (uint32)(_WindowY);
|
||||
x = (uint32)_WindowX;
|
||||
y = (uint32)_WindowY;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
|
||||
NL3D::MAC::getWindowPos(x, y);
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
x = y = 0;
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
}
|
||||
|
||||
|
@ -1431,8 +1492,13 @@ void CDriverGL::getWindowPos(uint32 &x, uint32 &y)
|
|||
bool CDriverGL::isActive()
|
||||
{
|
||||
H_AUTO_OGL(CDriverGL_isActive)
|
||||
|
||||
bool res = true;
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
return (IsWindow(_hWnd) != 0);
|
||||
|
||||
res = (IsWindow(_hWnd) != FALSE);
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
// nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
|
@ -1440,7 +1506,8 @@ bool CDriverGL::isActive()
|
|||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
return true;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void CDriverGL::setCapture (bool b)
|
||||
|
@ -1488,11 +1555,11 @@ void CDriverGL::setCapture (bool b)
|
|||
|
||||
if(b) // capture the cursor.
|
||||
{
|
||||
XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
|
||||
XGrabPointer(_dpy, _win, True, 0, GrabModeAsync, GrabModeAsync, _win, None, CurrentTime);
|
||||
}
|
||||
else // release the cursor.
|
||||
{
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
XUngrabPointer(_dpy, CurrentTime);
|
||||
}
|
||||
|
||||
#endif // NL_OS_UNIX
|
||||
|
@ -1671,21 +1738,20 @@ bool CDriverGL::setMonitorColorProperties (const CMonitorColorProperties &proper
|
|||
else
|
||||
{
|
||||
nlwarning ("(CDriverGL::setMonitorColorProperties): can't create DC");
|
||||
return false;
|
||||
}
|
||||
|
||||
#elif defined(NL_OS_MAC) && defined(NL_MAC_NATIVE)
|
||||
# warning "OpenGL Driver: Missing Mac Implementation"
|
||||
nlwarning("OpenGL Driver: Missing Mac Implementation");
|
||||
return false;
|
||||
|
||||
#elif defined (NL_OS_UNIX)
|
||||
|
||||
// TODO for Linux: implement CDriverGL::setMonitorColorProperties
|
||||
nlwarning ("CDriverGL::setMonitorColorProperties not implemented");
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // NL3D
|
||||
|
|
Loading…
Reference in a new issue