Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/egl_tests/EGLBlobCacheTest.cpp
1693 views
1
//
2
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
// EGLBlobCacheTest:
7
// Unit tests for the EGL_ANDROID_blob_cache extension.
8
9
// Must be included first to prevent errors with "None".
10
#include "test_utils/ANGLETest.h"
11
12
#include <map>
13
#include <vector>
14
15
#include "common/PackedEnums.h"
16
#include "common/angleutils.h"
17
#include "test_utils/gl_raii.h"
18
#include "util/EGLWindow.h"
19
20
using namespace angle;
21
22
constexpr char kEGLExtName[] = "EGL_ANDROID_blob_cache";
23
24
enum class CacheOpResult
25
{
26
SetSuccess,
27
GetNotFound,
28
GetMemoryTooSmall,
29
GetSuccess,
30
ValueNotSet,
31
EnumCount
32
};
33
34
angle::PackedEnumMap<CacheOpResult, std::string> kCacheOpToString = {
35
{CacheOpResult::SetSuccess, "SetSuccess"},
36
{CacheOpResult::GetNotFound, "GetNotFound"},
37
{CacheOpResult::GetMemoryTooSmall, "GetMemoryTooSmall"},
38
{CacheOpResult::GetSuccess, "GetSuccess"},
39
{CacheOpResult::ValueNotSet, "ValueNotSet"},
40
};
41
42
std::ostream &operator<<(std::ostream &os, CacheOpResult result)
43
{
44
return os << kCacheOpToString[result];
45
}
46
47
namespace
48
{
49
std::map<std::vector<uint8_t>, std::vector<uint8_t>> gApplicationCache;
50
CacheOpResult gLastCacheOpResult = CacheOpResult::ValueNotSet;
51
52
void SetBlob(const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize)
53
{
54
std::vector<uint8_t> keyVec(keySize);
55
memcpy(keyVec.data(), key, keySize);
56
57
std::vector<uint8_t> valueVec(valueSize);
58
memcpy(valueVec.data(), value, valueSize);
59
60
gApplicationCache[keyVec] = valueVec;
61
62
gLastCacheOpResult = CacheOpResult::SetSuccess;
63
}
64
65
EGLsizeiANDROID GetBlob(const void *key,
66
EGLsizeiANDROID keySize,
67
void *value,
68
EGLsizeiANDROID valueSize)
69
{
70
std::vector<uint8_t> keyVec(keySize);
71
memcpy(keyVec.data(), key, keySize);
72
73
auto entry = gApplicationCache.find(keyVec);
74
if (entry == gApplicationCache.end())
75
{
76
gLastCacheOpResult = CacheOpResult::GetNotFound;
77
return 0;
78
}
79
80
if (entry->second.size() <= static_cast<size_t>(valueSize))
81
{
82
memcpy(value, entry->second.data(), entry->second.size());
83
gLastCacheOpResult = CacheOpResult::GetSuccess;
84
}
85
else
86
{
87
gLastCacheOpResult = CacheOpResult::GetMemoryTooSmall;
88
}
89
90
return entry->second.size();
91
}
92
} // anonymous namespace
93
94
class EGLBlobCacheTest : public ANGLETest
95
{
96
protected:
97
EGLBlobCacheTest() : mHasBlobCache(false)
98
{
99
// Force disply caching off. Blob cache functions require it.
100
forceNewDisplay();
101
}
102
103
void testSetUp() override
104
{
105
EGLDisplay display = getEGLWindow()->getDisplay();
106
mHasBlobCache = IsEGLDisplayExtensionEnabled(display, kEGLExtName);
107
}
108
109
void testTearDown() override { gApplicationCache.clear(); }
110
111
bool programBinaryAvailable() { return IsGLExtensionEnabled("GL_OES_get_program_binary"); }
112
113
bool mHasBlobCache;
114
};
115
116
// Makes sure the extension exists and works
117
TEST_P(EGLBlobCacheTest, Functional)
118
{
119
EGLDisplay display = getEGLWindow()->getDisplay();
120
121
EXPECT_TRUE(mHasBlobCache);
122
eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
123
ASSERT_EGL_SUCCESS();
124
125
constexpr char kVertexShaderSrc[] = R"(attribute vec4 aTest;
126
attribute vec2 aPosition;
127
varying vec4 vTest;
128
void main()
129
{
130
vTest = aTest;
131
gl_Position = vec4(aPosition, 0.0, 1.0);
132
gl_PointSize = 1.0;
133
})";
134
135
constexpr char kFragmentShaderSrc[] = R"(precision mediump float;
136
varying vec4 vTest;
137
void main()
138
{
139
gl_FragColor = vTest;
140
})";
141
142
constexpr char kVertexShaderSrc2[] = R"(attribute vec4 aTest;
143
attribute vec2 aPosition;
144
varying vec4 vTest;
145
void main()
146
{
147
vTest = aTest;
148
gl_Position = vec4(aPosition, 1.0, 1.0);
149
gl_PointSize = 1.0;
150
})";
151
152
constexpr char kFragmentShaderSrc2[] = R"(precision mediump float;
153
varying vec4 vTest;
154
void main()
155
{
156
gl_FragColor = vTest - vec4(0.0, 1.0, 0.0, 0.0);
157
})";
158
159
// Compile a shader so it puts something in the cache
160
if (programBinaryAvailable())
161
{
162
ANGLE_GL_PROGRAM(program, kVertexShaderSrc, kFragmentShaderSrc);
163
EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
164
gLastCacheOpResult = CacheOpResult::ValueNotSet;
165
166
// Compile the same shader again, so it would try to retrieve it from the cache
167
program.makeRaster(kVertexShaderSrc, kFragmentShaderSrc);
168
ASSERT_TRUE(program.valid());
169
EXPECT_EQ(CacheOpResult::GetSuccess, gLastCacheOpResult);
170
gLastCacheOpResult = CacheOpResult::ValueNotSet;
171
172
// Compile another shader, which should create a new entry
173
program.makeRaster(kVertexShaderSrc2, kFragmentShaderSrc2);
174
ASSERT_TRUE(program.valid());
175
EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
176
gLastCacheOpResult = CacheOpResult::ValueNotSet;
177
178
// Compile the first shader again, which should still reside in the cache
179
program.makeRaster(kVertexShaderSrc, kFragmentShaderSrc);
180
ASSERT_TRUE(program.valid());
181
EXPECT_EQ(CacheOpResult::GetSuccess, gLastCacheOpResult);
182
gLastCacheOpResult = CacheOpResult::ValueNotSet;
183
}
184
}
185
186
// Tests error conditions of the APIs.
187
TEST_P(EGLBlobCacheTest, NegativeAPI)
188
{
189
EXPECT_TRUE(mHasBlobCache);
190
191
// Test bad display
192
eglSetBlobCacheFuncsANDROID(EGL_NO_DISPLAY, nullptr, nullptr);
193
EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
194
195
eglSetBlobCacheFuncsANDROID(EGL_NO_DISPLAY, SetBlob, GetBlob);
196
EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
197
198
EGLDisplay display = getEGLWindow()->getDisplay();
199
200
// Test bad arguments
201
eglSetBlobCacheFuncsANDROID(display, nullptr, nullptr);
202
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
203
204
eglSetBlobCacheFuncsANDROID(display, SetBlob, nullptr);
205
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
206
207
eglSetBlobCacheFuncsANDROID(display, nullptr, GetBlob);
208
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
209
210
// Set the arguments once and test setting them again (which should fail)
211
eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
212
ASSERT_EGL_SUCCESS();
213
214
eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
215
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
216
217
// Try again with bad parameters
218
eglSetBlobCacheFuncsANDROID(EGL_NO_DISPLAY, nullptr, nullptr);
219
EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
220
221
eglSetBlobCacheFuncsANDROID(display, nullptr, nullptr);
222
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
223
224
eglSetBlobCacheFuncsANDROID(display, SetBlob, nullptr);
225
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
226
227
eglSetBlobCacheFuncsANDROID(display, nullptr, GetBlob);
228
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
229
}
230
231
// Regression test for including the fragment output locatins in the program key.
232
// http://anglebug.com/4535
233
TEST_P(EGLBlobCacheTest, FragmentOutputLocationKey)
234
{
235
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended") ||
236
getClientMajorVersion() < 3);
237
238
EGLDisplay display = getEGLWindow()->getDisplay();
239
240
EXPECT_TRUE(mHasBlobCache);
241
eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
242
ASSERT_EGL_SUCCESS();
243
244
// Compile a shader so it puts something in the cache
245
if (programBinaryAvailable())
246
{
247
constexpr char kFragmentShaderSrc[] = R"(#version 300 es
248
#extension GL_EXT_blend_func_extended : require
249
precision mediump float;
250
uniform vec4 src;
251
uniform vec4 src1;
252
out vec4 FragData;
253
out vec4 SecondaryFragData;
254
void main() {
255
FragData = src;
256
SecondaryFragData = src1;
257
})";
258
259
constexpr char kVertexShaderSrc[] = R"(#version 300 es
260
in vec4 position;
261
void main() {
262
gl_Position = position;
263
})";
264
265
GLuint program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc, [](GLuint p) {
266
glBindFragDataLocationEXT(p, 0, "FragData[0]");
267
glBindFragDataLocationIndexedEXT(p, 0, 1, "SecondaryFragData[0]");
268
});
269
ASSERT_NE(0u, program);
270
EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
271
gLastCacheOpResult = CacheOpResult::ValueNotSet;
272
273
// Re-link the program with different fragment output bindings
274
program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc, [](GLuint p) {
275
glBindFragDataLocationEXT(p, 0, "FragData");
276
glBindFragDataLocationIndexedEXT(p, 0, 1, "SecondaryFragData");
277
});
278
ASSERT_NE(0u, program);
279
EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
280
gLastCacheOpResult = CacheOpResult::ValueNotSet;
281
}
282
}
283
284
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLBlobCacheTest);
285
286