[automerger skipped] DO NOT MERGE: Make the tests permissive for Lollipop MR1 am...
[platform/upstream/VK-GL-CTS.git] / framework / platform / android / tcuAndroidPlatform.cpp
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  * \file
21  * \brief Android EGL platform.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuAndroidPlatform.hpp"
25 #include "tcuAndroidUtil.hpp"
26 #include "gluRenderContext.hpp"
27 #include "egluNativeDisplay.hpp"
28 #include "egluNativeWindow.hpp"
29 #include "egluGLContextFactory.hpp"
30 #include "egluUtil.hpp"
31 #include "eglwLibrary.hpp"
32 #include "eglwEnums.hpp"
33 #include "tcuFunctionLibrary.hpp"
34 #include "vkWsiPlatform.hpp"
35
36 // Assume no call translation is needed
37 #include <android/native_window.h>
38 struct egl_native_pixmap_t;
39 DE_STATIC_ASSERT(sizeof(eglw::EGLNativeDisplayType) == sizeof(void*));
40 DE_STATIC_ASSERT(sizeof(eglw::EGLNativePixmapType) == sizeof(struct egl_native_pixmap_t*));
41 DE_STATIC_ASSERT(sizeof(eglw::EGLNativeWindowType) == sizeof(ANativeWindow*));
42
43 namespace tcu
44 {
45 namespace Android
46 {
47
48 using namespace eglw;
49
50 static const eglu::NativeDisplay::Capability    DISPLAY_CAPABILITIES    = eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY;
51 static const eglu::NativeWindow::Capability             WINDOW_CAPABILITIES             = (eglu::NativeWindow::Capability)(eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |
52                                                                                                                                                                                                                    eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |
53                                                                                                                                                                                                                    eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE);
54
55 class NativeDisplay : public eglu::NativeDisplay
56 {
57 public:
58                                                                         NativeDisplay                   (void) : eglu::NativeDisplay(DISPLAY_CAPABILITIES), m_library("libEGL.so") {}
59         virtual                                                 ~NativeDisplay                  (void) {}
60
61         virtual EGLNativeDisplayType    getLegacyNative                 (void)                  { return EGL_DEFAULT_DISPLAY;   }
62         virtual const eglw::Library&    getLibrary                              (void) const    { return m_library;                             }
63
64 private:
65         eglw::DefaultLibrary                    m_library;
66 };
67
68 class NativeDisplayFactory : public eglu::NativeDisplayFactory
69 {
70 public:
71                                                                         NativeDisplayFactory    (WindowRegistry& windowRegistry);
72                                                                         ~NativeDisplayFactory   (void) {}
73
74         virtual eglu::NativeDisplay*    createDisplay                   (const EGLAttrib* attribList) const;
75 };
76
77 class NativeWindow : public eglu::NativeWindow
78 {
79 public:
80                                                                         NativeWindow                    (Window* window, int width, int height, int32_t format);
81         virtual                                                 ~NativeWindow                   (void);
82
83         virtual EGLNativeWindowType             getLegacyNative                 (void)                  { return m_window->getNativeWindow();   }
84         IVec2                                                   getScreenSize                   (void) const    { return m_window->getSize();                   }
85
86         void                                                    setSurfaceSize                  (IVec2 size);
87
88         virtual void                                    processEvents                   (void);
89
90 private:
91         Window*                                                 m_window;
92         int32_t                                                 m_format;
93 };
94
95 class NativeWindowFactory : public eglu::NativeWindowFactory
96 {
97 public:
98                                                                         NativeWindowFactory             (WindowRegistry& windowRegistry);
99                                                                         ~NativeWindowFactory    (void);
100
101         virtual eglu::NativeWindow*             createWindow                    (eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const;
102         virtual eglu::NativeWindow*             createWindow                    (eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, const eglu::WindowParams& params) const;
103
104 private:
105         virtual eglu::NativeWindow*             createWindow                    (const eglu::WindowParams& params, int32_t format) const;
106
107         WindowRegistry&                                 m_windowRegistry;
108 };
109
110 // NativeWindow
111
112 NativeWindow::NativeWindow (Window* window, int width, int height, int32_t format)
113         : eglu::NativeWindow    (WINDOW_CAPABILITIES)
114         , m_window                              (window)
115         , m_format                              (format)
116 {
117         // Set up buffers.
118         setSurfaceSize(IVec2(width, height));
119 }
120
121 NativeWindow::~NativeWindow (void)
122 {
123         m_window->release();
124 }
125
126 void NativeWindow::processEvents (void)
127 {
128         if (m_window->isPendingDestroy())
129                 throw eglu::WindowDestroyedError("Window has been destroyed");
130 }
131
132 void NativeWindow::setSurfaceSize (tcu::IVec2 size)
133 {
134         m_window->setBuffersGeometry(size.x() != eglu::WindowParams::SIZE_DONT_CARE ? size.x() : 0,
135                                                                  size.y() != eglu::WindowParams::SIZE_DONT_CARE ? size.y() : 0,
136                                                                  m_format);
137 }
138
139 // NativeWindowFactory
140
141 NativeWindowFactory::NativeWindowFactory (WindowRegistry& windowRegistry)
142         : eglu::NativeWindowFactory     ("default", "Default display", WINDOW_CAPABILITIES)
143         , m_windowRegistry                      (windowRegistry)
144 {
145 }
146
147 NativeWindowFactory::~NativeWindowFactory (void)
148 {
149 }
150
151 eglu::NativeWindow* NativeWindowFactory::createWindow (eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const
152 {
153         DE_UNREF(nativeDisplay);
154         return createWindow(params, WINDOW_FORMAT_RGBA_8888);
155 }
156
157 eglu::NativeWindow* NativeWindowFactory::createWindow (eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, const eglu::WindowParams& params) const
158 {
159         const int32_t format = (int32_t)eglu::getConfigAttribInt(nativeDisplay->getLibrary(), display, config, EGL_NATIVE_VISUAL_ID);
160         DE_UNREF(nativeDisplay && attribList);
161         return createWindow(params, format);
162 }
163
164 eglu::NativeWindow* NativeWindowFactory::createWindow (const eglu::WindowParams& params, int32_t format) const
165 {
166         Window* window = m_windowRegistry.tryAcquireWindow();
167
168         if (!window)
169                 throw ResourceError("Native window is not available", DE_NULL, __FILE__, __LINE__);
170
171         return new NativeWindow(window, params.width, params.height, format);
172 }
173
174 // NativeDisplayFactory
175
176 NativeDisplayFactory::NativeDisplayFactory (WindowRegistry& windowRegistry)
177         : eglu::NativeDisplayFactory("default", "Default display", DISPLAY_CAPABILITIES)
178 {
179         m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(windowRegistry));
180 }
181
182 eglu::NativeDisplay* NativeDisplayFactory::createDisplay (const EGLAttrib* attribList) const
183 {
184         DE_UNREF(attribList);
185         return new NativeDisplay();
186 }
187
188 // Vulkan
189
190 class VulkanLibrary : public vk::Library
191 {
192 public:
193         VulkanLibrary (void)
194                 : m_library     ("libvulkan.so")
195                 , m_driver      (m_library)
196         {
197         }
198
199         const vk::PlatformInterface& getPlatformInterface (void) const
200         {
201                 return m_driver;
202         }
203
204 private:
205         const tcu::DynamicFunctionLibrary       m_library;
206         const vk::PlatformDriver                        m_driver;
207 };
208
209 DE_STATIC_ASSERT(sizeof(vk::pt::AndroidNativeWindowPtr) == sizeof(ANativeWindow*));
210
211 class VulkanWindow : public vk::wsi::AndroidWindowInterface
212 {
213 public:
214         VulkanWindow (tcu::Android::Window& window)
215                 : vk::wsi::AndroidWindowInterface       (vk::pt::AndroidNativeWindowPtr(window.getNativeWindow()))
216                 , m_window                                                      (window)
217         {
218         }
219
220         ~VulkanWindow (void)
221         {
222                 m_window.release();
223         }
224
225 private:
226         tcu::Android::Window&   m_window;
227 };
228
229 class VulkanDisplay : public vk::wsi::Display
230 {
231 public:
232         VulkanDisplay (WindowRegistry& windowRegistry)
233                 : m_windowRegistry(windowRegistry)
234         {
235         }
236
237         vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
238         {
239                 Window* const   window  = m_windowRegistry.tryAcquireWindow();
240
241                 if (window)
242                 {
243                         try
244                         {
245                                 if (initialSize)
246                                         window->setBuffersGeometry((int)initialSize->x(), (int)initialSize->y(), WINDOW_FORMAT_RGBA_8888);
247
248                                 return new VulkanWindow(*window);
249                         }
250                         catch (...)
251                         {
252                                 window->release();
253                                 throw;
254                         }
255                 }
256                 else
257                         TCU_THROW(ResourceError, "Native window is not available");
258         }
259
260 private:
261         WindowRegistry&         m_windowRegistry;
262 };
263
264 static size_t getTotalSystemMemory (ANativeActivity* activity)
265 {
266         const size_t    MiB             = (size_t)(1<<20);
267
268         try
269         {
270                 const size_t    cddRequiredSize = getCDDRequiredSystemMemory(activity);
271
272                 print("Device has at least %.2f MiB total system memory per Android CDD\n", double(cddRequiredSize) / double(MiB));
273
274                 return cddRequiredSize;
275         }
276         catch (const std::exception& e)
277         {
278                 // Use relatively high fallback size to encourage CDD-compliant behavior
279                 const size_t    fallbackSize    = (sizeof(void*) == sizeof(deUint64)) ? 2048*MiB : 1024*MiB;
280
281                 print("WARNING: Failed to determine system memory size required by CDD: %s\n", e.what());
282                 print("WARNING: Using fall-back size of %.2f MiB\n", double(fallbackSize) / double(MiB));
283
284                 return fallbackSize;
285         }
286 }
287
288 // Platform
289
290 Platform::Platform (NativeActivity& activity)
291         : m_activity                    (activity)
292         , m_totalSystemMemory   (getTotalSystemMemory(activity.getNativeActivity()))
293 {
294         m_nativeDisplayFactoryRegistry.registerFactory(new NativeDisplayFactory(m_windowRegistry));
295         m_contextFactoryRegistry.registerFactory(new eglu::GLContextFactory(m_nativeDisplayFactoryRegistry));
296 }
297
298 Platform::~Platform (void)
299 {
300 }
301
302 bool Platform::processEvents (void)
303 {
304         m_windowRegistry.garbageCollect();
305         return true;
306 }
307
308 vk::Library* Platform::createLibrary (void) const
309 {
310         return new VulkanLibrary();
311 }
312
313 void Platform::describePlatform (std::ostream& dst) const
314 {
315         tcu::Android::describePlatform(m_activity.getNativeActivity(), dst);
316 }
317
318 void Platform::getMemoryLimits (vk::PlatformMemoryLimits& limits) const
319 {
320         // Worst-case estimates
321         const size_t    MiB                             = (size_t)(1<<20);
322         const size_t    baseMemUsage    = 400*MiB;
323         const double    safeUsageRatio  = 0.25;
324
325         limits.totalSystemMemory                                        = de::max((size_t)(double(deInt64(m_totalSystemMemory)-deInt64(baseMemUsage)) * safeUsageRatio), 16*MiB);
326
327         // Assume UMA architecture
328         limits.totalDeviceLocalMemory                           = 0;
329
330         // Reasonable worst-case estimates
331         limits.deviceMemoryAllocationGranularity        = 64*1024;
332         limits.devicePageSize                                           = 4096;
333         limits.devicePageTableEntrySize                         = 8;
334         limits.devicePageTableHierarchyLevels           = 3;
335 }
336
337 vk::wsi::Display* Platform::createWsiDisplay (vk::wsi::Type wsiType) const
338 {
339         if (wsiType == vk::wsi::TYPE_ANDROID)
340                 return new VulkanDisplay(const_cast<WindowRegistry&>(m_windowRegistry));
341         else
342                 TCU_THROW(NotSupportedError, "WSI type not supported on Android");
343 }
344
345 } // Android
346 } // tcu