Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / 3d / stereo_debugger.cpp
blobb046618ccd871102ffaf60a2732a3ab7bc450e96
1 /**
2 * \file stereo_debugger.cpp
3 * \brief CStereoDebugger
4 * \date 2013-07-03 20:17GMT
5 * \author Jan Boon (Kaetemi)
6 * CStereoDebugger
7 */
9 // NeL - MMORPG Framework <https://wiki.ryzom.dev/>
10 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
12 // This program is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU Affero General Public License as
14 // published by the Free Software Foundation, either version 3 of the
15 // License, or (at your option) any later version.
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Affero General Public License for more details.
22 // You should have received a copy of the GNU Affero General Public License
23 // along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #if !FINAL_VERSION
26 #include "std3d.h"
27 #include "nel/3d/stereo_debugger.h"
29 // STL includes
31 // NeL includes
32 // #include <nel/misc/debug.h>
34 // Project includes
35 #include "nel/3d/u_camera.h"
36 #include "nel/3d/u_driver.h"
37 #include "nel/3d/material.h"
38 #include "nel/3d/texture_bloom.h"
39 #include "nel/3d/texture_user.h"
40 #include "nel/3d/driver_user.h"
41 #include "nel/3d/u_texture.h"
42 #include "nel/3d/render_target_manager.h"
44 using namespace std;
45 // using namespace NLMISC;
47 #ifdef DEBUG_NEW
48 #define new DEBUG_NEW
49 #endif
51 namespace NL3D {
53 namespace {
55 const char *a_arbfp1 =
56 "!!ARBfp1.0\n"
57 "PARAM c[1] = { { 1, 0, 0.5 } };\n"
58 "TEMP R0;\n"
59 "TEMP R1;\n"
60 "TEMP R2;\n"
61 "TEX R0, fragment.texcoord[0], texture[0], 2D;\n"
62 "TEX R1, fragment.texcoord[0], texture[1], 2D;\n"
63 "ADD R2, R0, -R1;\n"
64 "ADD R1, R0, R1;\n"
65 "MUL R1, R1, c[0].z;\n"
66 "ABS R2, R2;\n"
67 "CMP R2, -R2, c[0].x, c[0].y;\n"
68 "ADD_SAT R2.x, R2, R2.y;\n"
69 "ADD_SAT R2.x, R2, R2.z;\n"
70 "ADD_SAT R2.x, R2, R2.w;\n"
71 "ABS R2.x, R2;\n"
72 "CMP R2.x, -R2, c[0].y, c[0];\n"
73 "ABS R0.x, R2;\n"
74 "CMP R2.x, -R0, c[0].y, c[0];\n"
75 "MOV R0.xzw, R1;\n"
76 "MAD R0.y, R1, c[0].z, c[0].z;\n"
77 "CMP R0, -R2.x, R1, R0;\n"
78 "MAD R1.x, R0, c[0].z, c[0].z;\n"
79 "CMP result.color.x, -R2, R1, R0;\n"
80 "MOV result.color.yzw, R0;\n"
81 "END\n";
83 const char *a_ps_2_0 =
84 "ps_2_0\n"
85 // cgc version 3.1.0013, build date Apr 18 2012
86 // command line args: -profile ps_2_0
87 // source file: pp_stereo_debug.cg
88 //vendor NVIDIA Corporation
89 //version 3.1.0.13
90 //profile ps_2_0
91 //program pp_stereo_debug
92 //semantic pp_stereo_debug.cTex0 : TEX0
93 //semantic pp_stereo_debug.cTex1 : TEX1
94 //var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
95 //var sampler2D cTex0 : TEX0 : texunit 0 : 1 : 1
96 //var sampler2D cTex1 : TEX1 : texunit 1 : 2 : 1
97 //var float4 oCol : $vout.COLOR : COL : 3 : 1
98 //const c[0] = 0 1 0.5
99 "dcl_2d s0\n"
100 "dcl_2d s1\n"
101 "def c0, 0.00000000, 1.00000000, 0.50000000, 0\n"
102 "dcl t0.xy\n"
103 "texld r1, t0, s1\n"
104 "texld r2, t0, s0\n"
105 "add r0, r2, -r1\n"
106 "add r1, r2, r1\n"
107 "mul r1, r1, c0.z\n"
108 "abs r0, r0\n"
109 "cmp r0, -r0, c0.x, c0.y\n"
110 "add_pp_sat r0.x, r0, r0.y\n"
111 "add_pp_sat r0.x, r0, r0.z\n"
112 "add_pp_sat r0.x, r0, r0.w\n"
113 "abs_pp r0.x, r0\n"
114 "cmp_pp r0.x, -r0, c0.y, c0\n"
115 "abs_pp r0.x, r0\n"
116 "mov r2.xzw, r1\n"
117 "mad r2.y, r1, c0.z, c0.z\n"
118 "cmp r2, -r0.x, r1, r2\n"
119 "mad r1.x, r2, c0.z, c0.z\n"
120 "mov r0.yzw, r2\n"
121 "cmp r0.x, -r0, r1, r2\n"
122 "mov oC0, r0\n";
124 class CStereoDebuggerFactory : public IStereoDeviceFactory
126 public:
127 IStereoDisplay *createDevice() const
129 return new CStereoDebugger();
133 } /* anonymous namespace */
135 CStereoDebugger::CStereoDebugger() : m_Driver(NULL), m_Stage(0), m_SubStage(0), m_LeftTexU(NULL), m_RightTexU(NULL), m_PixelProgram(NULL)
140 CStereoDebugger::~CStereoDebugger()
142 if (!m_Mat.empty())
144 m_Driver->deleteMaterial(m_Mat);
147 delete m_PixelProgram;
148 m_PixelProgram = NULL;
150 m_Driver = NULL;
153 /// Sets driver and generates necessary render targets
154 void CStereoDebugger::setDriver(NL3D::UDriver *driver)
156 nlassert(!m_PixelProgram);
158 m_Driver = driver;
159 NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(driver))->getDriver();
161 if (drvInternal->supportBloomEffect() && drvInternal->supportNonPowerOfTwoTextures())
163 m_PixelProgram = new CPixelProgram();
164 // arbfp1
166 IProgram::CSource *source = new IProgram::CSource();
167 source->Features.MaterialFlags = CProgramFeatures::TextureStages;
168 source->Profile = IProgram::arbfp1;
169 source->setSourcePtr(a_arbfp1);
170 m_PixelProgram->addSource(source);
172 // ps_2_0
174 IProgram::CSource *source = new IProgram::CSource();
175 source->Features.MaterialFlags = CProgramFeatures::TextureStages;
176 source->Profile = IProgram::ps_2_0;
177 source->setSourcePtr(a_ps_2_0);
178 m_PixelProgram->addSource(source);
180 if (!drvInternal->compilePixelProgram(m_PixelProgram))
182 nlwarning("No supported pixel program for stereo debugger");
184 delete m_PixelProgram;
185 m_PixelProgram = NULL;
189 if (m_PixelProgram)
191 m_Mat = m_Driver->createMaterial();
192 m_Mat.initUnlit();
193 m_Mat.setColor(CRGBA::White);
194 m_Mat.setBlend (false);
195 m_Mat.setAlphaTest (false);
196 NL3D::CMaterial *mat = m_Mat.getObjectPtr();
197 mat->setShader(NL3D::CMaterial::Normal);
198 mat->setBlendFunc(CMaterial::one, CMaterial::zero);
199 mat->setZWrite(false);
200 mat->setZFunc(CMaterial::always);
201 mat->setDoubleSided(true);
203 m_QuadUV.V0 = CVector(0.f, 0.f, 0.5f);
204 m_QuadUV.V1 = CVector(1.f, 0.f, 0.5f);
205 m_QuadUV.V2 = CVector(1.f, 1.f, 0.5f);
206 m_QuadUV.V3 = CVector(0.f, 1.f, 0.5f);
208 m_QuadUV.Uv0 = CUV(0.f, 0.f);
209 m_QuadUV.Uv1 = CUV(1.f, 0.f);
210 m_QuadUV.Uv2 = CUV(1.f, 1.f);
211 m_QuadUV.Uv3 = CUV(0.f, 1.f);
215 bool CStereoDebugger::attachToDisplay()
217 return false;
220 void CStereoDebugger::detachFromDisplay()
225 void CStereoDebugger::getTextures()
227 nlassert(!m_LeftTexU);
228 nlassert(!m_RightTexU);
229 uint32 width, height;
230 m_Driver->getWindowSize(width, height);
231 m_LeftTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
232 m_RightTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
233 NL3D::CMaterial *mat = m_Mat.getObjectPtr();
234 mat->setTexture(0, m_LeftTexU->getITexture());
235 mat->setTexture(1, m_RightTexU->getITexture());
238 void CStereoDebugger::recycleTextures()
240 nlassert(m_LeftTexU);
241 nlassert(m_RightTexU);
242 m_Mat.getObjectPtr()->setTexture(0, NULL);
243 m_Mat.getObjectPtr()->setTexture(1, NULL);
244 m_Driver->getRenderTargetManager().recycleRenderTarget(m_LeftTexU);
245 m_Driver->getRenderTargetManager().recycleRenderTarget(m_RightTexU);
246 m_LeftTexU = NULL;
247 m_RightTexU = NULL;
251 void CStereoDebugger::releaseTextures()
253 if (!m_Mat.empty())
255 m_Mat.getObjectPtr()->setTexture(0, NULL);
256 m_Mat.getObjectPtr()->setTexture(1, NULL);
257 m_Driver->deleteMaterial(m_Mat);
260 delete m_LeftTexU;
261 m_LeftTexU = NULL;
262 m_LeftTex = NULL; // CSmartPtr
264 delete m_RightTexU;
265 m_RightTexU = NULL;
266 m_RightTex = NULL; // CSmartPtr
268 *//*
269 void CStereoDebugger::initTextures()
271 uint32 width, height;
272 m_Driver->getWindowSize(width, height);
273 NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
275 m_LeftTex = new CTextureBloom();
276 m_LeftTex->setRenderTarget(true);
277 m_LeftTex->setReleasable(false);
278 m_LeftTex->resize(width, height);
279 m_LeftTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
280 m_LeftTex->setWrapS(ITexture::Clamp);
281 m_LeftTex->setWrapT(ITexture::Clamp);
282 drvInternal->setupTexture(*m_LeftTex);
283 m_LeftTexU = new CTextureUser(m_LeftTex);
284 nlassert(!drvInternal->isTextureRectangle(m_LeftTex)); // not allowed
286 m_RightTex = new CTextureBloom();
287 m_RightTex->setRenderTarget(true);
288 m_RightTex->setReleasable(false);
289 m_RightTex->resize(width, height);
290 m_RightTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
291 m_RightTex->setWrapS(ITexture::Clamp);
292 m_RightTex->setWrapT(ITexture::Clamp);
293 drvInternal->setupTexture(*m_RightTex);
294 m_RightTexU = new CTextureUser(m_RightTex);
295 nlassert(!drvInternal->isTextureRectangle(m_RightTex)); // not allowed
298 void CStereoDebugger::setTextures()
300 NL3D::CMaterial *mat = m_Mat.getObjectPtr();
301 mat->setTexture(0, m_LeftTex);
302 mat->setTexture(1, m_RightTex);
305 void CStereoDebugger::verifyTextures()
307 if (m_Driver)
309 uint32 width, height;
310 m_Driver->getWindowSize(width, height);
311 if (m_LeftTex->getWidth() != width
312 || m_RightTex->getWidth() != width
313 || m_LeftTex->getHeight() != height
314 || m_RightTex->getHeight() != height)
316 nldebug("Rebuild textures");
317 releaseTextures();
318 initTextures();
319 setTextures();
324 /// Gets the required screen resolution for this device
325 bool CStereoDebugger::getScreenResolution(uint &width, uint &height)
327 return false;
330 /// Set latest camera position etcetera
331 void CStereoDebugger::updateCamera(uint cid, const NL3D::UCamera *camera)
333 m_Frustum[cid] = camera->getFrustum();
336 /// Get the frustum to use for clipping
337 void CStereoDebugger::getClippingFrustum(uint cid, NL3D::UCamera *camera) const
339 // do nothing
342 /// Get the original frustum of the camera
343 void CStereoDebugger::getOriginalFrustum(uint cid, NL3D::UCamera *camera) const
345 // do nothing, as we never modified it
348 /// Is there a next pass
349 bool CStereoDebugger::nextPass()
351 if (m_Driver->getPolygonMode() == UDriver::Filled)
353 switch (m_Stage)
355 case 0:
356 ++m_Stage;
357 m_SubStage = 0;
358 return true;
359 case 1:
360 ++m_Stage;
361 m_SubStage = 0;
362 return true;
363 case 2:
364 ++m_Stage;
365 m_SubStage = 0;
366 return true;
367 case 3:
368 m_Stage = 0;
369 m_SubStage = 0;
370 return false;
373 else
375 switch (m_Stage)
377 case 0:
378 ++m_Stage;
379 m_SubStage = 0;
380 return true;
381 case 1:
382 m_Stage = 0;
383 m_SubStage = 0;
384 return false;
387 return false;
390 /// Gets the current viewport
391 const NL3D::CViewport &CStereoDebugger::getCurrentViewport() const
393 if (m_Stage % 2) return m_LeftViewport;
394 else return m_RightViewport;
397 /// Gets the current camera frustum
398 const NL3D::CFrustum &CStereoDebugger::getCurrentFrustum(uint cid) const
400 return m_Frustum[cid];
403 /// Gets the current camera frustum
404 void CStereoDebugger::getCurrentFrustum(uint cid, NL3D::UCamera *camera) const
406 // do nothing
409 /// Gets the current camera matrix
410 void CStereoDebugger::getCurrentMatrix(uint cid, NL3D::UCamera *camera) const
412 // do nothing
415 /// At the start of a new render target
416 bool CStereoDebugger::wantClear()
418 m_SubStage = 1;
419 return m_Stage != 3;
422 /// The 3D scene
423 bool CStereoDebugger::wantScene()
425 m_SubStage = 2;
426 return m_Stage != 3;
429 /// The 3D scene end (after multiple wantScene)
430 bool CStereoDebugger::wantSceneEffects()
432 return m_Stage != 3;
435 /// Interface within the 3D scene
436 bool CStereoDebugger::wantInterface3D()
438 m_SubStage = 3;
439 return m_Stage == 3;
442 /// 2D Interface
443 bool CStereoDebugger::wantInterface2D()
445 m_SubStage = 4;
446 return m_Stage == 3;
449 bool CStereoDebugger::isSceneFirst()
451 return m_Stage != 3;
454 bool CStereoDebugger::isSceneLast()
456 return m_Stage != 3;
459 /// Returns true if a new render target was set, always fase if not using render targets
460 bool CStereoDebugger::beginRenderTarget()
462 if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled))
464 if (!m_LeftTexU) getTextures();
465 if (m_Stage % 2) static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_RightTexU, 0, 0, 0, 0);
466 else static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_LeftTexU, 0, 0, 0, 0);
467 return true;
469 return false;
472 /// Returns true if a render target was fully drawn, always false if not using render targets
473 bool CStereoDebugger::endRenderTarget()
475 if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled))
477 CTextureUser cu;
478 (static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
479 bool fogEnabled = m_Driver->fogEnabled();
480 m_Driver->enableFog(false);
482 m_Driver->setMatrixMode2D11();
483 CViewport vp = CViewport();
484 m_Driver->setViewport(vp);
485 uint32 width, height;
486 NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
487 NL3D::CMaterial *mat = m_Mat.getObjectPtr();
488 mat->setTexture(0, m_LeftTexU->getITexture());
489 mat->setTexture(1, m_RightTexU->getITexture());
490 drvInternal->activePixelProgram(m_PixelProgram);
492 m_Driver->drawQuad(m_QuadUV, m_Mat);
494 drvInternal->activePixelProgram(NULL);
495 m_Driver->enableFog(fogEnabled);
496 recycleTextures();
498 return true;
500 return false;
503 void CStereoDebugger::listDevices(std::vector<CStereoDeviceInfo> &devicesOut)
505 CStereoDeviceInfo devInfo;
506 devInfo.Factory = new CStereoDebuggerFactory();
507 devInfo.Library = CStereoDeviceInfo::NeL3D;
508 devInfo.Class = CStereoDeviceInfo::StereoDisplay;
509 devInfo.Manufacturer = "NeL";
510 devInfo.ProductName = "Stereo Debugger";
511 devInfo.Serial = "NL-3D-DEBUG";
512 devInfo.AllowAuto = false;
513 devicesOut.push_back(devInfo);
516 } /* namespace NL3D */
518 #endif /* #if !FINAL_VERSION */
520 /* end of file */