Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/deqp_support/tcuANGLENativeDisplayFactory.cpp
1693 views
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
#if defined(ANGLE_USE_X11)
49
# include <X11/Xlib.h>
50
#endif
51
52
namespace tcu
53
{
54
namespace
55
{
56
57
template <typename destType, typename sourceType>
58
destType bitCast(sourceType source)
59
{
60
constexpr size_t copySize =
61
sizeof(destType) < sizeof(sourceType) ? sizeof(destType) : sizeof(sourceType);
62
destType output(0);
63
memcpy(&output, &source, copySize);
64
return output;
65
}
66
67
enum
68
{
69
DEFAULT_SURFACE_WIDTH = 400,
70
DEFAULT_SURFACE_HEIGHT = 300,
71
};
72
73
constexpr eglu::NativeDisplay::Capability kDisplayCapabilities =
74
static_cast<eglu::NativeDisplay::Capability>(
75
eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM |
76
eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM_EXT);
77
constexpr eglu::NativePixmap::Capability kBitmapCapabilities =
78
eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;
79
constexpr eglu::NativeWindow::Capability kWindowCapabilities =
80
static_cast<eglu::NativeWindow::Capability>(
81
eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY |
82
eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE |
83
eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE |
84
eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS |
85
eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE |
86
eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);
87
88
class ANGLENativeDisplay : public eglu::NativeDisplay
89
{
90
public:
91
explicit ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<eglw::EGLAttrib> attribs);
92
~ANGLENativeDisplay() override = default;
93
94
void *getPlatformNative() override
95
{
96
// On OSX 64bits mDeviceContext is a 32 bit integer, so we can't simply
97
// use reinterpret_cast<void*>.
98
return bitCast<void *>(mDeviceContext);
99
}
100
const eglw::EGLAttrib *getPlatformAttributes() const override
101
{
102
return &mPlatformAttributes[0];
103
}
104
const eglw::Library &getLibrary() const override { return mLibrary; }
105
106
EGLNativeDisplayType getDeviceContext() const { return mDeviceContext; }
107
108
private:
109
EGLNativeDisplayType mDeviceContext;
110
eglw::DefaultLibrary mLibrary;
111
std::vector<eglw::EGLAttrib> mPlatformAttributes;
112
};
113
114
class NativePixmapFactory : public eglu::NativePixmapFactory
115
{
116
public:
117
NativePixmapFactory();
118
~NativePixmapFactory() override = default;
119
120
eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
121
int width,
122
int height) const override;
123
eglu::NativePixmap *createPixmap(eglu::NativeDisplay *nativeDisplay,
124
eglw::EGLDisplay display,
125
eglw::EGLConfig config,
126
const eglw::EGLAttrib *attribList,
127
int width,
128
int height) const override;
129
};
130
131
class NativePixmap : public eglu::NativePixmap
132
{
133
public:
134
NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth);
135
virtual ~NativePixmap();
136
137
eglw::EGLNativePixmapType getLegacyNative() override;
138
139
private:
140
OSPixmap *mPixmap;
141
};
142
143
class NativeWindowFactory : public eglu::NativeWindowFactory
144
{
145
public:
146
explicit NativeWindowFactory(EventState *eventState, uint32_t preRotation);
147
~NativeWindowFactory() override = default;
148
149
eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
150
const eglu::WindowParams &params) const override;
151
eglu::NativeWindow *createWindow(eglu::NativeDisplay *nativeDisplay,
152
eglw::EGLDisplay display,
153
eglw::EGLConfig config,
154
const eglw::EGLAttrib *attribList,
155
const eglu::WindowParams &params) const override;
156
157
private:
158
EventState *mEvents;
159
uint32_t mPreRotation;
160
};
161
162
class NativeWindow : public eglu::NativeWindow
163
{
164
public:
165
NativeWindow(ANGLENativeDisplay *nativeDisplay,
166
const eglu::WindowParams &params,
167
EventState *eventState,
168
uint32_t preRotation);
169
~NativeWindow() override;
170
171
eglw::EGLNativeWindowType getLegacyNative() override;
172
IVec2 getSurfaceSize() const override;
173
IVec2 getScreenSize() const override { return getSurfaceSize(); }
174
void processEvents() override;
175
void setSurfaceSize(IVec2 size) override;
176
void setVisibility(eglu::WindowParams::Visibility visibility) override;
177
void readScreenPixels(tcu::TextureLevel *dst) const override;
178
179
private:
180
OSWindow *mWindow;
181
EventState *mEvents;
182
uint32_t mPreRotation;
183
};
184
185
// ANGLE NativeDisplay
186
187
ANGLENativeDisplay::ANGLENativeDisplay(EGLNativeDisplayType display, std::vector<EGLAttrib> attribs)
188
: eglu::NativeDisplay(kDisplayCapabilities, EGL_PLATFORM_ANGLE_ANGLE, "EGL_EXT_platform_base"),
189
mDeviceContext(display),
190
mLibrary(ANGLE_EGL_LIBRARY_FULL_NAME),
191
mPlatformAttributes(std::move(attribs))
192
{}
193
194
// NativePixmap
195
196
NativePixmap::NativePixmap(EGLNativeDisplayType display, int width, int height, int bitDepth)
197
: eglu::NativePixmap(kBitmapCapabilities), mPixmap(CreateOSPixmap())
198
{
199
#if (DE_OS != DE_OS_UNIX)
200
throw tcu::NotSupportedError("Pixmap not supported");
201
#else
202
if (!mPixmap)
203
{
204
throw ResourceError("Failed to create pixmap", DE_NULL, __FILE__, __LINE__);
205
}
206
207
if (!mPixmap->initialize(display, width, height, bitDepth))
208
{
209
throw ResourceError("Failed to initialize pixmap", DE_NULL, __FILE__, __LINE__);
210
}
211
#endif
212
}
213
214
NativePixmap::~NativePixmap()
215
{
216
delete mPixmap;
217
}
218
219
eglw::EGLNativePixmapType NativePixmap::getLegacyNative()
220
{
221
return reinterpret_cast<eglw::EGLNativePixmapType>(mPixmap->getNativePixmap());
222
}
223
224
// NativePixmapFactory
225
226
NativePixmapFactory::NativePixmapFactory()
227
: eglu::NativePixmapFactory("bitmap", "ANGLE Bitmap", kBitmapCapabilities)
228
{}
229
230
eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
231
eglw::EGLDisplay display,
232
eglw::EGLConfig config,
233
const eglw::EGLAttrib *attribList,
234
int width,
235
int height) const
236
{
237
const eglw::Library &egl = nativeDisplay->getLibrary();
238
int nativeVisual = 0;
239
240
DE_ASSERT(display != EGL_NO_DISPLAY);
241
242
egl.getConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisual);
243
EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
244
245
return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
246
width, height, nativeVisual);
247
}
248
249
eglu::NativePixmap *NativePixmapFactory::createPixmap(eglu::NativeDisplay *nativeDisplay,
250
int width,
251
int height) const
252
{
253
const int defaultDepth = 32;
254
return new NativePixmap(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay)->getDeviceContext(),
255
width, height, defaultDepth);
256
}
257
258
// NativeWindowFactory
259
260
NativeWindowFactory::NativeWindowFactory(EventState *eventState, uint32_t preRotation)
261
: eglu::NativeWindowFactory("window", "ANGLE Window", kWindowCapabilities),
262
mEvents(eventState),
263
mPreRotation(preRotation)
264
{}
265
266
eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
267
const eglu::WindowParams &params) const
268
{
269
DE_ASSERT(DE_FALSE);
270
return nullptr;
271
}
272
273
eglu::NativeWindow *NativeWindowFactory::createWindow(eglu::NativeDisplay *nativeDisplay,
274
eglw::EGLDisplay display,
275
eglw::EGLConfig config,
276
const eglw::EGLAttrib *attribList,
277
const eglu::WindowParams &params) const
278
{
279
return new NativeWindow(dynamic_cast<ANGLENativeDisplay *>(nativeDisplay), params, mEvents,
280
mPreRotation);
281
}
282
283
// NativeWindow
284
285
NativeWindow::NativeWindow(ANGLENativeDisplay *nativeDisplay,
286
const eglu::WindowParams &params,
287
EventState *eventState,
288
uint32_t preRotation)
289
: eglu::NativeWindow(kWindowCapabilities),
290
mWindow(OSWindow::New()),
291
mEvents(eventState),
292
mPreRotation(preRotation)
293
{
294
int osWindowWidth =
295
params.width == eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH : params.width;
296
int osWindowHeight = params.height == eglu::WindowParams::SIZE_DONT_CARE
297
? DEFAULT_SURFACE_HEIGHT
298
: params.height;
299
300
if (mPreRotation == 90 || mPreRotation == 270)
301
{
302
std::swap(osWindowWidth, osWindowHeight);
303
}
304
305
bool initialized = mWindow->initialize("dEQP ANGLE Tests", osWindowWidth, osWindowHeight);
306
TCU_CHECK(initialized);
307
308
if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)
309
NativeWindow::setVisibility(params.visibility);
310
}
311
312
void NativeWindow::setVisibility(eglu::WindowParams::Visibility visibility)
313
{
314
switch (visibility)
315
{
316
case eglu::WindowParams::VISIBILITY_HIDDEN:
317
mWindow->setVisible(false);
318
break;
319
320
case eglu::WindowParams::VISIBILITY_VISIBLE:
321
case eglu::WindowParams::VISIBILITY_FULLSCREEN:
322
mWindow->setVisible(true);
323
break;
324
325
default:
326
DE_ASSERT(DE_FALSE);
327
}
328
}
329
330
NativeWindow::~NativeWindow()
331
{
332
OSWindow::Delete(&mWindow);
333
}
334
335
eglw::EGLNativeWindowType NativeWindow::getLegacyNative()
336
{
337
return reinterpret_cast<eglw::EGLNativeWindowType>(mWindow->getNativeWindow());
338
}
339
340
IVec2 NativeWindow::getSurfaceSize() const
341
{
342
int width = mWindow->getWidth();
343
int height = mWindow->getHeight();
344
345
if (mPreRotation == 90 || mPreRotation == 270)
346
{
347
// Return the original dimensions dEQP asked for. This ensures that the dEQP code is never
348
// aware of the window actually being rotated.
349
std::swap(width, height);
350
}
351
352
return IVec2(width, height);
353
}
354
355
void NativeWindow::processEvents()
356
{
357
mWindow->messageLoop();
358
359
// Look for a quit event to forward to the EventState
360
Event event = {};
361
while (mWindow->popEvent(&event))
362
{
363
if (event.Type == Event::EVENT_CLOSED)
364
{
365
mEvents->signalQuitEvent();
366
}
367
}
368
}
369
370
void NativeWindow::setSurfaceSize(IVec2 size)
371
{
372
int osWindowWidth = size.x();
373
int osWindowHeight = size.y();
374
375
if (mPreRotation == 90 || mPreRotation == 270)
376
{
377
std::swap(osWindowWidth, osWindowHeight);
378
}
379
380
mWindow->resize(osWindowWidth, osWindowHeight);
381
}
382
383
void NativeWindow::readScreenPixels(tcu::TextureLevel *dst) const
384
{
385
dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8),
386
mWindow->getWidth(), mWindow->getHeight());
387
if (!mWindow->takeScreenshot(reinterpret_cast<uint8_t *>(dst->getAccess().getDataPtr())))
388
{
389
throw InternalError("Failed to read screen pixels", DE_NULL, __FILE__, __LINE__);
390
}
391
392
if (mPreRotation != 0)
393
{
394
throw InternalError("Read screen pixels with prerotation is not supported", DE_NULL,
395
__FILE__, __LINE__);
396
}
397
}
398
399
} // namespace
400
401
ANGLENativeDisplayFactory::ANGLENativeDisplayFactory(
402
const std::string &name,
403
const std::string &description,
404
std::vector<eglw::EGLAttrib> platformAttributes,
405
EventState *eventState)
406
: eglu::NativeDisplayFactory(name,
407
description,
408
kDisplayCapabilities,
409
EGL_PLATFORM_ANGLE_ANGLE,
410
"EGL_EXT_platform_base"),
411
mNativeDisplay(bitCast<eglw::EGLNativeDisplayType>(EGL_DEFAULT_DISPLAY)),
412
mPlatformAttributes(std::move(platformAttributes))
413
{
414
#if (DE_OS == DE_OS_UNIX) && defined(ANGLE_USE_X11)
415
// Make sure to only open the X display once so that it can be used by the EGL display as well
416
// as pixmaps
417
mNativeDisplay = bitCast<eglw::EGLNativeDisplayType>(XOpenDisplay(nullptr));
418
#endif // (DE_OS == DE_OS_UNIX)
419
420
// If pre-rotating, let NativeWindowFactory know.
421
uint32_t preRotation = 0;
422
for (size_t attrIndex = 0;
423
attrIndex < mPlatformAttributes.size() && mPlatformAttributes[attrIndex] != EGL_NONE;
424
attrIndex += 2)
425
{
426
if (mPlatformAttributes[attrIndex] != EGL_FEATURE_OVERRIDES_ENABLED_ANGLE)
427
{
428
continue;
429
}
430
431
const char **enabledFeatures =
432
reinterpret_cast<const char **>(mPlatformAttributes[attrIndex + 1]);
433
DE_ASSERT(enabledFeatures != nullptr && *enabledFeatures != nullptr);
434
435
for (; *enabledFeatures; ++enabledFeatures)
436
{
437
if (strcmp(enabledFeatures[0], "emulatedPrerotation90") == 0)
438
{
439
preRotation = 90;
440
}
441
else if (strcmp(enabledFeatures[0], "emulatedPrerotation180") == 0)
442
{
443
preRotation = 180;
444
}
445
else if (strcmp(enabledFeatures[0], "emulatedPrerotation270") == 0)
446
{
447
preRotation = 270;
448
}
449
}
450
break;
451
}
452
453
m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(eventState, preRotation));
454
m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
455
}
456
457
ANGLENativeDisplayFactory::~ANGLENativeDisplayFactory() = default;
458
459
eglu::NativeDisplay *ANGLENativeDisplayFactory::createDisplay(
460
const eglw::EGLAttrib *attribList) const
461
{
462
DE_UNREF(attribList);
463
return new ANGLENativeDisplay(bitCast<EGLNativeDisplayType>(mNativeDisplay),
464
mPlatformAttributes);
465
}
466
467
} // namespace tcu
468
469