Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/egl_tests/EGLStreamTest.cpp
1693 views
1
//
2
// Copyright 2016 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
// EGLStreamTest:
7
// Tests pertaining to egl::Stream.
8
//
9
10
#include <gtest/gtest.h>
11
12
#include <vector>
13
14
#include "media/yuvtest.inl"
15
#include "test_utils/ANGLETest.h"
16
#include "test_utils/gl_raii.h"
17
#include "util/EGLWindow.h"
18
#include "util/OSWindow.h"
19
20
using namespace angle;
21
22
namespace
23
{
24
25
bool CheckTextureSupport(ID3D11Device *device, DXGI_FORMAT format)
26
{
27
HRESULT result;
28
UINT formatSupport;
29
result = device->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
30
if (result == E_FAIL)
31
{
32
return false;
33
}
34
return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
35
}
36
37
bool CheckNV12TextureSupport(ID3D11Device *device)
38
{
39
return CheckTextureSupport(device, DXGI_FORMAT_NV12);
40
}
41
42
bool CheckP010TextureSupport(ID3D11Device *device)
43
{
44
return CheckTextureSupport(device, DXGI_FORMAT_P010);
45
}
46
47
class EGLStreamTest : public ANGLETest
48
{
49
protected:
50
EGLStreamTest()
51
{
52
setWindowWidth(128);
53
setWindowHeight(128);
54
setConfigRedBits(8);
55
setConfigGreenBits(8);
56
setConfigBlueBits(8);
57
setConfigAlphaBits(8);
58
setConfigDepthBits(24);
59
}
60
};
61
62
// Tests validation of the stream API
63
TEST_P(EGLStreamTest, StreamValidationTest)
64
{
65
EGLWindow *window = getEGLWindow();
66
EGLDisplay display = window->getDisplay();
67
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
68
if (strstr(extensionsString, "EGL_KHR_stream") == nullptr)
69
{
70
std::cout << "Stream extension not supported" << std::endl;
71
return;
72
}
73
74
const EGLint streamAttributesBad[] = {
75
EGL_STREAM_STATE_KHR,
76
0,
77
EGL_NONE,
78
EGL_PRODUCER_FRAME_KHR,
79
0,
80
EGL_NONE,
81
EGL_CONSUMER_FRAME_KHR,
82
0,
83
EGL_NONE,
84
EGL_CONSUMER_LATENCY_USEC_KHR,
85
-1,
86
EGL_NONE,
87
EGL_RED_SIZE,
88
EGL_DONT_CARE,
89
EGL_NONE,
90
};
91
92
// Validate create stream attributes
93
EGLStreamKHR stream = eglCreateStreamKHR(display, &streamAttributesBad[0]);
94
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
95
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
96
97
stream = eglCreateStreamKHR(display, &streamAttributesBad[3]);
98
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
99
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
100
101
stream = eglCreateStreamKHR(display, &streamAttributesBad[6]);
102
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
103
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
104
105
stream = eglCreateStreamKHR(display, &streamAttributesBad[9]);
106
ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
107
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
108
109
stream = eglCreateStreamKHR(display, &streamAttributesBad[12]);
110
ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
111
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
112
113
const EGLint streamAttributes[] = {
114
EGL_CONSUMER_LATENCY_USEC_KHR,
115
0,
116
EGL_NONE,
117
};
118
119
stream = eglCreateStreamKHR(EGL_NO_DISPLAY, streamAttributes);
120
ASSERT_EGL_ERROR(EGL_BAD_DISPLAY);
121
ASSERT_EQ(EGL_NO_STREAM_KHR, stream);
122
123
// Create an actual stream
124
stream = eglCreateStreamKHR(display, streamAttributes);
125
ASSERT_EGL_SUCCESS();
126
ASSERT_NE(EGL_NO_STREAM_KHR, stream);
127
128
// Assert it is in the created state
129
EGLint state;
130
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
131
ASSERT_EGL_SUCCESS();
132
ASSERT_EQ(EGL_STREAM_STATE_CREATED_KHR, state);
133
134
// Test getting and setting the latency
135
EGLint latency = 10;
136
eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, latency);
137
ASSERT_EGL_SUCCESS();
138
eglQueryStreamKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, &latency);
139
ASSERT_EGL_SUCCESS();
140
ASSERT_EQ(10, latency);
141
eglStreamAttribKHR(display, stream, EGL_CONSUMER_LATENCY_USEC_KHR, -1);
142
ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
143
ASSERT_EQ(10, latency);
144
145
// Test the 64-bit queries
146
EGLuint64KHR value;
147
eglQueryStreamu64KHR(display, stream, EGL_CONSUMER_FRAME_KHR, &value);
148
ASSERT_EGL_SUCCESS();
149
eglQueryStreamu64KHR(display, stream, EGL_PRODUCER_FRAME_KHR, &value);
150
ASSERT_EGL_SUCCESS();
151
152
// Destroy the stream
153
eglDestroyStreamKHR(display, stream);
154
ASSERT_EGL_SUCCESS();
155
}
156
157
// Tests validation of stream consumer gltexture API
158
TEST_P(EGLStreamTest, StreamConsumerGLTextureValidationTest)
159
{
160
EGLWindow *window = getEGLWindow();
161
EGLDisplay display = window->getDisplay();
162
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
163
if (strstr(extensionsString, "EGL_KHR_stream_consumer_gltexture") == nullptr)
164
{
165
std::cout << "Stream consumer gltexture extension not supported" << std::endl;
166
return;
167
}
168
169
const EGLint streamAttributes[] = {
170
EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
171
};
172
173
EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
174
ASSERT_EGL_SUCCESS();
175
176
EGLBoolean result = eglStreamConsumerGLTextureExternalKHR(display, stream);
177
ASSERT_EGL_FALSE(result);
178
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
179
180
GLTexture tex;
181
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
182
result = eglStreamConsumerGLTextureExternalKHR(display, stream);
183
ASSERT_EGL_TRUE(result);
184
ASSERT_EGL_SUCCESS();
185
186
EGLint state;
187
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
188
ASSERT_EGL_SUCCESS();
189
ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);
190
191
eglDestroyStreamKHR(display, stream);
192
ASSERT_EGL_SUCCESS();
193
}
194
195
// Tests validation of stream consumer gltexture yuv API
196
TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVValidationTest)
197
{
198
EGLWindow *window = getEGLWindow();
199
EGLDisplay display = window->getDisplay();
200
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
201
if (strstr(extensionsString, "EGL_NV_stream_consumer_gltexture_yuv") == nullptr)
202
{
203
std::cout << "Stream consumer gltexture yuv extension not supported" << std::endl;
204
return;
205
}
206
207
const EGLint streamAttributes[] = {
208
EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
209
};
210
211
EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
212
ASSERT_EGL_SUCCESS();
213
214
EGLAttrib consumerAttributesBad[] = {
215
EGL_COLOR_BUFFER_TYPE,
216
EGL_YUV_BUFFER_EXT, // 0
217
EGL_YUV_NUMBER_OF_PLANES_EXT,
218
0,
219
EGL_NONE,
220
EGL_COLOR_BUFFER_TYPE,
221
EGL_YUV_BUFFER_EXT, // 5
222
EGL_YUV_NUMBER_OF_PLANES_EXT,
223
1,
224
EGL_NONE,
225
EGL_COLOR_BUFFER_TYPE,
226
EGL_YUV_BUFFER_EXT, // 10
227
EGL_YUV_NUMBER_OF_PLANES_EXT,
228
1,
229
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
230
9999,
231
EGL_NONE,
232
EGL_COLOR_BUFFER_TYPE,
233
EGL_YUV_BUFFER_EXT, // 17
234
EGL_YUV_NUMBER_OF_PLANES_EXT,
235
1,
236
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
237
0,
238
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
239
1,
240
EGL_NONE,
241
EGL_COLOR_BUFFER_TYPE,
242
EGL_YUV_BUFFER_EXT, // 26
243
EGL_YUV_NUMBER_OF_PLANES_EXT,
244
2,
245
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
246
0,
247
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
248
0,
249
EGL_NONE,
250
};
251
252
EGLAttrib consumerAttributes[] = {
253
EGL_COLOR_BUFFER_TYPE,
254
EGL_YUV_BUFFER_EXT,
255
EGL_YUV_NUMBER_OF_PLANES_EXT,
256
2,
257
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
258
0,
259
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
260
1,
261
EGL_NONE,
262
};
263
264
EGLBoolean result =
265
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[0]);
266
ASSERT_EGL_FALSE(result);
267
ASSERT_EGL_ERROR(EGL_BAD_MATCH);
268
269
result =
270
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[5]);
271
ASSERT_EGL_FALSE(result);
272
ASSERT_EGL_ERROR(EGL_BAD_MATCH);
273
274
result =
275
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[10]);
276
ASSERT_EGL_FALSE(result);
277
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
278
279
result =
280
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[17]);
281
ASSERT_EGL_FALSE(result);
282
ASSERT_EGL_ERROR(EGL_BAD_MATCH);
283
284
result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
285
ASSERT_EGL_FALSE(result);
286
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
287
288
GLTexture tex[2];
289
glActiveTexture(GL_TEXTURE0);
290
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
291
glActiveTexture(GL_TEXTURE1);
292
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
293
294
result =
295
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, &consumerAttributesBad[26]);
296
ASSERT_EGL_FALSE(result);
297
ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
298
299
result = eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
300
ASSERT_EGL_TRUE(result);
301
ASSERT_EGL_SUCCESS();
302
303
EGLint state;
304
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
305
ASSERT_EGL_SUCCESS();
306
ASSERT_EQ(EGL_STREAM_STATE_CONNECTING_KHR, state);
307
308
eglDestroyStreamKHR(display, stream);
309
ASSERT_EGL_SUCCESS();
310
}
311
312
// Tests that deleting a texture invalidates the associated stream
313
TEST_P(EGLStreamTest, StreamConsumerGLTextureYUVDeletionTest)
314
{
315
EGLWindow *window = getEGLWindow();
316
EGLDisplay display = window->getDisplay();
317
const char *extensionsString = eglQueryString(display, EGL_EXTENSIONS);
318
if (strstr(extensionsString, "EGL_ANGLE_stream_producer_d3d_texture") == nullptr)
319
{
320
std::cout << "Stream producer d3d texture not supported" << std::endl;
321
return;
322
}
323
324
const EGLint streamAttributes[] = {
325
EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
326
};
327
328
EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
329
ASSERT_EGL_SUCCESS();
330
331
EGLAttrib consumerAttributes[] = {
332
EGL_COLOR_BUFFER_TYPE,
333
EGL_YUV_BUFFER_EXT,
334
EGL_YUV_NUMBER_OF_PLANES_EXT,
335
2,
336
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
337
0,
338
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
339
1,
340
EGL_NONE,
341
};
342
343
// Note: The purpose of this test means that we can't use the RAII GLTexture class
344
GLuint tex[2];
345
glGenTextures(2, tex);
346
glActiveTexture(GL_TEXTURE0);
347
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
348
glActiveTexture(GL_TEXTURE1);
349
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
350
351
EGLBoolean result =
352
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
353
ASSERT_EGL_TRUE(result);
354
ASSERT_EGL_SUCCESS();
355
356
EGLAttrib producerAttributes[] = {
357
EGL_NONE,
358
};
359
360
result = eglCreateStreamProducerD3DTextureANGLE(display, stream, producerAttributes);
361
ASSERT_EGL_TRUE(result);
362
ASSERT_EGL_SUCCESS();
363
364
EGLint state;
365
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
366
ASSERT_EGL_SUCCESS();
367
ASSERT_EQ(EGL_STREAM_STATE_EMPTY_KHR, state);
368
369
// Delete the first texture, which should be enough to invalidate the stream
370
glDeleteTextures(1, tex);
371
372
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
373
ASSERT_EGL_SUCCESS();
374
ASSERT_EQ(EGL_STREAM_STATE_DISCONNECTED_KHR, state);
375
376
eglDestroyStreamKHR(display, stream);
377
ASSERT_EGL_SUCCESS();
378
}
379
380
class D3D11TextureStreamSamplingTest : public ANGLETest
381
{
382
protected:
383
void testSetUp() override
384
{
385
EGLWindow *window = getEGLWindow();
386
mDisplay = window->getDisplay();
387
if (!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_stream_producer_d3d_texture"))
388
{
389
std::cout << "Stream producer d3d texture not supported" << std::endl;
390
return;
391
}
392
393
glGenRenderbuffers(1, &mRB);
394
glBindRenderbuffer(GL_RENDERBUFFER, mRB);
395
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 2, 2);
396
glBindRenderbuffer(GL_RENDERBUFFER, 0);
397
398
glGenFramebuffers(1, &mFB);
399
glBindFramebuffer(GL_FRAMEBUFFER, mFB);
400
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRB);
401
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
402
403
glViewport(0, 0, 2, 2);
404
glClearColor(1, 0, 0, 1);
405
glClear(GL_COLOR_BUFFER_BIT);
406
ASSERT_GL_NO_ERROR();
407
408
uint32_t pixel;
409
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
410
ASSERT_EQ(pixel, 0xff0000ff);
411
412
mStream = eglCreateStreamKHR(mDisplay, nullptr);
413
ASSERT_EGL_SUCCESS();
414
415
EGLDeviceEXT eglDevice;
416
eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice);
417
eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, (EGLAttrib *)&mD3D);
418
}
419
420
void testTearDown() override
421
{
422
EGLBoolean result = eglDestroyStreamKHR(mDisplay, mStream);
423
ASSERT_EGL_TRUE(result);
424
ASSERT_EGL_SUCCESS();
425
426
glDeleteRenderbuffers(1, &mRB);
427
glDeleteFramebuffers(1, &mFB);
428
}
429
430
EGLDisplay mDisplay = 0;
431
EGLStreamKHR mStream = 0;
432
GLuint mRB = 0;
433
GLuint mFB = 0;
434
ID3D11Device *mD3D;
435
};
436
437
// Test RGBA texture sampling via EGLStreams
438
TEST_P(D3D11TextureStreamSamplingTest, RGBA)
439
{
440
EGLWindow *window = getEGLWindow();
441
EGLDisplay display = window->getDisplay();
442
ANGLE_SKIP_TEST_IF(
443
!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));
444
445
constexpr char kVertShader[] = R"(
446
attribute vec4 aPos;
447
varying vec2 vTexCoord;
448
void main()
449
{
450
gl_Position = aPos;
451
vTexCoord = gl_Position.xy * 0.5 + 0.5;
452
}
453
)";
454
constexpr char kFragShader[] = R"(
455
#extension GL_NV_EGL_stream_consumer_external : require
456
precision mediump float;
457
uniform samplerExternalOES uTex;
458
varying vec2 vTexCoord;
459
void main()
460
{
461
gl_FragColor = texture2D(uTex, vTexCoord);
462
}
463
)";
464
ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);
465
glUseProgram(prog);
466
glUniform1i(glGetUniformLocation(prog, "uTex"), 0);
467
468
GLTexture tex;
469
glActiveTexture(GL_TEXTURE0);
470
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
471
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
472
ASSERT_GL_NO_ERROR();
473
474
EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(mDisplay, mStream, nullptr);
475
ASSERT_EGL_TRUE(result);
476
ASSERT_EGL_SUCCESS();
477
glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picked up
478
// the current slot.
479
480
result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);
481
ASSERT_EGL_TRUE(result);
482
ASSERT_EGL_SUCCESS();
483
484
// Create and post the d3d11 texture
485
486
D3D11_TEXTURE2D_DESC desc = {};
487
desc.Width = 1;
488
desc.Height = 1;
489
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
490
desc.MipLevels = 1;
491
desc.ArraySize = 1;
492
desc.SampleDesc.Count = 1;
493
desc.Usage = D3D11_USAGE_DEFAULT;
494
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
495
496
constexpr uint8_t texData[] = {0x10, 0x20, 0x30, 0x40};
497
D3D11_SUBRESOURCE_DATA subres;
498
subres.pSysMem = texData;
499
subres.SysMemPitch = 4;
500
501
ID3D11Texture2D *texture = nullptr;
502
(void)mD3D->CreateTexture2D(&desc, &subres, &texture);
503
ASSERT_NE(nullptr, texture);
504
505
result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);
506
ASSERT_EGL_TRUE(result);
507
ASSERT_EGL_SUCCESS();
508
509
// Sample and test
510
511
result = eglStreamConsumerAcquireKHR(mDisplay, mStream);
512
ASSERT_EGL_TRUE(result);
513
ASSERT_EGL_SUCCESS();
514
515
drawQuad(prog, "aPos", 0.0);
516
517
uint32_t pixel;
518
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
519
ASSERT_GL_NO_ERROR();
520
ASSERT_EQ(pixel, static_cast<uint32_t>(0x40302010));
521
522
result = eglStreamConsumerReleaseKHR(mDisplay, mStream);
523
ASSERT_EGL_TRUE(result);
524
ASSERT_EGL_SUCCESS();
525
}
526
527
// Test NV12 texture sampling via EGLStreams
528
TEST_P(D3D11TextureStreamSamplingTest, NV12)
529
{
530
EGLWindow *window = getEGLWindow();
531
EGLDisplay display = window->getDisplay();
532
ANGLE_SKIP_TEST_IF(
533
!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));
534
ANGLE_SKIP_TEST_IF(!CheckNV12TextureSupport(mD3D));
535
536
constexpr char kVertShader[] = R"(
537
attribute vec4 aPos;
538
varying vec2 vTexCoord;
539
void main()
540
{
541
gl_Position = aPos;
542
vTexCoord = gl_Position.xy * 0.5 + 0.5;
543
}
544
)";
545
const char kFragShader[] = R"(
546
#extension GL_NV_EGL_stream_consumer_external : require
547
precision mediump float;
548
uniform samplerExternalOES uTexY;
549
uniform samplerExternalOES uTexUV;
550
varying vec2 vTexCoord;
551
void main()
552
{
553
gl_FragColor.r = texture2D(uTexY, vTexCoord).r;
554
gl_FragColor.gb = texture2D(uTexUV, vTexCoord).rg;
555
gl_FragColor.a = 1.0;
556
}
557
)";
558
ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);
559
glUseProgram(prog);
560
glUniform1i(glGetUniformLocation(prog, "uTexY"), 0);
561
glUniform1i(glGetUniformLocation(prog, "uTexUV"), 1);
562
563
ASSERT_GL_NO_ERROR();
564
565
GLTexture tex[2];
566
glActiveTexture(GL_TEXTURE0);
567
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
568
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
569
ASSERT_GL_NO_ERROR();
570
glActiveTexture(GL_TEXTURE1);
571
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
572
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
573
ASSERT_GL_NO_ERROR();
574
575
glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picks up
576
// the current slot.
577
constexpr EGLAttrib consumerAttributes[] = {
578
EGL_COLOR_BUFFER_TYPE,
579
EGL_YUV_BUFFER_EXT,
580
EGL_YUV_NUMBER_OF_PLANES_EXT,
581
2,
582
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
583
0,
584
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
585
1,
586
EGL_NONE,
587
};
588
EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
589
mDisplay, mStream, const_cast<EGLAttrib *>(consumerAttributes));
590
ASSERT_EGL_TRUE(result);
591
ASSERT_EGL_SUCCESS();
592
593
result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);
594
ASSERT_EGL_TRUE(result);
595
ASSERT_EGL_SUCCESS();
596
597
// Create and post the d3d11 texture
598
599
D3D11_TEXTURE2D_DESC desc = {};
600
desc.Width = 2;
601
desc.Height = 2;
602
desc.Format = DXGI_FORMAT_NV12;
603
desc.MipLevels = 1;
604
desc.ArraySize = 1;
605
desc.SampleDesc.Count = 1;
606
desc.Usage = D3D11_USAGE_DEFAULT;
607
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
608
609
/* DXGI_FORMAT_NV12:
610
* Width and height must be even.
611
* Direct3D 11 staging resources and initData parameters for this format use
612
* (rowPitch * (height + (height / 2))) bytes.
613
* The first (SysMemPitch * height) bytes are the Y plane, the remaining
614
* (SysMemPitch * (height / 2)) bytes are the UV plane.
615
*/
616
constexpr uint8_t texData[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60};
617
D3D11_SUBRESOURCE_DATA subres;
618
subres.pSysMem = texData;
619
subres.SysMemPitch = 2;
620
621
ID3D11Texture2D *texture = nullptr;
622
(void)mD3D->CreateTexture2D(&desc, &subres, &texture);
623
ASSERT_NE(nullptr, texture);
624
625
result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);
626
ASSERT_EGL_TRUE(result);
627
ASSERT_EGL_SUCCESS();
628
629
// Sample and test
630
631
result = eglStreamConsumerAcquireKHR(mDisplay, mStream);
632
ASSERT_EGL_TRUE(result);
633
ASSERT_EGL_SUCCESS();
634
635
drawQuad(prog, "aPos", 0.0);
636
uint32_t pixel;
637
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
638
ASSERT_EQ(pixel, 0xff605010);
639
640
glReadPixels(1, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
641
ASSERT_EQ(pixel, 0xff605020);
642
643
glReadPixels(0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
644
ASSERT_EQ(pixel, 0xff605030);
645
646
glReadPixels(1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
647
ASSERT_EQ(pixel, 0xff605040);
648
649
result = eglStreamConsumerReleaseKHR(mDisplay, mStream);
650
ASSERT_EGL_TRUE(result);
651
ASSERT_EGL_SUCCESS();
652
}
653
654
// End2end test for rendering an NV12 texture. Renders a YUV quad, reads back the RGB values, and
655
// ensures they are correct
656
TEST_P(EGLStreamTest, StreamProducerTextureNV12End2End)
657
{
658
EGLWindow *window = getEGLWindow();
659
EGLDisplay display = window->getDisplay();
660
ANGLE_SKIP_TEST_IF(
661
!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));
662
663
bool useESSL3Shaders =
664
getClientMajorVersion() >= 3 && IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3");
665
666
// yuv to rgb conversion shader using Microsoft's given conversion formulas
667
const char *yuvVS = nullptr;
668
const char *yuvPS = nullptr;
669
if (useESSL3Shaders)
670
{
671
yuvVS =
672
"#version 300 es\n"
673
"in highp vec4 position;\n"
674
"out vec2 texcoord;\n"
675
"void main(void)\n"
676
"{\n"
677
" gl_Position = position;\n"
678
" texcoord = (position.xy * 0.5) + 0.5;\n"
679
" texcoord.y = 1.0 - texcoord.y;\n"
680
"}\n";
681
yuvPS =
682
"#version 300 es\n"
683
"#extension GL_OES_EGL_image_external_essl3 : require\n"
684
"#extension GL_NV_EGL_stream_consumer_external : require\n"
685
"precision highp float;\n"
686
"in vec2 texcoord;\n"
687
"out vec4 color;\n"
688
"uniform samplerExternalOES y;\n"
689
"uniform samplerExternalOES uv\n;"
690
"void main(void)\n"
691
"{\n"
692
" float c = texture(y, texcoord).r - (16.0 / 256.0);\n"
693
" float d = texture(uv, texcoord).r - 0.5;\n"
694
" float e = texture(uv, texcoord).g - 0.5;\n"
695
" float r = 1.164383 * c + 1.596027 * e;\n"
696
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
697
" float b = 1.164383 * c + 2.017232 * d;\n"
698
" color = vec4(r, g, b, 1.0);\n"
699
"}\n";
700
}
701
else
702
{
703
yuvVS =
704
"attribute highp vec4 position;\n"
705
"varying vec2 texcoord;\n"
706
"void main(void)\n"
707
"{\n"
708
" gl_Position = position;\n"
709
" texcoord = (position.xy * 0.5) + 0.5;\n"
710
" texcoord.y = 1.0 - texcoord.y;\n"
711
"}\n";
712
713
yuvPS =
714
"#extension GL_NV_EGL_stream_consumer_external : require\n"
715
"precision highp float;\n"
716
"varying vec2 texcoord;\n"
717
"uniform samplerExternalOES y;\n"
718
"uniform samplerExternalOES uv\n;"
719
"void main(void)\n"
720
"{\n"
721
" float c = texture2D(y, texcoord).r - (16.0 / 256.0);\n"
722
" float d = texture2D(uv, texcoord).r - 0.5;\n"
723
" float e = texture2D(uv, texcoord).g - 0.5;\n"
724
" float r = 1.164383 * c + 1.596027 * e;\n"
725
" float g = 1.164383 * c - 0.391762 * d - 0.812968 * e;\n"
726
" float b = 1.164383 * c + 2.017232 * d;\n"
727
" gl_FragColor = vec4(r, g, b, 1.0);\n"
728
"}\n";
729
}
730
731
ANGLE_GL_PROGRAM(program, yuvVS, yuvPS);
732
GLuint yUniform = glGetUniformLocation(program, "y");
733
GLuint uvUniform = glGetUniformLocation(program, "uv");
734
735
// Fetch the D3D11 device
736
EGLDeviceEXT eglDevice;
737
eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, (EGLAttrib *)&eglDevice);
738
ID3D11Device *device;
739
eglQueryDeviceAttribEXT(eglDevice, EGL_D3D11_DEVICE_ANGLE, (EGLAttrib *)&device);
740
741
ANGLE_SKIP_TEST_IF(!CheckNV12TextureSupport(device));
742
743
// Create the NV12 D3D11 texture
744
D3D11_TEXTURE2D_DESC desc;
745
desc.Width = yuvtest_width;
746
desc.Height = yuvtest_height;
747
desc.Format = DXGI_FORMAT_NV12;
748
desc.MipLevels = 1;
749
desc.ArraySize = 1;
750
desc.SampleDesc.Count = 1;
751
desc.SampleDesc.Quality = 0;
752
desc.Usage = D3D11_USAGE_DEFAULT;
753
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
754
desc.CPUAccessFlags = 0;
755
desc.MiscFlags = 0;
756
757
D3D11_SUBRESOURCE_DATA subres;
758
subres.pSysMem = yuvtest_data;
759
subres.SysMemPitch = yuvtest_width;
760
subres.SysMemSlicePitch = yuvtest_width * yuvtest_height * 3 / 2;
761
762
ID3D11Texture2D *texture = nullptr;
763
(void)device->CreateTexture2D(&desc, &subres, &texture);
764
ASSERT_NE(nullptr, texture);
765
766
// Create the stream
767
const EGLint streamAttributes[] = {
768
EGL_CONSUMER_LATENCY_USEC_KHR, 0, EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0, EGL_NONE,
769
};
770
771
EGLStreamKHR stream = eglCreateStreamKHR(display, streamAttributes);
772
ASSERT_EGL_SUCCESS();
773
774
EGLAttrib consumerAttributes[] = {
775
EGL_COLOR_BUFFER_TYPE,
776
EGL_YUV_BUFFER_EXT,
777
EGL_YUV_NUMBER_OF_PLANES_EXT,
778
2,
779
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
780
0,
781
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
782
1,
783
EGL_NONE,
784
};
785
786
GLTexture tex[2];
787
glActiveTexture(GL_TEXTURE0);
788
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
789
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
790
ASSERT_GL_NO_ERROR();
791
glActiveTexture(GL_TEXTURE1);
792
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
793
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
794
ASSERT_GL_NO_ERROR();
795
796
EGLBoolean result =
797
eglStreamConsumerGLTextureExternalAttribsNV(display, stream, consumerAttributes);
798
ASSERT_EGL_TRUE(result);
799
ASSERT_EGL_SUCCESS();
800
801
EGLAttrib producerAttributes[] = {
802
EGL_NONE,
803
};
804
805
result = eglCreateStreamProducerD3DTextureANGLE(display, stream, producerAttributes);
806
ASSERT_EGL_TRUE(result);
807
ASSERT_EGL_SUCCESS();
808
809
// Insert the frame
810
EGLAttrib frameAttributes[] = {
811
EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
812
0,
813
EGL_NONE,
814
};
815
result = eglStreamPostD3DTextureANGLE(display, stream, (void *)texture, frameAttributes);
816
ASSERT_EGL_TRUE(result);
817
ASSERT_EGL_SUCCESS();
818
819
EGLint state;
820
eglQueryStreamKHR(display, stream, EGL_STREAM_STATE_KHR, &state);
821
ASSERT_EGL_SUCCESS();
822
ASSERT_EQ(EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR, state);
823
824
eglStreamConsumerAcquireKHR(display, stream);
825
ASSERT_EGL_SUCCESS();
826
827
glUseProgram(program);
828
glUniform1i(yUniform, 0);
829
glUniform1i(uvUniform, 1);
830
drawQuad(program, "position", 0.0f);
831
ASSERT_GL_NO_ERROR();
832
833
eglStreamConsumerReleaseKHR(display, stream);
834
ASSERT_EGL_SUCCESS();
835
836
eglSwapBuffers(display, window->getSurface());
837
SafeRelease(texture);
838
}
839
840
// Test P010 texture sampling via EGLStreams
841
TEST_P(D3D11TextureStreamSamplingTest, P010)
842
{
843
EGLWindow *window = getEGLWindow();
844
EGLDisplay display = window->getDisplay();
845
ANGLE_SKIP_TEST_IF(
846
!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_stream_producer_d3d_texture"));
847
ANGLE_SKIP_TEST_IF(!CheckP010TextureSupport(mD3D));
848
ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
849
850
constexpr char kVertShader[] = R"(
851
attribute vec4 aPos;
852
varying vec2 vTexCoord;
853
void main()
854
{
855
gl_Position = aPos;
856
vTexCoord = gl_Position.xy * 0.5 + 0.5;
857
})";
858
859
const char kFragShader[] = R"(
860
#extension GL_NV_EGL_stream_consumer_external : require
861
precision mediump float;
862
uniform samplerExternalOES uTexY;
863
uniform samplerExternalOES uTexUV;
864
varying vec2 vTexCoord;
865
void main()
866
{
867
gl_FragColor.r = texture2D(uTexY, vTexCoord).r;
868
gl_FragColor.gb = texture2D(uTexUV, vTexCoord).rg;
869
gl_FragColor.a = 1.0;
870
})";
871
872
ANGLE_GL_PROGRAM(prog, kVertShader, kFragShader);
873
glUseProgram(prog);
874
GLint location = glGetUniformLocation(prog, "uTexY");
875
ASSERT_NE(location, -1);
876
glUniform1i(location, 0);
877
location = glGetUniformLocation(prog, "uTexUV");
878
ASSERT_NE(location, -1);
879
glUniform1i(location, 1);
880
881
ASSERT_GL_NO_ERROR();
882
883
GLTexture tex[2];
884
glActiveTexture(GL_TEXTURE0);
885
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[0]);
886
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
887
ASSERT_GL_NO_ERROR();
888
glActiveTexture(GL_TEXTURE1);
889
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex[1]);
890
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
891
ASSERT_GL_NO_ERROR();
892
893
glActiveTexture(GL_TEXTURE3); // Set to an unused slot to ensure StreamConsumer picks up
894
// the current slot.
895
constexpr EGLAttrib consumerAttributes[] = {
896
EGL_COLOR_BUFFER_TYPE,
897
EGL_YUV_BUFFER_EXT,
898
EGL_YUV_NUMBER_OF_PLANES_EXT,
899
2,
900
EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
901
0,
902
EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
903
1,
904
EGL_NONE,
905
};
906
EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
907
mDisplay, mStream, const_cast<EGLAttrib *>(consumerAttributes));
908
ASSERT_EGL_TRUE(result);
909
ASSERT_EGL_SUCCESS();
910
911
result = eglCreateStreamProducerD3DTextureANGLE(mDisplay, mStream, nullptr);
912
ASSERT_EGL_TRUE(result);
913
ASSERT_EGL_SUCCESS();
914
915
// Create and post the d3d11 texture
916
917
D3D11_TEXTURE2D_DESC desc = {};
918
desc.Width = 2;
919
desc.Height = 2;
920
desc.Format = DXGI_FORMAT_P010;
921
desc.MipLevels = 1;
922
desc.ArraySize = 1;
923
desc.SampleDesc.Count = 1;
924
desc.Usage = D3D11_USAGE_DEFAULT;
925
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
926
927
// DXGI_FORMAT_P010:
928
// Width and height must be even.
929
// Direct3D 11 staging resources and initData parameters for this format use
930
// (rowPitch * (height + (height / 2))) bytes.
931
// The first (SysMemPitch * height) bytes are the Y plane, the remaining
932
// (SysMemPitch * (height / 2)) bytes are the UV plane.
933
constexpr uint16_t texData[] = {0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000};
934
D3D11_SUBRESOURCE_DATA subres;
935
subres.pSysMem = texData;
936
subres.SysMemPitch = 4;
937
938
ID3D11Texture2D *texture = nullptr;
939
(void)mD3D->CreateTexture2D(&desc, &subres, &texture);
940
ASSERT_NE(nullptr, texture);
941
942
result = eglStreamPostD3DTextureANGLE(mDisplay, mStream, (void *)texture, nullptr);
943
ASSERT_EGL_TRUE(result);
944
ASSERT_EGL_SUCCESS();
945
946
// Sample and test
947
948
result = eglStreamConsumerAcquireKHR(mDisplay, mStream);
949
ASSERT_EGL_TRUE(result);
950
ASSERT_EGL_SUCCESS();
951
952
drawQuad(prog, "aPos", 0.0);
953
uint32_t pixel;
954
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
955
ASSERT_EQ(pixel, 0xff605010);
956
957
glReadPixels(1, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
958
ASSERT_EQ(pixel, 0xff605020);
959
960
glReadPixels(0, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
961
ASSERT_EQ(pixel, 0xff605030);
962
963
glReadPixels(1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
964
ASSERT_EQ(pixel, 0xff605040);
965
966
result = eglStreamConsumerReleaseKHR(mDisplay, mStream);
967
ASSERT_EGL_TRUE(result);
968
ASSERT_EGL_SUCCESS();
969
}
970
971
ANGLE_INSTANTIATE_TEST(EGLStreamTest,
972
ES2_D3D9(),
973
ES2_D3D11(),
974
ES3_D3D11(),
975
ES2_OPENGL(),
976
ES3_OPENGL(),
977
ES2_VULKAN());
978
ANGLE_INSTANTIATE_TEST(D3D11TextureStreamSamplingTest, ES2_D3D11(), ES3_D3D11(), ES31_D3D11());
979
} // anonymous namespace
980
981