1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkEGLRenderWindow.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkEGLRenderWindow.h"
17 
18 #include "vtkCommand.h"
19 #include "vtkIdList.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkOpenGLRenderer.h"
22 #include "vtkRenderWindowInteractor.h"
23 #include "vtkRendererCollection.h"
24 #include "vtkType.h"
25 #include "vtk_glew.h"
26 #include "vtksys/SystemTools.hxx"
27 
28 #include <EGL/egl.h>
29 #include <atomic>
30 #include <cassert>
31 #include <sstream>
32 
33 #if defined(__ANDROID__) || defined(ANDROID)
34 #include <android/native_window.h>
35 #include <vtkAndroidRenderWindowInteractor.h>
36 #endif
37 
38 namespace
39 {
40 typedef void* EGLDeviceEXT;
41 typedef EGLBoolean (*EGLQueryDevicesType)(EGLint, EGLDeviceEXT*, EGLint*);
42 typedef EGLDisplay (*EGLGetPlatformDisplayType)(EGLenum, void*, const EGLint*);
43 const EGLenum EGL_PLATFORM_DEVICE_EXT = 0x313F;
44 
45 /**
46  * EGLDisplay provided by eglGetDisplay() call can be same handle for multiple
47  * instances of vtkEGLRenderWindow. In which case, while it's safe to call
48  * eglInitialize() repeatedly, eglTerminate() should only be called once after
49  * the final instance of the window is destroyed. This class helps us do
50  * that. See paraview/paraview#16928.
51  */
52 class vtkEGLDisplayInitializationHelper
53 {
54   static std::map<EGLDisplay, std::atomic<int64_t>> DisplayUsageCounts;
55 
56 public:
Initialize(EGLDisplay dpy,EGLint * major,EGLint * minor)57   static EGLBoolean Initialize(EGLDisplay dpy, EGLint* major, EGLint* minor)
58   {
59     ++DisplayUsageCounts[dpy];
60     return eglInitialize(dpy, major, minor);
61   }
Terminate(EGLDisplay dpy)62   static EGLBoolean Terminate(EGLDisplay dpy)
63   {
64     assert(DisplayUsageCounts.find(dpy) != DisplayUsageCounts.end());
65     if (--DisplayUsageCounts[dpy] == 0)
66     {
67       DisplayUsageCounts.erase(dpy);
68       return eglTerminate(dpy);
69     }
70     return EGL_TRUE;
71   }
72 };
73 
74 std::map<EGLDisplay, std::atomic<int64_t>> vtkEGLDisplayInitializationHelper::DisplayUsageCounts;
75 
76 struct vtkEGLDeviceExtensions
77 {
GetInstance__anon939613e00111::vtkEGLDeviceExtensions78   static vtkEGLDeviceExtensions* GetInstance()
79   {
80     static vtkEGLDeviceExtensions* instance = nullptr;
81     if (instance == nullptr)
82     {
83       instance = new vtkEGLDeviceExtensions();
84     }
85     return instance;
86   }
Available__anon939613e00111::vtkEGLDeviceExtensions87   bool Available() { return this->Available_; }
88   bool Available_;
89   EGLQueryDevicesType eglQueryDevices;
90   EGLGetPlatformDisplayType eglGetPlatformDisplay;
91 
92 private:
vtkEGLDeviceExtensions__anon939613e00111::vtkEGLDeviceExtensions93   vtkEGLDeviceExtensions()
94   {
95     this->Available_ = false;
96     this->eglQueryDevices = nullptr;
97     this->eglGetPlatformDisplay = nullptr;
98     const char* s = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
99     if (s == nullptr)
100     {
101       // eglQueryString returns a nullptr upon failure.
102       // Setting it to empty string to silently ignore failure.
103       s = "";
104     }
105     std::string platformExtensions(s);
106     if (platformExtensions.find("EGL_EXT_device_base") != std::string::npos &&
107       platformExtensions.find("EGL_EXT_platform_device") != std::string::npos &&
108       platformExtensions.find("EGL_EXT_platform_base") != std::string::npos)
109     {
110       this->eglQueryDevices = (EGLQueryDevicesType)eglGetProcAddress("eglQueryDevicesEXT");
111       this->eglGetPlatformDisplay =
112         (EGLGetPlatformDisplayType)eglGetProcAddress("eglGetPlatformDisplayEXT");
113       if (this->eglQueryDevices && this->eglGetPlatformDisplay)
114       {
115         this->Available_ = true;
116       }
117     }
118   }
119 };
120 };
121 
122 vtkStandardNewMacro(vtkEGLRenderWindow);
123 
124 struct vtkEGLRenderWindow::vtkInternals
125 {
126   EGLNativeWindowType Window;
127   EGLDisplay Display;
128   EGLSurface Surface;
129   EGLContext Context;
vtkInternalsvtkEGLRenderWindow::vtkInternals130   vtkInternals()
131     : Window((EGLNativeWindowType)0)
132     , Display(EGL_NO_DISPLAY)
133     , Surface(EGL_NO_SURFACE)
134     , Context(EGL_NO_CONTEXT)
135   {
136   }
137 };
138 
vtkEGLRenderWindow()139 vtkEGLRenderWindow::vtkEGLRenderWindow()
140 {
141   this->Internals = new vtkInternals();
142   this->OwnWindow = true;
143   this->ScreenSize[0] = 1920;
144   this->ScreenSize[1] = 1080;
145 
146   // this is initialized in vtkRenderWindow
147   // so we don't need to initialize on else
148 #ifdef VTK_USE_OFFSCREEN_EGL
149   this->DeviceIndex = VTK_DEFAULT_EGL_DEVICE_INDEX;
150   this->ShowWindow = false;
151 #endif
152 
153   // Use an environment variable to set the default device index
154   char* EGLDefaultDeviceIndexEnv = std::getenv("VTK_DEFAULT_EGL_DEVICE_INDEX");
155   if (EGLDefaultDeviceIndexEnv)
156   {
157     // If parsing the environment variable fails and throws an exception we
158     // can safely ignore it since a default is already set above.
159     try
160     {
161       this->DeviceIndex = atoi(EGLDefaultDeviceIndexEnv);
162     }
163     catch (const std::out_of_range&)
164     {
165     }
166     catch (const std::invalid_argument&)
167     {
168     }
169   }
170 
171   this->IsPointSpriteBugTested = false;
172   this->IsPointSpriteBugPresent_ = false;
173 }
174 
175 // free up memory & close the window
~vtkEGLRenderWindow()176 vtkEGLRenderWindow::~vtkEGLRenderWindow()
177 {
178   // close-down all system-specific drawing resources
179   this->Finalize();
180 
181   vtkRenderer* ren;
182   vtkCollectionSimpleIterator rit;
183   this->Renderers->InitTraversal(rit);
184   while ((ren = this->Renderers->GetNextRenderer(rit)))
185   {
186     ren->SetRenderWindow(nullptr);
187   }
188   delete this->Internals;
189 }
190 
191 // End the rendering process and display the image.
Frame()192 void vtkEGLRenderWindow::Frame()
193 {
194   vtkInternals* impl = this->Internals;
195   this->MakeCurrent();
196   this->Superclass::Frame();
197   if (this->OwnWindow)
198   {
199     if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers &&
200       impl->Display != EGL_NO_DISPLAY)
201     {
202       eglSwapBuffers(impl->Display, impl->Surface);
203       glFinish();
204       vtkDebugMacro(<< " eglSwapBuffers\n");
205     }
206   }
207   else
208   {
209     if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
210     {
211       eglSwapBuffers(eglGetCurrentDisplay(), eglGetCurrentSurface(EGL_DRAW));
212       glFinish();
213       vtkDebugMacro(<< " eglSwapBuffers\n");
214     }
215   }
216 }
217 
218 //
219 // Set the variable that indicates that we want a stereo capable window
220 // be created. This method can only be called before a window is realized.
221 //
SetStereoCapableWindow(vtkTypeBool capable)222 void vtkEGLRenderWindow::SetStereoCapableWindow(vtkTypeBool capable)
223 {
224   vtkInternals* impl = this->Internals;
225   if (impl->Display == EGL_NO_DISPLAY)
226   {
227     vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
228   }
229   else
230   {
231     vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
232                     << "before the window is realized, i.e. before a render.");
233   }
234 }
235 
236 // Specify the size of the rendering window.
SetSize(int width,int height)237 void vtkEGLRenderWindow::SetSize(int width, int height)
238 {
239   this->Superclass::SetSize(width, height);
240   vtkInternals* impl = this->Internals;
241 
242   if (this->OwnWindow && impl->Display != EGL_NO_DISPLAY && impl->Surface != EGL_NO_SURFACE)
243   {
244     // We only need to resize the window if we own it
245     int w, h;
246     this->GetEGLSurfaceSize(&w, &h);
247     if (w != this->Size[0] || h != this->Size[1])
248     {
249       this->ResizeWindow(this->Size[0], this->Size[1]);
250     }
251   }
252 }
253 
CreateAWindow()254 void vtkEGLRenderWindow::CreateAWindow()
255 {
256   int s[2];
257   if (this->Size[0] != 0 && this->Size[1] != 0)
258   {
259     s[0] = this->Size[0];
260     s[1] = this->Size[1];
261   }
262   else
263   {
264     s[0] = this->ScreenSize[0];
265     s[1] = this->ScreenSize[1];
266   }
267   this->ResizeWindow(s[0], s[1]);
268 }
269 
GetNumberOfDevices()270 int vtkEGLRenderWindow::GetNumberOfDevices()
271 {
272   vtkEGLDeviceExtensions* ext = vtkEGLDeviceExtensions::GetInstance();
273   if (ext->Available())
274   {
275     EGLint num_devices = 0;
276     ext->eglQueryDevices(num_devices, nullptr, &num_devices);
277     return num_devices;
278   }
279   vtkWarningMacro(
280     "Getting the number of devices (graphics cards) on a system require "
281     "EGL_EXT_device_base, EGL_EXT_platform_device and EGL_EXT_platform_base extensions");
282   return 0;
283 }
284 
SetDeviceAsDisplay(int deviceIndex)285 void vtkEGLRenderWindow::SetDeviceAsDisplay(int deviceIndex)
286 {
287   vtkInternals* impl = this->Internals;
288   vtkEGLDeviceExtensions* ext = vtkEGLDeviceExtensions::GetInstance();
289   if (ext->Available())
290   {
291     EGLint num_devices = 0;
292     ext->eglQueryDevices(num_devices, nullptr, &num_devices);
293     if (deviceIndex >= num_devices)
294     {
295       vtkWarningMacro("EGL device index: " << deviceIndex
296                                            << " is greater than "
297                                               "the number of supported deviced in the system: "
298                                            << num_devices << ". Using device 0 ...");
299       return;
300     }
301     EGLDeviceEXT* devices = new EGLDeviceEXT[num_devices];
302     ext->eglQueryDevices(num_devices, devices, &num_devices);
303     impl->Display =
304       ext->eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, devices[deviceIndex], nullptr);
305     delete[] devices;
306     return;
307   }
308   vtkWarningMacro("Setting an EGL display to device index: "
309     << deviceIndex
310     << " require "
311        "EGL_EXT_device_base EGL_EXT_platform_device EGL_EXT_platform_base extensions");
312 }
313 
SetShowWindow(bool val)314 void vtkEGLRenderWindow::SetShowWindow(bool val)
315 {
316   if (val == this->ShowWindow)
317   {
318     return;
319   }
320 
321 #if defined(VTK_USE_OFFSCREEN_EGL)
322   if (!val)
323   {
324     this->Superclass::SetShowWindow(val);
325   }
326 #else
327   this->Superclass::SetShowWindow(val);
328 #endif
329 }
330 
ResizeWindow(int width,int height)331 void vtkEGLRenderWindow::ResizeWindow(int width, int height)
332 {
333   vtkInternals* impl = this->Internals;
334   /*
335    * Here specify the attributes of the desired configuration.
336    * Below, we select an EGLConfig with at least 8 bits per color
337    * component compatible with on-screen windows
338    */
339   EGLint surfaceType, clientAPI;
340   const EGLint* contextAttribs;
341 #if defined(__ANDROID__) || defined(ANDROID)
342   surfaceType = EGL_WINDOW_BIT;
343   clientAPI = EGL_OPENGL_ES2_BIT;
344   const EGLint contextES2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
345   contextAttribs = contextES2;
346 #else
347   // arguably you could have EGL_WINDOW_BIT here as well
348   surfaceType = EGL_PBUFFER_BIT;
349   clientAPI = EGL_OPENGL_BIT;
350   contextAttribs = nullptr;
351 #endif
352 
353   const EGLint configs[] = { EGL_SURFACE_TYPE, surfaceType, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
354     EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_RENDERABLE_TYPE, clientAPI,
355     EGL_NONE };
356 
357 #if !defined(__ANDROID__) && !defined(ANDROID)
358   const EGLint surface_attribs[] = { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE };
359 #endif
360 
361   EGLint numConfigs = 0;
362   EGLConfig config;
363 
364   if (impl->Display == EGL_NO_DISPLAY)
365   {
366     // eglGetDisplay(EGL_DEFAULT_DISPLAY) does not seem to work
367     // if there are several cards on a system.
368     this->SetDeviceAsDisplay(this->DeviceIndex);
369 
370     // try to use the default display
371     if (impl->Display == EGL_NO_DISPLAY)
372     {
373       impl->Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
374     }
375 
376     EGLint major = 0, minor = 0;
377     vtkEGLDisplayInitializationHelper::Initialize(impl->Display, &major, &minor);
378 #if !defined(__ANDROID__) && !defined(ANDROID)
379     if (major <= 1 && minor < 4)
380     {
381       vtkErrorMacro("Only EGL 1.4 and greater allows OpenGL as client API. "
382                     "See eglBindAPI for more information.");
383       return;
384     }
385     eglBindAPI(EGL_OPENGL_API);
386 #endif
387   }
388 
389   /* Here, the application chooses the configuration it desires. In this
390    * sample, we have a very simplified selection process, where we pick
391    * the first EGLConfig that matches our criteria */
392   eglChooseConfig(impl->Display, configs, &config, 1, &numConfigs);
393   if (numConfigs == 0)
394   {
395     vtkErrorMacro("No matching EGL configuration found.");
396     return;
397   }
398 
399 #if defined(__ANDROID__) || defined(ANDROID)
400   EGLint format = 0;
401   /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
402    * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
403    * As soon as we picked a EGLConfig, we can safely reconfigure the
404    * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
405   eglGetConfigAttrib(impl->Display, config, EGL_NATIVE_VISUAL_ID, &format);
406 
407   ANativeWindow_setBuffersGeometry(impl->Window, 0, 0, format);
408 #endif
409 
410   if (impl->Context == EGL_NO_CONTEXT)
411   {
412     impl->Context = eglCreateContext(impl->Display, config, EGL_NO_CONTEXT, contextAttribs);
413   }
414 
415   if (impl->Surface != EGL_NO_SURFACE)
416   {
417     eglDestroySurface(impl->Display, impl->Surface);
418   }
419 
420 #if defined(__ANDROID__) || defined(ANDROID)
421   impl->Surface = eglCreateWindowSurface(impl->Display, config, impl->Window, nullptr);
422 #else
423   impl->Surface = eglCreatePbufferSurface(impl->Display, config, surface_attribs);
424 #endif
425   this->Mapped = this->ShowWindow;
426   this->OwnWindow = true;
427 
428 #if defined(__ANDROID__) || defined(ANDROID)
429   vtkAndroidRenderWindowInteractor* interactor =
430     vtkAndroidRenderWindowInteractor::SafeDownCast(this->Interactor);
431   if (interactor)
432   {
433     interactor->SetOwnWindow(this->OwnWindow);
434   }
435 #endif
436 
437   this->MakeCurrent();
438 
439   EGLint w, h;
440   eglQuerySurface(impl->Display, impl->Surface, EGL_WIDTH, &w);
441   eglQuerySurface(impl->Display, impl->Surface, EGL_HEIGHT, &h);
442   this->Size[0] = w;
443   this->Size[1] = h;
444 }
445 
DestroyWindow()446 void vtkEGLRenderWindow::DestroyWindow()
447 {
448   vtkInternals* impl = this->Internals;
449   this->ReleaseGraphicsResources(this);
450   if (this->OwnWindow && impl->Display != EGL_NO_DISPLAY)
451   {
452     // make sure all other code knows we're not mapped anymore
453     this->Mapped = 0;
454     eglMakeCurrent(impl->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
455     if (impl->Context != EGL_NO_CONTEXT)
456     {
457       eglDestroyContext(impl->Display, impl->Context);
458       impl->Context = EGL_NO_CONTEXT;
459     }
460     if (impl->Surface != EGL_NO_SURFACE)
461     {
462       eglDestroySurface(impl->Display, impl->Surface);
463       impl->Surface = EGL_NO_SURFACE;
464     }
465     vtkEGLDisplayInitializationHelper::Terminate(impl->Display);
466     impl->Display = EGL_NO_DISPLAY;
467   }
468 }
469 
470 // Initialize the window for rendering.
WindowInitialize(void)471 void vtkEGLRenderWindow::WindowInitialize(void)
472 {
473   vtkInternals* impl = this->Internals;
474   if (this->OwnWindow)
475   {
476     this->CreateAWindow();
477   }
478   else if (impl->Context == EGL_NO_CONTEXT)
479   {
480     // Get our current context from the EGL current context
481     impl->Context = eglGetCurrentContext();
482   }
483 
484   this->MakeCurrent();
485 
486   // tell our renderers about us
487   vtkRenderer* ren;
488   for (this->Renderers->InitTraversal(); (ren = this->Renderers->GetNextItem());)
489   {
490     ren->SetRenderWindow(0);
491     ren->SetRenderWindow(this);
492   }
493 
494   this->OpenGLInit();
495 
496   // for offscreen EGL always turn on point sprites
497 #if !defined(__ANDROID__) && !defined(ANDROID) && defined(GL_POINT_SPRITE)
498   glEnable(GL_POINT_SPRITE);
499 #endif
500 
501 #if defined(__ANDROID__) || defined(ANDROID)
502   vtkAndroidRenderWindowInteractor* interactor =
503     vtkAndroidRenderWindowInteractor::SafeDownCast(this->Interactor);
504   if (interactor)
505   {
506     interactor->SetOwnWindow(this->OwnWindow);
507   }
508 #endif
509 }
510 
511 // Initialize the rendering window.
Initialize(void)512 void vtkEGLRenderWindow::Initialize(void)
513 {
514   vtkInternals* impl = this->Internals;
515   if (impl->Context == EGL_NO_CONTEXT)
516   {
517     this->WindowInitialize();
518   }
519   this->Initialized = true;
520 }
521 
Finalize(void)522 void vtkEGLRenderWindow::Finalize(void)
523 {
524   // clean and destroy window
525   this->DestroyWindow();
526 }
527 
528 // Change the window to fill the entire screen.
SetFullScreen(vtkTypeBool vtkNotUsed (arg))529 void vtkEGLRenderWindow::SetFullScreen(vtkTypeBool vtkNotUsed(arg))
530 {
531   // window is always full screen
532 }
533 
534 // Set the preferred window size to full screen.
PrefFullScreen()535 void vtkEGLRenderWindow::PrefFullScreen()
536 {
537   // don't show borders
538   this->Borders = 0;
539 }
540 
541 // Resize the window.
WindowRemap()542 void vtkEGLRenderWindow::WindowRemap()
543 {
544   // shut everything down
545   this->Finalize();
546 
547   // set everything up again
548   this->Initialize();
549 }
550 
GetEGLSurfaceSize(int * width,int * height)551 void vtkEGLRenderWindow::GetEGLSurfaceSize(int* width, int* height)
552 {
553   vtkInternals* impl = this->Internals;
554   if (impl->Display != EGL_NO_DISPLAY && impl->Surface != EGL_NO_SURFACE)
555   {
556     EGLint w, h;
557     eglQuerySurface(impl->Display, impl->Surface, EGL_WIDTH, &w);
558     eglQuerySurface(impl->Display, impl->Surface, EGL_HEIGHT, &h);
559     *width = w;
560     *height = h;
561   }
562   else
563   {
564     *width = 0;
565     *height = 0;
566   }
567 }
568 
PrintSelf(ostream & os,vtkIndent indent)569 void vtkEGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
570 {
571   vtkInternals* impl = this->Internals;
572   this->Superclass::PrintSelf(os, indent);
573 
574   os << indent << "Context: " << impl->Context << "\n";
575   os << indent << "Display: " << impl->Display << "\n";
576   os << indent << "Surface: " << impl->Surface << "\n";
577 }
578 
MakeCurrent()579 void vtkEGLRenderWindow::MakeCurrent()
580 {
581   vtkInternals* impl = this->Internals;
582   if (impl->Display != EGL_NO_DISPLAY && impl->Context != EGL_NO_CONTEXT &&
583     impl->Surface != EGL_NO_SURFACE)
584   {
585     if (eglMakeCurrent(impl->Display, impl->Surface, impl->Surface, impl->Context) == EGL_FALSE)
586     {
587       vtkWarningMacro("Unable to eglMakeCurrent: " << eglGetError());
588       return;
589     }
590   }
591 }
592 
ReleaseCurrent()593 void vtkEGLRenderWindow::ReleaseCurrent()
594 {
595   vtkInternals* impl = this->Internals;
596   if (impl->Display != EGL_NO_DISPLAY)
597   {
598     eglMakeCurrent(impl->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
599   }
600 }
601 
602 //------------------------------------------------------------------------------
603 // Description:
604 // Tells if this window is the current OpenGL context for the calling thread.
IsCurrent()605 bool vtkEGLRenderWindow::IsCurrent()
606 {
607   return true;
608 }
609 
610 // Get the size of the screen in pixels
GetScreenSize()611 int* vtkEGLRenderWindow::GetScreenSize()
612 {
613   // TODO: actually determine screensize.
614 
615   return this->ScreenSize;
616 }
617 
618 // Get the position in screen coordinates (pixels) of the window.
GetPosition(void)619 int* vtkEGLRenderWindow::GetPosition(void)
620 {
621   return this->Position;
622 }
623 
624 // Move the window to a new position on the display.
SetPosition(int x,int y)625 void vtkEGLRenderWindow::SetPosition(int x, int y)
626 {
627   if ((this->Position[0] != x) || (this->Position[1] != y))
628   {
629     this->Modified();
630   }
631   this->Position[0] = x;
632   this->Position[1] = y;
633 }
634 
635 // Set this RenderWindow to a pre-existing window.
SetWindowInfo(const char *)636 void vtkEGLRenderWindow::SetWindowInfo(const char*)
637 {
638   this->Mapped = 1;
639   this->OwnWindow = false;
640 
641 #if defined(__ANDROID__) || defined(ANDROID)
642   vtkAndroidRenderWindowInteractor* interactor =
643     vtkAndroidRenderWindowInteractor::SafeDownCast(this->Interactor);
644   if (interactor)
645   {
646     interactor->SetOwnWindow(this->OwnWindow);
647   }
648 #endif
649 }
650 
SetWindowName(const char * name)651 void vtkEGLRenderWindow::SetWindowName(const char* name)
652 {
653   vtkOpenGLRenderWindow::SetWindowName(name);
654 }
655 
Render()656 void vtkEGLRenderWindow::Render()
657 {
658   // Now do the superclass stuff
659   this->vtkOpenGLRenderWindow::Render();
660 }
661 
662 //------------------------------------------------------------------------------
HideCursor()663 void vtkEGLRenderWindow::HideCursor() {}
664 
665 //------------------------------------------------------------------------------
ShowCursor()666 void vtkEGLRenderWindow::ShowCursor() {}
667 
668 //------------------------------------------------------------------------------
GetGenericDisplayId()669 void* vtkEGLRenderWindow::GetGenericDisplayId()
670 {
671   vtkInternals* impl = this->Internals;
672   return impl->Display;
673 }
674 
675 //------------------------------------------------------------------------------
GetGenericContext()676 void* vtkEGLRenderWindow::GetGenericContext()
677 {
678   vtkInternals* impl = this->Internals;
679   return impl->Context;
680 }
681 
682 //------------------------------------------------------------------------------
IsPointSpriteBugPresent()683 bool vtkEGLRenderWindow::IsPointSpriteBugPresent()
684 {
685   // eventually we'll want to check with the NVIDIA EGL version to see if the
686   // point sprite bug is fixed but we don't know yet when it will be fixed
687   // but we do know that it's present in both the 355 and 358 drivers. for
688   // now do the safe thing and just assume the bug isn't fixed until we
689   // find a driver version where it is fixed.
690   this->IsPointSpriteBugTested = true;
691   this->IsPointSpriteBugPresent_ = true;
692   // if (! this->IsPointSpriteBugTested)
693   //   {
694   //   this->IsPointSpriteBugTested = true;
695   //   this->IsPointSpriteBugPresent_ =
696   //     (strcmp(reinterpret_cast<const char*>(glGetString(GL_VERSION)), "4.5.0 NVIDIA 355.11") ==
697   //     0) || (strcmp(reinterpret_cast<const char*>(glGetString(GL_VERSION)), "4.5.0 NVIDIA
698   //     358.16") == 0);
699   //   }
700   return this->IsPointSpriteBugPresent_;
701 }
702 
703 //------------------------------------------------------------------------------
SetWindowId(void * window)704 void vtkEGLRenderWindow::SetWindowId(void* window)
705 {
706   vtkInternals* impl = this->Internals;
707   impl->Window = reinterpret_cast<EGLNativeWindowType>(window);
708 }
709