Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/targets/osmesa/test-render.cpp
4565 views
1
#include <cstdint>
2
#include <cstdio>
3
#include <cstdlib>
4
#include <array>
5
#include <memory>
6
7
#include <gtest/gtest.h>
8
9
#include "GL/osmesa.h"
10
#include "util/macros.h"
11
#include "util/u_endian.h"
12
#include "util/u_math.h"
13
14
typedef struct {
15
unsigned format;
16
GLenum type;
17
int bpp;
18
uint64_t expected;
19
} Params;
20
21
class OSMesaRenderTestFixture : public testing::TestWithParam<Params> {};
22
23
std::string
24
name_params(const testing::TestParamInfo<Params> params) {
25
auto p = params.param;
26
std::string first, second;
27
switch (p.format) {
28
case OSMESA_RGBA:
29
first = "rgba";
30
break;
31
case OSMESA_BGRA:
32
first = "bgra";
33
break;
34
case OSMESA_RGB:
35
first = "rgb";
36
break;
37
case OSMESA_RGB_565:
38
first = "rgb_565";
39
break;
40
case OSMESA_ARGB:
41
first = "argb";
42
break;
43
}
44
45
switch (p.type) {
46
case GL_UNSIGNED_SHORT:
47
second = "unsigned_short";
48
break;
49
case GL_UNSIGNED_BYTE:
50
second = "unsigned_byte";
51
break;
52
case GL_FLOAT:
53
second = "float";
54
break;
55
case GL_UNSIGNED_SHORT_5_6_5:
56
second = "unsigned_short_565";
57
break;
58
}
59
60
return first + "_" + second;
61
};
62
63
TEST_P(OSMesaRenderTestFixture, Render)
64
{
65
auto p = GetParam();
66
const int w = 2, h = 2;
67
uint8_t pixels[w * h * 8] = { 0 };
68
69
std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{
70
OSMesaCreateContext(p.format, NULL), &OSMesaDestroyContext};
71
ASSERT_TRUE(ctx);
72
73
auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, p.type, w, h);
74
ASSERT_EQ(ret, GL_TRUE);
75
76
glClearColor(0.25, 1.0, 0.5, 0.75);
77
78
uint64_t expected = p.expected;
79
80
/* All the formats other than 565 and RGB/byte are array formats, but our
81
* expected values are packed, so byte swap appropriately.
82
*/
83
if (UTIL_ARCH_BIG_ENDIAN) {
84
switch (p.bpp) {
85
case 8:
86
expected = util_bswap64(expected);
87
break;
88
89
case 4:
90
expected = util_bswap32(expected);
91
break;
92
93
case 3:
94
case 2:
95
break;
96
}
97
}
98
99
glClear(GL_COLOR_BUFFER_BIT);
100
glFinish();
101
102
#if 0 /* XXX */
103
for (unsigned i = 0; i < ARRAY_SIZE(pixels); i += 4) {
104
fprintf(stderr, "pixel %d: %02x %02x %02x %02x\n",
105
i / 4,
106
pixels[i + 0],
107
pixels[i + 1],
108
pixels[i + 2],
109
pixels[i + 3]);
110
}
111
#endif
112
113
for (unsigned i = 0; i < w * h; i++) {
114
switch (p.bpp) {
115
case 2: {
116
uint16_t color = 0;
117
memcpy(&color, &pixels[i * p.bpp], p.bpp);
118
ASSERT_EQ(expected, color);
119
break;
120
}
121
122
case 3: {
123
uint32_t color = ((pixels[i * p.bpp + 0] << 0) |
124
(pixels[i * p.bpp + 1] << 8) |
125
(pixels[i * p.bpp + 2] << 16));
126
ASSERT_EQ(expected, color);
127
break;
128
}
129
130
case 4: {
131
uint32_t color = 0;
132
memcpy(&color, &pixels[i * p.bpp], p.bpp);
133
ASSERT_EQ(expected, color);
134
break;
135
}
136
137
case 8: {
138
uint64_t color = 0;
139
memcpy(&color, &pixels[i * p.bpp], p.bpp);
140
ASSERT_EQ(expected, color);
141
break;
142
}
143
144
default:
145
unreachable("bad bpp");
146
}
147
}
148
}
149
150
INSTANTIATE_TEST_CASE_P(
151
OSMesaRenderTest,
152
OSMesaRenderTestFixture,
153
testing::Values(
154
Params{ OSMESA_RGBA, GL_UNSIGNED_BYTE, 4, 0xbf80ff40 },
155
Params{ OSMESA_BGRA, GL_UNSIGNED_BYTE, 4, 0xbf40ff80 },
156
Params{ OSMESA_ARGB, GL_UNSIGNED_BYTE, 4, 0x80ff40bf},
157
Params{ OSMESA_RGB, GL_UNSIGNED_BYTE, 3, 0x80ff40 },
158
Params{ OSMESA_RGBA, GL_UNSIGNED_SHORT, 8, 0xbfff8000ffff4000ull },
159
Params{ OSMESA_RGB_565, GL_UNSIGNED_SHORT_5_6_5, 2, ((0x10 << 0) |
160
(0x3f << 5) |
161
(0x8 << 11)) }
162
),
163
name_params
164
);
165
166
TEST(OSMesaRenderTest, depth)
167
{
168
std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{
169
OSMesaCreateContextExt(OSMESA_RGB_565, 24, 8, 0, NULL), &OSMesaDestroyContext};
170
ASSERT_TRUE(ctx);
171
172
const int w = 3, h = 2;
173
uint8_t pixels[4096 * h * 2] = {0}; /* different cpp from our depth! */
174
auto ret = OSMesaMakeCurrent(ctx.get(), &pixels, GL_UNSIGNED_SHORT_5_6_5, w, h);
175
ASSERT_EQ(ret, GL_TRUE);
176
177
/* Expand the row length for the color buffer so we can see that it doesn't affect depth. */
178
OSMesaPixelStore(OSMESA_ROW_LENGTH, 4096);
179
180
uint32_t *depth;
181
GLint dw, dh, depth_cpp;
182
ASSERT_EQ(true, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth));
183
184
ASSERT_EQ(dw, w);
185
ASSERT_EQ(dh, h);
186
ASSERT_EQ(depth_cpp, 4);
187
188
glClearDepth(1.0);
189
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
190
glFinish();
191
EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);
192
EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);
193
EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff);
194
EXPECT_EQ(depth[w * 1 + 1], 0x00ffffff);
195
196
/* Scissor to the top half and clear */
197
glEnable(GL_SCISSOR_TEST);
198
glScissor(0, 1, 2, 1);
199
glClearDepth(0.0);
200
glClear(GL_DEPTH_BUFFER_BIT);
201
glFinish();
202
EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);
203
EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);
204
EXPECT_EQ(depth[w * 1 + 0], 0x00000000);
205
EXPECT_EQ(depth[w * 1 + 1], 0x00000000);
206
207
/* Y_UP didn't affect depth buffer orientation in classic osmesa. */
208
OSMesaPixelStore(OSMESA_Y_UP, false);
209
glScissor(0, 1, 1, 1);
210
glClearDepth(1.0);
211
glClear(GL_DEPTH_BUFFER_BIT);
212
glFinish();
213
EXPECT_EQ(depth[w * 0 + 0], 0x00ffffff);
214
EXPECT_EQ(depth[w * 0 + 1], 0x00ffffff);
215
EXPECT_EQ(depth[w * 1 + 0], 0x00ffffff);
216
EXPECT_EQ(depth[w * 1 + 1], 0x00000000);
217
}
218
219
TEST(OSMesaRenderTest, depth_get_no_attachment)
220
{
221
std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx{
222
OSMesaCreateContextExt(OSMESA_RGBA, 0, 0, 0, NULL), &OSMesaDestroyContext};
223
ASSERT_TRUE(ctx);
224
225
uint32_t pixel;
226
auto ret = OSMesaMakeCurrent(ctx.get(), &pixel, GL_UNSIGNED_BYTE, 1, 1);
227
ASSERT_EQ(ret, GL_TRUE);
228
229
uint32_t *depth;
230
GLint dw = 1, dh = 1, depth_cpp = 1;
231
ASSERT_EQ(false, OSMesaGetDepthBuffer(ctx.get(), &dw, &dh, &depth_cpp, (void **)&depth));
232
ASSERT_EQ(depth_cpp, NULL);
233
ASSERT_EQ(dw, 0);
234
ASSERT_EQ(dh, 0);
235
ASSERT_EQ(depth_cpp, 0);
236
}
237
238
static uint32_t be_bswap32(uint32_t x)
239
{
240
if (UTIL_ARCH_BIG_ENDIAN)
241
return util_bswap32(x);
242
else
243
return x;
244
}
245
246
TEST(OSMesaRenderTest, separate_buffers_per_context)
247
{
248
std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx1{
249
OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext};
250
std::unique_ptr<osmesa_context, decltype(&OSMesaDestroyContext)> ctx2{
251
OSMesaCreateContext(GL_RGBA, NULL), &OSMesaDestroyContext};
252
ASSERT_TRUE(ctx1);
253
ASSERT_TRUE(ctx2);
254
255
uint32_t pixel1, pixel2;
256
257
ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);
258
glClearColor(1.0, 0.0, 0.0, 0.0);
259
glClear(GL_COLOR_BUFFER_BIT);
260
glFinish();
261
EXPECT_EQ(pixel1, be_bswap32(0x000000ff));
262
263
ASSERT_EQ(OSMesaMakeCurrent(ctx2.get(), &pixel2, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);
264
glClearColor(0.0, 1.0, 0.0, 0.0);
265
glClear(GL_COLOR_BUFFER_BIT);
266
glFinish();
267
EXPECT_EQ(pixel1, be_bswap32(0x000000ff));
268
EXPECT_EQ(pixel2, be_bswap32(0x0000ff00));
269
270
/* Leave a dangling render to pixel2 as we switch contexts (there should be
271
*/
272
glClearColor(0.0, 0.0, 1.0, 0.0);
273
glClear(GL_COLOR_BUFFER_BIT);
274
275
ASSERT_EQ(OSMesaMakeCurrent(ctx1.get(), &pixel1, GL_UNSIGNED_BYTE, 1, 1), GL_TRUE);
276
/* Draw something off screen to trigger a real flush. We should have the
277
* same contents in pixel1 as before
278
*/
279
glBegin(GL_TRIANGLES);
280
glVertex2f(-2, -2);
281
glVertex2f(-2, -2);
282
glVertex2f(-2, -2);
283
glEnd();
284
glFinish();
285
EXPECT_EQ(pixel1, be_bswap32(0x000000ff));
286
EXPECT_EQ(pixel2, be_bswap32(0x00ff0000));
287
}
288
289