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