• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright (c) 2024 NVIDIA CORPORATION.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief QNX Screen Platform implementation.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuQnxScreenPlatform.hpp"
25 
26 // Define pointers to libscreen functions
27 extern "C"
28 {
29     typedef int (*PFNSCREENCREATECONTEXT)(screen_context_t *, int);
30     typedef int (*PFNSCREENDESTROYCONTEXT)(screen_context_t);
31     typedef int (*PFNSCREENCREATEWINDOW)(screen_window_t *, screen_context_t);
32     typedef int (*PFNSCREENSETWINDOWPROPERTYIV)(screen_window_t, int, const int *);
33     typedef int (*PFNXSCREENCREATEWINDOWBUFFERS)(screen_window_t, int);
34     typedef int (*PFNSCREENDESTROYWINDOW)(screen_window_t);
35 };
36 
37 static PFNSCREENCREATECONTEXT pscreen_create_context               = NULL;
38 static PFNSCREENDESTROYCONTEXT pscreen_destroy_context             = NULL;
39 static PFNSCREENCREATEWINDOW pscreen_create_window                 = NULL;
40 static PFNSCREENSETWINDOWPROPERTYIV pscreen_set_window_property_iv = NULL;
41 static PFNXSCREENCREATEWINDOWBUFFERS pscreen_create_window_buffers = NULL;
42 static PFNSCREENDESTROYWINDOW pscreen_destroy_window               = NULL;
43 
44 static bool loadedLibscreen{false};
45 static screen_context_t screenContext{nullptr};
46 static void *libScreen{nullptr};
47 
createPlatform(void)48 tcu::Platform *createPlatform(void)
49 {
50     return new tcu::QnxScreen::Platform();
51 }
52 
53 namespace tcu
54 {
55 namespace QnxScreen
56 {
57 
58 enum
59 {
60     DEFAULT_WINDOW_WIDTH  = 400,
61     DEFAULT_WINDOW_HEIGHT = 300
62 };
63 
64 // Macro to load function pointers from library
65 #define LOAD_FUNC_PTR(lib, name, type)                                              \
66     do                                                                              \
67     {                                                                               \
68         p##name = (type)dlsym(lib, #name);                                          \
69         if (!p##name)                                                               \
70         {                                                                           \
71             throw ResourceError("Could not load required function from libscreen"); \
72         }                                                                           \
73     } while (0)
74 
DisplayFactory(void)75 DisplayFactory::DisplayFactory(void)
76     : eglu::NativeDisplayFactory("QNX", "QNX Screen Display", eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY)
77 {
78     m_nativeWindowRegistry.registerFactory(new WindowFactory());
79 }
80 
createDisplay(const eglw::EGLAttrib *) const81 eglu::NativeDisplay *DisplayFactory::createDisplay(const eglw::EGLAttrib *) const
82 {
83     return new Display();
84 }
85 
createWindow(eglu::NativeDisplay * display,const eglu::WindowParams & params) const86 eglu::NativeWindow *WindowFactory::createWindow(eglu::NativeDisplay *display, const eglu::WindowParams &params) const
87 {
88     const int width  = params.width != eglu::WindowParams::SIZE_DONT_CARE ? params.width : DEFAULT_WINDOW_WIDTH;
89     const int height = params.height != eglu::WindowParams::SIZE_DONT_CARE ? params.height : DEFAULT_WINDOW_HEIGHT;
90 
91     return new Window(display, width, height, NULL, NULL);
92 }
93 
createWindow(eglu::NativeDisplay * display,eglw::EGLDisplay eglDisplay,eglw::EGLConfig config,const eglw::EGLAttrib * attribList,const eglu::WindowParams & params) const94 eglu::NativeWindow *WindowFactory::createWindow(eglu::NativeDisplay *display, eglw::EGLDisplay eglDisplay,
95                                                 eglw::EGLConfig config, const eglw::EGLAttrib *attribList,
96                                                 const eglu::WindowParams &params) const
97 {
98     DE_UNREF(attribList);
99 
100     const int width  = params.width != eglu::WindowParams::SIZE_DONT_CARE ? params.width : DEFAULT_WINDOW_WIDTH;
101     const int height = params.height != eglu::WindowParams::SIZE_DONT_CARE ? params.height : DEFAULT_WINDOW_HEIGHT;
102 
103     return new Window(display, width, height, eglDisplay, config);
104 }
105 
LoadLibscreen(void)106 void Display::LoadLibscreen(void)
107 {
108     if (!loadedLibscreen)
109     {
110         if (!libScreen)
111         {
112             libScreen = dlopen("libscreen.so", RTLD_LAZY);
113             if (!libScreen)
114             {
115                 libScreen = dlopen("libscreen.so.1", RTLD_LAZY);
116             }
117             if (!libScreen)
118             {
119                 throw ResourceError("Could not find / open libscreen");
120             }
121         }
122         LOAD_FUNC_PTR(libScreen, screen_create_context, PFNSCREENCREATECONTEXT);
123         LOAD_FUNC_PTR(libScreen, screen_destroy_context, PFNSCREENDESTROYCONTEXT);
124         LOAD_FUNC_PTR(libScreen, screen_create_window, PFNSCREENCREATEWINDOW);
125         LOAD_FUNC_PTR(libScreen, screen_set_window_property_iv, PFNSCREENSETWINDOWPROPERTYIV);
126         LOAD_FUNC_PTR(libScreen, screen_create_window_buffers, PFNXSCREENCREATEWINDOWBUFFERS);
127         LOAD_FUNC_PTR(libScreen, screen_destroy_window, PFNSCREENDESTROYWINDOW);
128         loadedLibscreen = true;
129     }
130 }
131 
CreateScreenContext(void)132 void Display::CreateScreenContext(void)
133 {
134     if (!screenContext)
135     {
136         const int ret{pscreen_create_context(&screenContext, 0)};
137         if (ret)
138         {
139             throw ResourceError("Failed to create QNX Screen context");
140         }
141     }
142 }
143 
DestroyScreenContext(void)144 void Display::DestroyScreenContext(void)
145 {
146     if (screenContext)
147     {
148         pscreen_destroy_context(screenContext);
149         screenContext = nullptr;
150     }
151 }
152 
Display(void)153 Display::Display(void) : eglu::NativeDisplay(eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY), m_display(0)
154 {
155     try
156     {
157         LoadLibscreen();
158         CreateScreenContext();
159     }
160     catch (...)
161     {
162         if (loadedLibscreen)
163         {
164             DestroyScreenContext();
165         }
166         throw; // Re-throw caught exception
167     }
168 }
169 
~Display(void)170 Display::~Display(void)
171 {
172     DestroyScreenContext();
173 }
174 
Window(eglu::NativeDisplay * display,int width,int height,eglw::EGLDisplay eglDisplay,eglw::EGLConfig config)175 Window::Window(eglu::NativeDisplay *display, int width, int height, eglw::EGLDisplay eglDisplay, eglw::EGLConfig config)
176     : eglu::NativeWindow(eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY)
177     , m_screenWindow(nullptr)
178 {
179     // offset is 0
180     // sizeX and sizeY is width and height
181     eglw::EGLint abits{};
182     eglw::EGLint rbits{};
183     eglw::EGLint gbits{};
184     eglw::EGLint bbits{};
185 
186     display->getLibrary().getConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &abits);
187     display->getLibrary().getConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &rbits);
188     display->getLibrary().getConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &gbits);
189     display->getLibrary().getConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &bbits);
190 
191     try
192     {
193         int rc{pscreen_create_window(&m_screenWindow, screenContext)};
194         if (rc)
195         {
196             throw ResourceError("Failed to create QNX Screen window.");
197         }
198 
199         int screenFormat{};
200         if ((rbits == 8) && (gbits == 8) && (bbits == 8))
201         {
202             // RGB888. Check for alpha
203             if (abits == 8)
204             {
205                 screenFormat = SCREEN_FORMAT_RGBA8888;
206             }
207             else
208             {
209                 screenFormat = SCREEN_FORMAT_RGBX8888;
210             }
211         }
212         else if ((rbits == 5) && (gbits == 6) && (bbits == 5))
213         {
214             screenFormat = SCREEN_FORMAT_RGB565;
215         }
216         else if ((rbits == 4) && (gbits == 4) && (bbits == 4))
217         {
218             // RGB444. Check for alpha
219             if (abits == 4)
220             {
221                 screenFormat = SCREEN_FORMAT_RGBA4444;
222             }
223             else
224             {
225                 screenFormat = SCREEN_FORMAT_RGBX4444;
226             }
227         }
228         else if ((rbits == 5) && (gbits == 5) && (bbits == 5))
229         {
230             // RGB555. Check for alpha
231             if (abits == 1)
232             {
233                 screenFormat = SCREEN_FORMAT_RGBA5551;
234             }
235             else
236             {
237                 screenFormat = SCREEN_FORMAT_RGBX5551;
238             }
239         }
240         else
241         {
242             throw ResourceError("Unsupported SCREEN_PROPERTY_FORMAT requested");
243         }
244 
245         rc = pscreen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_FORMAT, (const int *)&screenFormat);
246         if (rc)
247         {
248             throw ResourceError("Failed to set SCREEN_PROPERTY_FORMAT");
249         }
250 
251         int usage{SCREEN_USAGE_OPENGL_ES2};
252         rc = pscreen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_USAGE, &usage);
253         if (rc)
254         {
255             throw ResourceError("Failed to set SCREEN_PROPERTY_USAGE");
256         }
257 
258         int interval{1};
259         rc = pscreen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_SWAP_INTERVAL, &interval);
260         if (rc)
261         {
262             throw ResourceError("Failed to set SCREEN_PROPERTY_SWAP_INTERVAL");
263         }
264 
265         int size[]{width, height};
266         rc = pscreen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_SIZE, (const int *)size);
267         if (rc)
268         {
269             throw ResourceError("Failed to set SCREEN_PROPERTY_SIZE");
270         }
271 
272         int offset[]{0, 0};
273         rc = pscreen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_POSITION, offset);
274         if (rc)
275         {
276             throw ResourceError("Failed to set SCREEN_PROPERTY_POSITION");
277         }
278 
279         rc = pscreen_create_window_buffers(m_screenWindow, 2);
280         if (rc)
281         {
282             throw ResourceError("Failed to create QNX Screen window buffers");
283         }
284 
285         m_nativeWindow = (eglw::EGLNativeWindowType)(void *)m_screenWindow;
286     }
287     catch (...)
288     {
289         if (m_screenWindow)
290         {
291             pscreen_destroy_window(m_screenWindow);
292             m_screenWindow = nullptr;
293         }
294         throw;
295     }
296 }
297 
~Window(void)298 Window::~Window(void)
299 {
300     if (m_screenWindow)
301     {
302         pscreen_destroy_window(m_screenWindow);
303         m_screenWindow = nullptr;
304     }
305 }
306 
Platform(void)307 Platform::Platform(void)
308 {
309     m_nativeDisplayFactoryRegistry.registerFactory(new DisplayFactory());
310     m_contextFactoryRegistry.registerFactory(new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
311 }
312 
~Platform(void)313 Platform::~Platform(void)
314 {
315     if (screenContext)
316     {
317         pscreen_destroy_context(screenContext);
318     }
319     screenContext = nullptr;
320 }
321 
322 } // namespace QnxScreen
323 } // namespace tcu
324