vtkOpenGLHardwareSelector.cxx 10.8 KB
Newer Older
1
2
3
/*=========================================================================

  Program:   Visualization Toolkit
4
  Module:    vtkOpenGLHardwareSelector.cxx
5
6
7
8
9
10
11
12
13
14

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
#include "vtkOpenGLHardwareSelector.h"
16

Ken Martin's avatar
Ken Martin committed
17
#include "vtk_glew.h"
18

19
#include "vtkObjectFactory.h"
20
#include "vtkDataObject.h"
21
22
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
23
#include "vtkOpenGLRenderWindow.h"
24
25
26

#include "vtkOpenGLError.h"

Ken Martin's avatar
Ken Martin committed
27
28
29
30
31
//#define vtkOpenGLHardwareSelectorDEBUG
#ifdef vtkOpenGLHardwareSelectorDEBUG
#include "vtkPNMWriter.h"
#include "vtkImageImport.h"
#include "vtkNew.h"
32
33
#include <sstream>
#include "vtkWindows.h"  // OK on UNix etc
Ken Martin's avatar
Ken Martin committed
34
35
#endif

36
37
#define ID_OFFSET 1

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Define to print debug statements to the OpenGL CS stream (useful for e.g.
// apitrace debugging):
//#define ANNOTATE_STREAM

namespace
{
void annotate(const std::string &str)
{
#ifdef ANNOTATE_STREAM
  vtkOpenGLStaticCheckErrorMacro("Error before glDebug.")
  glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER,
                       GL_DEBUG_SEVERITY_NOTIFICATION,
                       0, str.size(), str.c_str());
  vtkOpenGLClearErrorMacro();
#else // ANNOTATE_STREAM
  (void)str;
#endif // ANNOTATE_STREAM
}
}

58
59
// Description:
// Internal state and helper methods.
60
class vtkOpenGLHardwareSelector::vtkInternals
61
62
{
public:
63
  vtkOpenGLRenderWindow *Context;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  bool MultisampleSupport;
  bool OriginalMultisample;
  bool OriginalBlending;

  vtkInternals() :
    Context(NULL),
    MultisampleSupport(false),
    OriginalMultisample(false),
    OriginalBlending(false)
    {}

  // Description:
  // Set the rendering context and load the required
  // extensions.
  void SetContext(vtkRenderWindow *context)
79
  {
80
    if (this->Context == context)
81
    {
82
      return;
83
    }
84
85
86
87
88
89
90
91
92
93

    if (context)
    {
      this->MultisampleSupport = (context->GetMultiSamples() > 0);
    }
    else
    {
      this->MultisampleSupport = false;
    }
    this->Context = static_cast<vtkOpenGLRenderWindow *>(context);
94
  }
95
96
97
98

  // Description:
  // Enable/disable multisampling.
  void EnableMultisampling(bool mode)
99
  {
100
    if (this->MultisampleSupport)
101
    {
102
#if GL_ES_VERSION_2_0 != 1
103
      if (mode)
104
      {
105
        glEnable(GL_MULTISAMPLE);
106
      }
107
      else
108
      {
109
        glDisable(GL_MULTISAMPLE);
110
      }
111
#endif
112
    }
113
  }
114
115
116
117

  // Description:
  // Check if multisample is enabled.
  bool QueryMultisampling()
118
  {
119
#if GL_ES_VERSION_2_0 != 1
120
    if (this->MultisampleSupport && glIsEnabled(GL_MULTISAMPLE))
121
    {
122
      return true;
123
    }
124
    else
125
    {
126
      return false;
127
    }
128
129
130
#else
    return false;
#endif
131
  }
132
133
134
135

  // Description:
  // Enable/Disable blending
  void EnableBlending(bool mode)
136
  {
137
    if (mode)
138
    {
139
      glEnable(GL_BLEND);
140
    }
141
    else
142
    {
143
144
      glDisable(GL_BLEND);
    }
145
  }
146
147
148
149

  // Description:
  // Check if blending is enabled.
  bool QueryBlending()
150
  {
151
    if (glIsEnabled(GL_BLEND))
152
    {
153
      return true;
154
    }
155
    else
156
    {
157
158
      return false;
    }
159
  }
160
161
162
};

//----------------------------------------------------------------------------
163
vtkStandardNewMacro(vtkOpenGLHardwareSelector);
164
165

//----------------------------------------------------------------------------
166
vtkOpenGLHardwareSelector::vtkOpenGLHardwareSelector()
167
{
168
169
  #ifdef vtkOpenGLHardwareSelectorDEBUG
  cerr << "=====vtkOpenGLHardwareSelector::vtkOpenGLHardwareSelector" << endl;
170
171
172
173
174
  #endif
  this->Internals = new vtkInternals;
}

//----------------------------------------------------------------------------
175
vtkOpenGLHardwareSelector::~vtkOpenGLHardwareSelector()
176
{
177
178
  #ifdef vtkOpenGLHardwareSelectorDEBUG
  cerr << "=====vtkOpenGLHardwareSelector::~vtkOpenGLHardwareSelector" << endl;
179
180
181
182
  #endif
  delete this->Internals;
}

183
184
185
186
187
//----------------------------------------------------------------------------
void vtkOpenGLHardwareSelector::PreCapturePass(int pass)
{
  annotate(std::string("Starting pass: ") +
           this->PassTypeToString(static_cast<PassTypes>(pass)));
188
189
190
191
192
193
194
195
196

  // Disable multisample, and blending
  vtkRenderWindow *rwin = this->Renderer->GetRenderWindow();
  this->Internals->SetContext(rwin);
  this->Internals->OriginalMultisample = this->Internals->QueryMultisampling();
  this->Internals->EnableMultisampling(false);

  this->Internals->OriginalBlending = this->Internals->QueryBlending();
  this->Internals->EnableBlending(false);
197
198
199
200
201
}

//----------------------------------------------------------------------------
void vtkOpenGLHardwareSelector::PostCapturePass(int pass)
{
202
203
204
  // Restore multisample, and blending.
  this->Internals->EnableMultisampling(this->Internals->OriginalMultisample);
  this->Internals->EnableBlending(this->Internals->OriginalBlending);
205
206
207
208
  annotate(std::string("Pass complete: ") +
           this->PassTypeToString(static_cast<PassTypes>(pass)));
}

209
//----------------------------------------------------------------------------
210
void vtkOpenGLHardwareSelector::BeginSelection()
211
{
212
  // render normally to set the zbuffer
213
  if (this->FieldAssociation == vtkDataObject::FIELD_ASSOCIATION_POINTS)
214
  {
215
    vtkRenderWindow *rwin = this->Renderer->GetRenderWindow();
216
217
218
219
220
221
222
223
224
    this->Internals->SetContext(rwin);

    // Disable multisample, and blending before writing the zbuffer
    this->Internals->OriginalMultisample = this->Internals->QueryMultisampling();
    this->Internals->EnableMultisampling(false);

    this->Internals->OriginalBlending = this->Internals->QueryBlending();
    this->Internals->EnableBlending(false);

225
226
227
    rwin->SwapBuffersOff();
    rwin->Render();
    this->Renderer->PreserveDepthBufferOn();
228
229
230
231

    // Restore multisample, and blending.
    this->Internals->EnableMultisampling(this->Internals->OriginalMultisample);
    this->Internals->EnableBlending(this->Internals->OriginalBlending);
232
  }
233

234
  return this->Superclass::BeginSelection();
235
236
}

Ken Martin's avatar
Ken Martin committed
237
238
239
240
241
242
243
244
245
246
247
248
249
//----------------------------------------------------------------------------
// just add debug output if compiled with vtkOpenGLHardwareSelectorDEBUG
void vtkOpenGLHardwareSelector::SavePixelBuffer(int passNo)
{
  this->Superclass::SavePixelBuffer(passNo);

#ifdef vtkOpenGLHardwareSelectorDEBUG

  vtkNew<vtkImageImport> ii;
  ii->SetImportVoidPointer(this->PixBuffer[passNo],1);
  ii->SetDataScalarTypeToUnsignedChar();
  ii->SetNumberOfScalarComponents(3);
  ii->SetDataExtent(this->Area[0], this->Area[2], this->Area[1], this->Area[3], 0, 0);
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  ii->SetWholeExtent(this->Area[0], this->Area[2], this->Area[1], this->Area[3], 0, 0);

  // change this to somewhere on your system
  // hardcoded as with MPI/parallel/client server it can be hard to
  // find these images sometimes.
  std::string fname = "C:/Users/ken.martin/Documents/pickbuffer_";

#if defined(_WIN32)
  std::ostringstream toString;
  toString.str("");
  toString.clear();
  toString << GetCurrentProcessId();
  fname += toString.str();
  fname += "_";
#endif
Ken Martin's avatar
Ken Martin committed
265
266
267
268
269
270
  fname += ('0'+passNo);
  fname += ".pnm";
  vtkNew<vtkPNMWriter> pw;
  pw->SetInputConnection(ii->GetOutputPort());
  pw->SetFileName(fname.c_str());
  pw->Write();
271
  cerr << "=====vtkOpenGLHardwareSelector wrote " << fname << "\n";
Ken Martin's avatar
Ken Martin committed
272
273
274
#endif
}

275
//----------------------------------------------------------------------------
276
void vtkOpenGLHardwareSelector::BeginRenderProp(vtkRenderWindow *)
277
{
278
279
  #ifdef vtkOpenGLHardwareSelectorDEBUG
  cerr << "=====vtkOpenGLHardwareSelector::BeginRenderProp" << endl;
280
281
282
283
284
  #endif

}

//----------------------------------------------------------------------------
285
void vtkOpenGLHardwareSelector::EndRenderProp(vtkRenderWindow *)
286
{
287
288
  #ifdef vtkOpenGLHardwareSelectorDEBUG
  cerr << "=====vtkOpenGLHardwareSelector::EndRenderProp" << endl;
289
290
291
292
  #endif
}

//----------------------------------------------------------------------------
293
void vtkOpenGLHardwareSelector::BeginRenderProp()
294
295
296
{
  this->InPropRender++;
  if (this->InPropRender != 1)
297
  {
298
    return;
299
  }
300
301
302
303
304
305
306

  // device specific prep
  vtkRenderWindow *renWin = this->Renderer->GetRenderWindow();
  this->BeginRenderProp(renWin);

  //cout << "In BeginRenderProp" << endl;
  if (this->CurrentPass == ACTOR_PASS)
307
  {
308
309
    int propid = this->PropID;
    if (propid >= 0xfffffe)
310
    {
311
312
313
      vtkErrorMacro("Too many props. Currently only " << 0xfffffe
        << " props are supported.");
      return;
314
    }
315
316
317
318
319
    float color[3];
    // Since 0 is reserved for nothing selected, we offset propid by 1.
    propid = propid + 1;
    vtkHardwareSelector::Convert(propid, color);
    this->SetPropColorValue(color);
320
  }
321
  else if (this->CurrentPass == PROCESS_PASS)
322
  {
323
324
325
326
    float color[3];
    // Since 0 is reserved for nothing selected, we offset propid by 1.
    vtkHardwareSelector::Convert(this->ProcessID + 1, color);
    this->SetPropColorValue(color);
327
  }
328
329
330
}

//----------------------------------------------------------------------------
331
void vtkOpenGLHardwareSelector::RenderCompositeIndex(unsigned int index)
332
333
334
{

  if (index > 0xffffff)
335
  {
336
337
    vtkErrorMacro("Indices > 0xffffff are not supported.");
    return;
338
  }
339
340
341
342

  index += ID_OFFSET;

  if (this->CurrentPass == COMPOSITE_INDEX_PASS)
343
  {
344
345
346
    float color[3];
    vtkHardwareSelector::Convert(static_cast<int>(0xffffff & index), color);
    this->SetPropColorValue(color);
347
  }
348
349
350
351
}

//----------------------------------------------------------------------------
// TODO: make inline
352
void vtkOpenGLHardwareSelector::RenderAttributeId(vtkIdType attribid)
353
354
{
  if (attribid < 0)
355
  {
356
357
    vtkErrorMacro("Invalid id: " << attribid);
    return;
358
  }
359
360
361
362
363

  this->MaxAttributeId = (attribid > this->MaxAttributeId)? attribid :
    this->MaxAttributeId;

  if (this->CurrentPass < ID_LOW24 || this->CurrentPass > ID_HIGH16)
364
  {
365
    return;
366
  }
367
368
369
370
371

  // 0 is reserved.
  attribid += ID_OFFSET;

  for (int cc=0; cc < 3; cc++)
372
  {
373
374
375
    int words24 = (0xffffff & attribid);
    attribid = attribid >> 24;
    if ((this->CurrentPass - ID_LOW24) == cc)
376
    {
377
378
379
380
381
      float color[3];
      vtkHardwareSelector::Convert(words24, color);
      this->SetPropColorValue(color);
      break;
    }
382
  }
383
384
385
}

//----------------------------------------------------------------------------
386
void vtkOpenGLHardwareSelector::RenderProcessId(unsigned int processid)
387
388
{
  if (this->CurrentPass == PROCESS_PASS && this->UseProcessIdFromData)
389
  {
390
    if (processid >= 0xffffff)
391
    {
392
393
      vtkErrorMacro("Invalid id: " << processid);
      return;
394
    }
395
396
397
398
399

    float color[3];
    vtkHardwareSelector::Convert(
      static_cast<int>(processid + 1), color);
    this->SetPropColorValue(color);
400
  }
401
402
403
404
405
}



//----------------------------------------------------------------------------
406
void vtkOpenGLHardwareSelector::PrintSelf(ostream& os, vtkIndent indent)
407
408
409
410
411
412
413
{
  this->Superclass::PrintSelf(os, indent);
  os
   << indent << "MultisampleSupport: "
   << this->Internals->MultisampleSupport
   << endl;
}