Developer Documentation
PostProcessorPhilipsStereo.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 #include <ACG/GL/acg_glew.hh>
44 
45 #include "PostProcessorPhilipsStereo.hh"
46 
47 #include <ACG/GL/ScreenQuad.hh>
48 
51 
52 #include "CRC/crc32.hh"
53 
54 PostProcessorPhilipsStereoPlugin::PostProcessorPhilipsStereoPlugin():
55  pProgram_(0),
56  settingsWidget_(0)
57 {
58 
59 }
60 
62  return QString("Philips Stereo Display Output");
63 }
64 
65 QAction* PostProcessorPhilipsStereoPlugin::optionsAction() {
66  QAction* action = new QAction("Philips Stereo Options",0);
67  connect(action,SIGNAL(triggered()),this,SLOT(slotShowOptionsMenu()));
68  return action;
69 }
70 
71 
72 
73 QString PostProcessorPhilipsStereoPlugin::checkOpenGL() {
74  if ( ! ACG::openGLVersion(3, 0) )
75  return QString("Insufficient OpenGL Version! OpenGL 3.0 or higher required");
76 
77  // Check extensions
78  QString missing("");
79  if ( !ACG::checkExtensionSupported("GL_ARB_texture_rectangle") )
80  missing += "GL_ARB_texture_rectangle extension missing\n";
81 
82  return missing;
83 }
84 
85 //-----------------------------------------------------------------------------
86 
87 void PostProcessorPhilipsStereoPlugin::postProcess(ACG::GLState* _glstate, const std::vector<const PostProcessorInput*>& _input, const PostProcessorOutput& _output) {
88 
89  // load shader if needed
90  if (!pProgram_)
91  pProgram_ = GLSL::loadProgram("Philips/screenquad.glsl", "Philips/Fragment42.glsl");
92 
93  if (!pProgram_)
94  return;
95 
96  int vp_l, vp_b, vp_w, vp_h;
97  _glstate->get_viewport(vp_l, vp_b, vp_w, vp_h);
98 
99 
100  // Turn on shader program
101  pProgram_->use();
102 
103  // ======================================================================================================
104  // Bind textures to different texture units and tell shader where to find them
105  // ======================================================================================================
106  _input[0]->bindDepthTex(1);
107  _input[0]->bindColorTex(0);
108 
109  pProgram_->setUniform("ColorTexture", 0);
110  pProgram_->setUniform("DepthStencil", 1);
111 
112  // ======================================================================================================
113  // Setup render states
114  // ======================================================================================================
115 
116  glDisable(GL_LIGHTING);
117  glDisable(GL_COLOR_MATERIAL);
118  glDisable(GL_DEPTH_TEST);
119  glDisable(GL_BLEND);
120 
121  glDepthMask(1);
122  glColorMask(1,1,1,1);
123 
124  // ======================================================================================================
125  // Setup orthogonal projection
126  // ======================================================================================================
127  _glstate->push_projection_matrix();
128  _glstate->push_modelview_matrix();
129 
130  _glstate->reset_projection();
131  _glstate->reset_modelview();
132 
133  _glstate->ortho(0, vp_w, 0, vp_h, 0, 1);
134 
135  // ======================================================================================================
136  // Bind textures to different texture units and tell shader where to find them
137  // ======================================================================================================
138  glColor3f(1.0, 1.0, 1.0);
139 
140 
141  // ======================================================================================================
142  // Bind output FBO
143  // ======================================================================================================
144 
145  _output.bind();
146 
147  // ======================================================================================================
148  // Execute
149  // ======================================================================================================
150  ACG::ScreenQuad::draw(pProgram_);
151 
152 
153  pProgram_->disable();
154 
155  glBindTexture(GL_TEXTURE_2D, 0);
156 
157  // ======================================================================================================
158  // Compute the header required for the display
159  // ======================================================================================================
160  uchar *header = new uchar[6];
161 
162  // Header ID
163  // Basic identifier used by the display to verify the header
164  header[0] = 241; // Header_ID1 = 11110001
165 
166  // Header content type
167  // This entry controls the displays internal rendering based on the input data specified here.
168  // There is no info about how this changes the rendering
169  // Possible values:
170  // 0 No Depth
171  // 1 Signage
172  // 2 Movie
173  // 3 Game
174  // 4 CGI
175  // 5 Still
176  header[1] = OpenFlipperSettings().value("Core/Stereo/Philips/Content",3).toInt(); // Hdr_Content_type (Game) = 00000011 (Gaming Mode)
177 
178  // Header Factor
179  // Each 3D Display has a 'Display recommended depth value', which corresponds to an
180  // acceptable maximum depth factor value for that specific type of display. This value strongly
181  // depends on the lens design. The factor field in the header contains the percentage to be
182  // used from the display recommended depth value. The value of 64 corresponds with the 100%
183  // of the display recommended depth value. It is allowed to use values higher than 64. The factor
184  // works on a linear scale and is multiplied with the factor controlled by the user in the Display
185  // Control Tool.
186  // Value range: 0-255 (default 64)
187  header[2] = OpenFlipperSettings().value("Core/Stereo/Philips/Factor",64).toInt(); // Hdr_Factor
188 
189  // Header Offset CC
190  // Values in the Depth map equal to the header-offset value will be located on the plane of the
191  // display. All values in the disparity map with a higher value will de displayed in front of the
192  // display.
193  // Offset_CC is the offset controlled by the Content Creator. In the system there is also an
194  // Offset_user present, which is controlled by the user using the Display Control Tool.
195  // Value Range: 0-255 (default 128)
196  header[3] = OpenFlipperSettings().value("Core/Stereo/Philips/Offset",128).toInt(); // Hdr_Offset_CC
197 
198  // Header select
199  // When all select signals are low the rendering settings are set to optimal settings for the content
200  // type denoted by Hdr_content_type. By making select signals high the settings for Factor and
201  // Offset_cc can be controlled individually by the header.
202  // Possible Values:
203  // 0 Use Displays defaults and automatic optimizations
204  // 1 Use Header provided factor
205  // 2 Use Header provided offset
206  // 3 Use both factor and offset
207  header[4] = OpenFlipperSettings().value("Core/Stereo/Philips/Select",0).toInt(); // Hdr_Factor_select(1) + Hdr_Offset_select(1) + reserved(6)
208 
209  // Unused Header entry (leave at 0 !)
210  header[5] = 0; // Reserved
211 
212  // Header checksum.
213  // The 4-byte EDC field H(6) − H(9) contains an Error Detection Code computed over the first 6
214  // header bytes. This EDC uses the standard CRC-32 polynomial as defined in IEEE 802.3 and ITU-T
215  // V.42. The initial value and final XOR value are both 0.
216  // unsigned long has 32bit = 4Byte
217  unsigned long checksum = CalcCRC32(&header[0], 6);
218 
219  // Store the complete header in a bit vector
220  std::vector<uchar> bitVector;
221 
222  // For all bytes of the header
223  for (int i = 0; i < 6; i++) {
224 
225  // For each bit of a headers byte
226  for (int j = 7; j >= 0; --j) {
227 
228  // Red and Green component have to be 0
229  bitVector.push_back(0);
230  bitVector.push_back(0);
231 
232  // If bit is set, the full component will be set to one otherwise zero
233  // And the order of the bits has to be reversed!
234  if (header[i] & (1 << j)) {
235  bitVector.push_back(255);
236  } else {
237  bitVector.push_back(0);
238  }
239 
240  // Only every second pixel is used for the header
241  // Skip every odd one by filling in 0 for RGB
242  bitVector.push_back(0);
243  bitVector.push_back(0);
244  bitVector.push_back(0);
245  }
246  }
247 
248  // Append checksum to header.
249  // Reversed bit order!
250  for (int i = 31; i >= 0; i--) {
251 
252  // Red and Green component have to be 0
253  bitVector.push_back(0);
254  bitVector.push_back(0);
255 
256  if (checksum & (1 << i))
257  bitVector.push_back(255);
258  else
259  bitVector.push_back(0);
260 
261  // Only every second pixel is used for the header
262  // Skip every odd one by filling in 0 for RGB
263  bitVector.push_back(0);
264  bitVector.push_back(0);
265  bitVector.push_back(0);
266  }
267 
268  // Select the top left of the renderbuffer and
269  // write complete header into these bits
270 // glRasterPos2i(0, _glstate->context_height() - 1);
271  glRasterPos2i(_output.viewport_[0], _output.viewport_[1] + _output.height - 1);
272  glDrawPixels(bitVector.size() / 3, 1, GL_RGB, GL_UNSIGNED_BYTE, &bitVector[0]);
273 
274  // ======================================================================================================
275  // Reset projection and modelview
276  // ======================================================================================================
277  _glstate->pop_projection_matrix();
278  _glstate->pop_modelview_matrix();
279 
280 
281 }
282 
283 
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
void reset_modelview()
reset modelview matrix (load identity)
Definition: GLState.cc:370
void push_projection_matrix()
push projection matrix
Definition: GLState.cc:971
void ortho(double _left, double _right, double _bottom, double _top, double _near_plane, double _far_plane)
orthographic projection
Definition: GLState.cc:402
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:816
QString postProcessorName()
announce name for the postProcessor function
void reset_projection()
reset projection matrix (load identity)
Definition: GLState.cc:334
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:138
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1076
void pop_projection_matrix()
pop projection matrix
Definition: GLState.cc:989
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:107
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129