1/*=========================================================================
2
3Program:   Visualization Toolkit
4Module:    vtkIOSRenderWindow.mm
5
6Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7All rights reserved.
8See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10This software is distributed WITHOUT ANY WARRANTY; without even
11the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12PURPOSE.  See the above copyright notice for more information.
13
14=========================================================================*/
15
16#include "vtkOpenGLRenderWindow.h"
17
18#import "vtkIOSRenderWindow.h"
19#import "vtkRenderWindowInteractor.h"
20#import "vtkCommand.h"
21#import "vtkIdList.h"
22#import "vtkObjectFactory.h"
23#import "vtkRendererCollection.h"
24#import "vtkIOSGLView.h"
25
26#import <vtksys/ios/sstream>
27
28vtkStandardNewMacro(vtkIOSRenderWindow);
29
30
31//----------------------------------------------------------------------------
32vtkIOSRenderWindow::vtkIOSRenderWindow()
33{
34  this->WindowCreated = 0;
35  this->ViewCreated = 0;
36  this->SetWindowName("Visualization Toolkit - IOS");
37  this->CursorHidden = 0;
38  this->ForceMakeCurrent = 0;
39  this->Capabilities = 0;
40  this->OnScreenInitialized = 0;
41  this->OffScreenInitialized = 0;
42}
43
44//----------------------------------------------------------------------------
45vtkIOSRenderWindow::~vtkIOSRenderWindow()
46{
47  if (this->CursorHidden)
48    {
49    this->ShowCursor();
50    }
51  this->Finalize();
52
53  vtkRenderer *ren;
54  vtkCollectionSimpleIterator rit;
55  this->Renderers->InitTraversal(rit);
56  while ( (ren = this->Renderers->GetNextRenderer(rit)) )
57    {
58    ren->SetRenderWindow(NULL);
59    }
60
61  delete[] this->Capabilities;
62  this->Capabilities = 0;
63
64  this->SetContextId(NULL);
65  this->SetPixelFormat(NULL);
66  this->SetRootWindow(NULL);
67  this->SetWindowId(NULL);
68  this->SetParentId(NULL);
69
70}
71
72//----------------------------------------------------------------------------
73void vtkIOSRenderWindow::Finalize()
74{
75  if(this->OffScreenInitialized)
76    {
77    this->OffScreenInitialized = 0;
78    this->DestroyOffScreenWindow();
79    }
80  if(this->OnScreenInitialized)
81    {
82    this->OnScreenInitialized = 0;
83    this->DestroyWindow();
84    }
85}
86
87//----------------------------------------------------------------------------
88void vtkIOSRenderWindow::DestroyWindow()
89{
90  // finish OpenGL rendering
91  if (this->OwnContext && this->GetContextId())
92    {
93    this->MakeCurrent();
94
95    // tell each of the renderers that this render window/graphics context
96    // is being removed (the RendererCollection is removed by vtkRenderWindow's
97    // destructor)
98    vtkCollectionSimpleIterator rsit;
99    vtkRenderer *ren;
100    for ( this->Renderers->InitTraversal(rsit);
101          (ren = this->Renderers->GetNextRenderer(rsit));)
102      {
103      ren->SetRenderWindow(NULL);
104      ren->SetRenderWindow(this);
105      }
106  }
107  this->SetContextId(NULL);
108  this->SetPixelFormat(NULL);
109
110  this->SetWindowId(NULL);
111  this->SetParentId(NULL);
112  this->SetRootWindow(NULL);
113}
114
115//----------------------------------------------------------------------------
116void vtkIOSRenderWindow::SetWindowName( const char * _arg )
117{
118  vtkWindow::SetWindowName(_arg);
119}
120
121//----------------------------------------------------------------------------
122bool vtkIOSRenderWindow::InitializeFromCurrentContext()
123{
124  // NSOpenGLContext *currentContext = [NSOpenGLContext currentContext];
125  // if (currentContext != NULL)
126  //   {
127  //   UIView *currentView = [currentContext view];
128  //   if (currentView != NULL)
129  //     {
130  //     UIWindow *window = [currentView window];
131  //     this->SetWindowId(currentView);
132  //     this->SetRootWindow(window);
133  //     this->SetContextId((void*)currentContext);
134  //     this->OpenGLInit();
135  //     this->OwnContext = 0;
136  //     return true;
137  //     }
138  //   }
139  return false;
140}
141
142//----------------------------------------------------------------------------
143int vtkIOSRenderWindow::GetEventPending()
144{
145  return 0;
146}
147
148//----------------------------------------------------------------------------
149// Initialize the rendering process.
150void vtkIOSRenderWindow::Start()
151{
152  this->Initialize();
153
154  // set the current window
155  this->MakeCurrent();
156}
157
158//----------------------------------------------------------------------------
159void vtkIOSRenderWindow::MakeCurrent()
160{
161  // if (this->GetContextId())
162  //   {
163  //   [(NSOpenGLContext*)this->GetContextId() makeCurrentContext];
164  //   }
165}
166
167// ----------------------------------------------------------------------------
168// Description:
169// Tells if this window is the current OpenGL context for the calling thread.
170bool vtkIOSRenderWindow::IsCurrent()
171{
172  return true;
173}
174
175//----------------------------------------------------------------------------
176bool vtkIOSRenderWindow::IsDrawable()
177{
178  // you must initialize it first
179  // else it always evaluates false
180  this->Initialize();
181
182  return true;
183}
184
185//----------------------------------------------------------------------------
186void vtkIOSRenderWindow::UpdateContext()
187{
188}
189
190//----------------------------------------------------------------------------
191const char* vtkIOSRenderWindow::ReportCapabilities()
192{
193  this->MakeCurrent();
194
195  const char* glVendor = (const char*) glGetString(GL_VENDOR);
196  const char* glRenderer = (const char*) glGetString(GL_RENDERER);
197  const char* glVersion = (const char*) glGetString(GL_VERSION);
198  const char* glExtensions = (const char*) glGetString(GL_EXTENSIONS);
199
200  vtksys_ios::ostringstream strm;
201  strm << "OpenGL vendor string:  " << glVendor
202       << "\nOpenGL renderer string:  " << glRenderer
203       << "\nOpenGL version string:  " << glVersion
204       << "\nOpenGL extensions:  " << glExtensions << endl;
205
206  delete[] this->Capabilities;
207
208  size_t len = strm.str().length() + 1;
209  this->Capabilities = new char[len];
210  strlcpy(this->Capabilities, strm.str().c_str(), len);
211
212  return this->Capabilities;
213}
214
215//----------------------------------------------------------------------------
216int vtkIOSRenderWindow::SupportsOpenGL()
217{
218  this->MakeCurrent();
219  if (!this->GetContextId() || !this->GetPixelFormat())
220    {
221    return 0;
222    }
223  return 1;
224}
225
226//----------------------------------------------------------------------------
227int vtkIOSRenderWindow::IsDirect()
228{
229  this->MakeCurrent();
230  if (!this->GetContextId() || !this->GetPixelFormat())
231    {
232    return 0;
233    }
234  return 1;
235}
236
237//----------------------------------------------------------------------------
238void vtkIOSRenderWindow::SetSize(int* a)
239{
240  this->SetSize( a[0], a[1] );
241}
242
243//----------------------------------------------------------------------------
244void vtkIOSRenderWindow::SetSize(int x, int y)
245{
246  static int resizing = 0;
247
248  if ((this->Size[0] != x) || (this->Size[1] != y) || (this->GetParentId()))
249    {
250    this->Modified();
251    this->Size[0] = x;
252    this->Size[1] = y;
253    }
254}
255
256//----------------------------------------------------------------------------
257void vtkIOSRenderWindow::SetForceMakeCurrent()
258{
259  this->ForceMakeCurrent = 1;
260}
261
262//----------------------------------------------------------------------------
263void vtkIOSRenderWindow::SetPosition(int* a)
264{
265  this->SetPosition( a[0], a[1] );
266}
267
268//----------------------------------------------------------------------------
269void vtkIOSRenderWindow::SetPosition(int x, int y)
270{
271  static int resizing = 0;
272
273  if ((this->Position[0] != x) || (this->Position[1] != y)
274      || (this->GetParentId()))
275    {
276    this->Modified();
277    this->Position[0] = x;
278    this->Position[1] = y;
279    }
280}
281
282//----------------------------------------------------------------------------
283// End the rendering process and display the image.
284void vtkIOSRenderWindow::Frame()
285{
286  this->MakeCurrent();
287
288  if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
289    {
290//    [(NSOpenGLContext*)this->GetContextId() flushBuffer];
291    }
292   else
293    {
294    glFlush();
295    }
296}
297
298//----------------------------------------------------------------------------
299// Update system if needed due to stereo rendering.
300void vtkIOSRenderWindow::StereoUpdate()
301{
302  // if stereo is on and it wasn't before
303  if (this->StereoRender && (!this->StereoStatus))
304    {
305    switch (this->StereoType)
306      {
307      case VTK_STEREO_CRYSTAL_EYES:
308        this->StereoStatus = 1;
309        break;
310      case VTK_STEREO_RED_BLUE:
311        this->StereoStatus = 1;
312        break;
313      case VTK_STEREO_ANAGLYPH:
314        this->StereoStatus = 1;
315        break;
316      case VTK_STEREO_DRESDEN:
317        this->StereoStatus = 1;
318        break;
319      case VTK_STEREO_INTERLACED:
320        this->StereoStatus = 1;
321        break;
322      case VTK_STEREO_CHECKERBOARD:
323        this->StereoStatus = 1;
324        break;
325      case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
326        this->StereoStatus = 1;
327        break;
328      }
329    }
330  else if ((!this->StereoRender) && this->StereoStatus)
331    {
332    switch (this->StereoType)
333      {
334      case VTK_STEREO_CRYSTAL_EYES:
335        this->StereoStatus = 0;
336        break;
337      case VTK_STEREO_RED_BLUE:
338        this->StereoStatus = 0;
339        break;
340      case VTK_STEREO_ANAGLYPH:
341        this->StereoStatus = 0;
342        break;
343      case VTK_STEREO_DRESDEN:
344        this->StereoStatus = 0;
345        break;
346      case VTK_STEREO_INTERLACED:
347        this->StereoStatus = 0;
348        break;
349      case VTK_STEREO_CHECKERBOARD:
350        this->StereoStatus = 0;
351        break;
352      case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
353        this->StereoStatus = 0;
354        break;
355      }
356    }
357}
358
359//----------------------------------------------------------------------------
360// Specify various window parameters.
361void vtkIOSRenderWindow::WindowConfigure()
362{
363  // this is all handled by the desiredVisualInfo method
364}
365
366//----------------------------------------------------------------------------
367void vtkIOSRenderWindow::SetupPixelFormat(void*, void*, int, int, int)
368{
369  vtkErrorMacro(<< "vtkIOSRenderWindow::SetupPixelFormat - IMPLEMENT");
370}
371
372//----------------------------------------------------------------------------
373void vtkIOSRenderWindow::SetupPalette(void*)
374{
375  vtkErrorMacro(<< "vtkIOSRenderWindow::SetupPalette - IMPLEMENT");
376}
377
378//----------------------------------------------------------------------------
379// Initialize the window for rendering.
380void vtkIOSRenderWindow::CreateAWindow()
381{
382  static unsigned count = 1;
383
384  this->CreateGLContext();
385
386  this->MakeCurrent();
387
388  // wipe out any existing display lists
389  vtkRenderer *renderer = NULL;
390  vtkCollectionSimpleIterator rsit;
391
392  for ( this->Renderers->InitTraversal(rsit);
393        (renderer = this->Renderers->GetNextRenderer(rsit));)
394    {
395    renderer->SetRenderWindow(0);
396    renderer->SetRenderWindow(this);
397    }
398  this->OpenGLInit();
399  this->Mapped = 1;
400}
401
402//----------------------------------------------------------------------------
403void vtkIOSRenderWindow::CreateGLContext()
404{
405}
406
407//----------------------------------------------------------------------------
408// Initialize the rendering window.
409void vtkIOSRenderWindow::Initialize ()
410{
411}
412
413//-----------------------------------------------------------------------------
414void vtkIOSRenderWindow::DestroyOffScreenWindow()
415{
416}
417
418//----------------------------------------------------------------------------
419// Get the current size of the window.
420int *vtkIOSRenderWindow::GetSize()
421{
422  // if we aren't mapped then just return the ivar
423  if (!this->Mapped)
424    {
425    return this->Superclass::GetSize();
426    }
427
428  return this->Superclass::GetSize();
429}
430
431//----------------------------------------------------------------------------
432// Get the current size of the screen in pixels.
433int *vtkIOSRenderWindow::GetScreenSize()
434{
435  return this->Size;
436}
437
438//----------------------------------------------------------------------------
439// Get the position in screen coordinates of the window.
440int *vtkIOSRenderWindow::GetPosition()
441{
442  return this->Position;
443}
444
445//----------------------------------------------------------------------------
446// Change the window to fill the entire screen.
447void vtkIOSRenderWindow::SetFullScreen(int arg)
448{
449}
450
451//----------------------------------------------------------------------------
452//
453// Set the variable that indicates that we want a stereo capable window
454// be created. This method can only be called before a window is realized.
455//
456void vtkIOSRenderWindow::SetStereoCapableWindow(int capable)
457{
458  if (this->GetContextId() == 0)
459    {
460    vtkRenderWindow::SetStereoCapableWindow(capable);
461    }
462  else
463    {
464    vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
465                    << "before the window is realized, i.e. before a render.");
466    }
467}
468
469//----------------------------------------------------------------------------
470// Set the preferred window size to full screen.
471void vtkIOSRenderWindow::PrefFullScreen()
472{
473  int *size = this->GetScreenSize();
474  vtkWarningMacro(<< "Can only set FullScreen before showing window: "
475                  << size[0] << 'x' << size[1] << ".");
476}
477
478//----------------------------------------------------------------------------
479// Remap the window.
480void vtkIOSRenderWindow::WindowRemap()
481{
482  vtkWarningMacro(<< "Can't remap the window.");
483  // Acquire the display and capture the screen.
484  // Create the full-screen window.
485  // Add the context.
486}
487
488//----------------------------------------------------------------------------
489void vtkIOSRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
490{
491  this->Superclass::PrintSelf(os,indent);
492
493  os << indent << "MultiSamples: " << this->MultiSamples << endl;
494  os << indent << "RootWindow (UIWindow): " << this->GetRootWindow() << endl;
495  os << indent << "WindowId (UIView): " << this->GetWindowId() << endl;
496  os << indent << "ParentId: " << this->GetParentId() << endl;
497  os << indent << "ContextId: " << this->GetContextId() << endl;
498  os << indent << "PixelFormat: " << this->GetPixelFormat() << endl;
499  os << indent << "WindowCreated: " << (this->WindowCreated ? "Yes" : "No") << endl;
500  os << indent << "ViewCreated: " << (this->ViewCreated ? "Yes" : "No") << endl;
501}
502
503//----------------------------------------------------------------------------
504int vtkIOSRenderWindow::GetDepthBufferSize()
505{
506  if ( this->Mapped )
507    {
508    GLint size = 0;
509    glGetIntegerv( GL_DEPTH_BITS, &size );
510    return (int) size;
511    }
512  else
513    {
514    vtkDebugMacro(<< "Window is not mapped yet!" );
515    return 24;
516    }
517}
518
519//----------------------------------------------------------------------------
520// Returns the UIWindow* associated with this vtkRenderWindow.
521void *vtkIOSRenderWindow::GetRootWindow()
522{
523  return NULL;
524}
525
526//----------------------------------------------------------------------------
527// Sets the UIWindow* associated with this vtkRenderWindow.
528void vtkIOSRenderWindow::SetRootWindow(void *vtkNotUsed(arg))
529{
530}
531
532//----------------------------------------------------------------------------
533// Returns the UIView* associated with this vtkRenderWindow.
534void *vtkIOSRenderWindow::GetWindowId()
535{
536  return NULL;
537}
538
539//----------------------------------------------------------------------------
540// Sets the UIView* associated with this vtkRenderWindow.
541void vtkIOSRenderWindow::SetWindowId(void *vtkNotUsed(arg))
542{
543}
544
545//----------------------------------------------------------------------------
546// Returns the UIView* that is the parent of this vtkRenderWindow.
547void *vtkIOSRenderWindow::GetParentId()
548{
549  return NULL;
550}
551
552//----------------------------------------------------------------------------
553// Sets the UIView* that this vtkRenderWindow should use as a parent.
554void vtkIOSRenderWindow::SetParentId(void *vtkNotUsed(arg))
555{
556}
557
558//----------------------------------------------------------------------------
559// Sets the NSOpenGLContext* associated with this vtkRenderWindow.
560void vtkIOSRenderWindow::SetContextId(void *vtkNotUsed(contextId))
561{
562}
563
564//----------------------------------------------------------------------------
565// Returns the NSOpenGLContext* associated with this vtkRenderWindow.
566void *vtkIOSRenderWindow::GetContextId()
567{
568  return NULL;
569}
570
571//----------------------------------------------------------------------------
572// Sets the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
573void vtkIOSRenderWindow::SetPixelFormat(void *vtkNotUsed(pixelFormat))
574{
575}
576
577//----------------------------------------------------------------------------
578// Returns the NSOpenGLPixelFormat* associated with this vtkRenderWindow.
579void *vtkIOSRenderWindow::GetPixelFormat()
580{
581  return NULL;
582}
583
584
585//----------------------------------------------------------------------------
586void vtkIOSRenderWindow::SetWindowInfo(char *info)
587{
588  // The paramater is an ASCII string of a decimal number representing
589  // a pointer to the window. Convert it back to a pointer.
590  ptrdiff_t tmp = 0;
591  if (info)
592    {
593    (void)sscanf(info, "%tu", &tmp);
594    }
595
596  this->SetWindowId (reinterpret_cast<void *>(tmp));
597}
598
599//----------------------------------------------------------------------------
600void vtkIOSRenderWindow::SetParentInfo(char *info)
601{
602  // The paramater is an ASCII string of a decimal number representing
603  // a pointer to the window. Convert it back to a pointer.
604  ptrdiff_t tmp = 0;
605  if (info)
606    {
607    (void)sscanf(info, "%tu", &tmp);
608    }
609
610  this->SetParentId (reinterpret_cast<void *>(tmp));
611}
612
613//----------------------------------------------------------------------------
614void vtkIOSRenderWindow::HideCursor()
615{
616  if (this->CursorHidden)
617    {
618    return;
619    }
620  this->CursorHidden = 1;
621}
622
623//----------------------------------------------------------------------------
624void vtkIOSRenderWindow::ShowCursor()
625{
626  if (!this->CursorHidden)
627    {
628    return;
629    }
630  this->CursorHidden = 0;
631}
632
633// ---------------------------------------------------------------------------
634int vtkIOSRenderWindow::GetWindowCreated()
635{
636  return this->WindowCreated;
637}
638
639//----------------------------------------------------------------------------
640void vtkIOSRenderWindow::SetCursorPosition(int x, int y)
641{
642}
643
644//----------------------------------------------------------------------------
645void vtkIOSRenderWindow::SetCurrentCursor(int shape)
646{
647  if (this->InvokeEvent(vtkCommand::CursorChangedEvent, &shape))
648    {
649    return;
650    }
651  this->Superclass::SetCurrentCursor(shape);
652}
653