• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
3  * ----------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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 
21 #include "egluNativeDisplay.hpp"
22 
23 #include "tcuANGLENativeDisplayFactory.h"
24 
25 #include <EGL/egl.h>
26 #include <EGL/eglext.h>
27 
28 #include "deClock.h"
29 #include "deMemory.h"
30 #include "egluDefs.hpp"
31 #include "eglwLibrary.hpp"
32 #include "tcuTexture.hpp"
33 #include "util/OSPixmap.h"
34 #include "util/OSWindow.h"
35 
36 // clang-format off
37 #if (DE_OS == DE_OS_WIN32)
38     #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dll"
39 #elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_ANDROID)
40     #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".so"
41 #elif (DE_OS == DE_OS_OSX)
42     #define ANGLE_EGL_LIBRARY_FULL_NAME ANGLE_EGL_LIBRARY_NAME ".dylib"
43 #else
44     #error "Unsupported platform"
45 #endif
46 // clang-format on
47 
48 namespace tcu
49 {
50 namespace
51 {
52 
53 enum
54 {
55     DEFAULT_SURFACE_WIDTH  = 400,
56     DEFAULT_SURFACE_HEIGHT = 300,
57 };
58 
59 constexpr eglu::NativeDisplay::Capability kDisplayCapabilities =
60     static_cast<eglu::NativeDisplay::Capability>(
61         eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM |
62         eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM_EXT);
63 constexpr eglu::NativePixmap::Capability kBitmapCapabilities =
64     eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;
65 constexpr eglu::NativeWindow::Capability kWindowCapabilities =
66     static_cast<eglu::NativeWindow::Capability>(
67         eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |
68         eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE |
69         eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE |
70         eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS |
71         eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |
72         eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);
73 
74 class ANGLENativeDisplay : public eglu::NativeDisplay
75 {
76   public:
77     explicit ANGLENativeDisplay(std::vector<eglw::EGLAttrib> attribs);
78     ~ANGLENativeDisplay() override = default;
79 
getPlatformNative()80     void *getPlatformNative() override
81     {
82         // On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply
83         // use reinterpret_cast<void*>.
84         void *result = nullptr;
85         memcpy(&result, &mDeviceContext, sizeof(mDeviceContext));
86         return result;
87     }
getPlatformAttributes() const88     const eglw::EGLAttrib *getPlatformAttributes() const override
89     {
90         return &mPlatformAttributes[0];
91     }
getLibrary() const92     const eglw::Library &getLibrary() const override { return mLibrary; }
93 
getDeviceContext() const94     EGLNativeDisplayType getDeviceContext() const { return mDeviceContext; }
95 
96   private:
97     EGLNativeDisplayType mDeviceContext;
98     eglw::DefaultLibrary mLibrary;
99     std::vector<eglw::EGLAttrib> mPlatformAttributes;
100 };
101 
102 class NativePixmapFactory : public eglu::NativePixmapFactory
103 {
104   public:
105     NativePixmapFactory();
106     ~NativePixmapFactory() override = default;
107 
108     eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
109                                      int width,
110                                      int height) const override;
111     eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
112                                      eglw::EGLDisplay display,
113                                      eglw::EGLConfig config,
114                                      const eglw::EGLAttrib *attribList,
115                                      int width,
116                                      int height) const override;
117 };
118 
119 class NativePixmap : public eglu::NativePixmap
120 {
121   public:
122     NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth);
123     virtual ~NativePixmap();
124 
125     eglw::EGLNativePixmapType getLegacyNative() override;
126 
127   private:
128     OSPixmap *mPixmap;
129 };
130 
131 class NativeWindowFactory : public eglu::NativeWindowFactory
132 {
133   public:
134     explicit NativeWindowFactory(EventState *eventState);
135     ~NativeWindowFactory() override = default;
136 
137     eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
138                                      const eglu::WindowParams &params) const override;
139     eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
140                                      eglw::EGLDisplay display,
141                                      eglw::EGLConfig config,
142                                      const eglw::EGLAttrib *attribList,
143                                      const eglu::WindowParams &params) const override;
144 
145   private:
146     EventState *mEvents;
147 };
148 
149 class NativeWindow : public eglu::NativeWindow
150 {
151   public:
152     NativeWindow(ANGLENativeDisplay *nativeDisplay,
153                  const eglu::WindowParams &params,
154                  EventState *eventState);
155     ~NativeWindow() override;
156 
157     eglw::EGLNativeWindowType getLegacyNative() override;
158     IVec2 getSurfaceSize() const override;
getScreenSize() const159     IVec2 getScreenSize() const override { return getSurfaceSize(); }
160     void processEvents() override;
161     void setSurfaceSize(IVec2 size) override;
162     void setVisibility(eglu::WindowParams::Visibility visibility) override;
163     void readScreenPixels(tcu::TextureLevel *dst) const override;
164 
165   private:
166     OSWindow *mWindow;
167     EventState *mEvents;
168 };
169 
170 // ANGLE NativeDisplay
171 
ANGLENativeDisplay(std::vector<EGLAttrib> attribs)172 ANGLENativeDisplay::ANGLENativeDisplay(std::vector<EGLAttrib> attribs)
173     : eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
174       mDeviceContext(EGL_DEFAULT_DISPLAY),
175       mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME),
176       mPlatformAttributes(std::move(attribs))
177 {}
178 
179 // NativePixmap
180 
NativePixmap(EGLNativeDisplayType display,int width,int height,int bitDepth)181 NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth)
182     : eglu::NativePixmap(kBitmapCapabilities), mPixmap(CreateOSPixmap())
183 {
184 #if (DE_OS != DE_OS_UNIX)
185     throw tcu::NotSupportedError("Pixmap not supported");
186 #else
187     if (!mPixmap)
188     {
189         throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__);
190     }
191 
192     if (!mPixmap->initialize(display, width, height, bitDepth))
193     {
194         throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__);
195     }
196 #endif
197 }
198 
~NativePixmap()199 NativePixmap::~NativePixmap()
200 {
201     delete mPixmap;
202 }
203 
getLegacyNative()204 eglw::EGLNativePixmapType NativePixmap::getLegacyNative()
205 {
206     return reinterpret_cast<eglw::EGLNativePixmapType>(mPixmap->getNativePixmap());
207 }
208 
209 // NativePixmapFactory
210 
NativePixmapFactory()211 NativePixmapFactory::NativePixmapFactory()
212     : eglu::NativePixmapFactory("bitmap", "ANGLE Bitmap", kBitmapCapabilities)
213 {}
214 
createPixmap(eglu::NativeDisplay * nativeDisplay,eglw::EGLDisplay display,eglw::EGLConfig config,const eglw::EGLAttrib * attribList,int width,int height) const215 eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
216                                                       eglw::EGLDisplay display,
217                                                       eglw::EGLConfig config,
218                                                       const eglw::EGLAttrib *attribList,
219                                                       int width,
220                                                       int height) const
221 {
222     const eglw::Library &egl = nativeDisplay->getLibrary();
223     int redBits              = 0;
224     int greenBits            = 0;
225     int blueBits             = 0;
226     int alphaBits            = 0;
227     int bitSum               = 0;
228 
229     DE_ASSERT(display != EGL_NO_DISPLAY);
230 
231     egl.getConfigAttrib(display, config, EGL_RED_SIZE, &redBits);
232     egl.getConfigAttrib(display, config, EGL_GREEN_SIZE, &greenBits);
233     egl.getConfigAttrib(display, config, EGL_BLUE_SIZE, &blueBits);
234     egl.getConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaBits);
235     EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
236 
237     bitSum = redBits + greenBits + blueBits + alphaBits;
238 
239     return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
240                             width, height, bitSum);
241 }
242 
createPixmap(eglu::NativeDisplay * nativeDisplay,int width,int height) const243 eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
244                                                       int width,
245                                                       int height) const
246 {
247     const int defaultDepth = 32;
248     return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
249                             width, height, defaultDepth);
250 }
251 
252 // NativeWindowFactory
253 
NativeWindowFactory(EventState * eventState)254 NativeWindowFactory::NativeWindowFactory(EventState *eventState)
255     : eglu::NativeWindowFactory("window", "ANGLE Window", kWindowCapabilities), mEvents(eventState)
256 {}
257 
createWindow(eglu::NativeDisplay * nativeDisplay,const eglu::WindowParams & params) const258 eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
259                                                       const eglu::WindowParams &params) const
260 {
261     DE_ASSERT(DE_FALSE);
262     return nullptr;
263 }
264 
createWindow(eglu::NativeDisplay * nativeDisplay,eglw::EGLDisplay display,eglw::EGLConfig config,const eglw::EGLAttrib * attribList,const eglu::WindowParams & params) const265 eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
266                                                       eglw::EGLDisplay display,
267                                                       eglw::EGLConfig config,
268                                                       const eglw::EGLAttrib *attribList,
269                                                       const eglu::WindowParams &params) const
270 {
271     return new NativeWindow(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay), params, mEvents);
272 }
273 
274 // NativeWindow
275 
NativeWindow(ANGLENativeDisplay * nativeDisplay,const eglu::WindowParams & params,EventState * eventState)276 NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay,
277                            const eglu::WindowParams &params,
278                            EventState *eventState)
279     : eglu::NativeWindow(kWindowCapabilities), mWindow(OSWindow::New()), mEvents(eventState)
280 {
281     bool initialized = mWindow->initialize(
282         "dEQP ANGLE Tests",
283         params.width == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH : params.width,
284         params.height == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_HEIGHT
285                                                             : params.height);
286     TCU_CHECK(initialized);
287 
288     if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)
289         NativeWindow::setVisibility(params.visibility);
290 }
291 
setVisibility(eglu::WindowParams::Visibility visibility)292 void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)
293 {
294     switch (visibility)
295     {
296         case eglu::WindowParams::VISIBILITY_HIDDEN:
297             mWindow->setVisible(false);
298             break;
299 
300         case eglu::WindowParams::VISIBILITY_VISIBLE:
301         case eglu::WindowParams::VISIBILITY_FULLSCREEN:
302             mWindow->setVisible(true);
303             break;
304 
305         default:
306             DE_ASSERT(DE_FALSE);
307     }
308 }
309 
~NativeWindow()310 NativeWindow::~NativeWindow()
311 {
312     OSWindow::Delete(&mWindow);
313 }
314 
getLegacyNative()315 eglw::EGLNativeWindowType NativeWindow::getLegacyNative()
316 {
317     return reinterpret_cast<eglw::EGLNativeWindowType>(mWindow->getNativeWindow());
318 }
319 
getSurfaceSize() const320 IVec2 NativeWindow::getSurfaceSize() const
321 {
322     return IVec2(mWindow->getWidth(), mWindow->getHeight());
323 }
324 
processEvents()325 void NativeWindow::processEvents()
326 {
327     mWindow->messageLoop();
328 
329     // Look for a quit event to forward to the EventState
330     Event event = {};
331     while (mWindow->popEvent(&event))
332     {
333         if (event.Type == Event::EVENT_CLOSED)
334         {
335             mEvents->signalQuitEvent();
336         }
337     }
338 }
339 
setSurfaceSize(IVec2 size)340 void NativeWindow::setSurfaceSize(IVec2 size)
341 {
342     mWindow->resize(size.x(), size.y());
343 }
344 
readScreenPixels(tcu::TextureLevel * dst) const345 void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const
346 {
347     dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8),
348                     mWindow->getWidth(), mWindow->getHeight());
349     if (!mWindow->takeScreenshot(reinterpret_cast<uint8_t *>(dst->getAccess().getDataPtr())))
350     {
351         throw InternalError("Failed to read screen pixels", DE_NULL, __FILE__, __LINE__);
352     }
353 }
354 
355 }  // namespace
356 
ANGLENativeDisplayFactory(const std::string & name,const std::string & description,std::vector<eglw::EGLAttrib> platformAttributes,EventState * eventState)357 ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(
358     const std::string &name,
359     const std::string &description,
360     std::vector<eglw::EGLAttrib> platformAttributes,
361     EventState *eventState)
362     : eglu::NativeDisplayFactory(name,
363                                  description,
364                                  kDisplayCapabilities,
365                                  EGL_PLATFORM_ANGLE_ANGLE,
366                                  "EGL_EXT_platform_base"),
367       mPlatformAttributes(std::move(platformAttributes))
368 {
369     m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState));
370     m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
371 }
372 
373 ANGLENativeDisplayFactory::~ANGLENativeDisplayFactory() = default;
374 
createDisplay(const eglw::EGLAttrib * attribList) const375 eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(
376     const eglw::EGLAttrib *attribList) const
377 {
378     DE_UNREF(attribList);
379     return new ANGLENativeDisplay(mPlatformAttributes);
380 }
381 
382 }  // namespace tcu
383