Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/egl_tests/EGLIOSurfaceClientBufferTest.cpp
1693 views
1
//
2
// Copyright 2017 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
// EGLIOSurfaceClientBufferTest.cpp: tests for the EGL_ANGLE_iosurface_client_buffer extension.
7
//
8
9
#include "test_utils/ANGLETest.h"
10
11
#include "common/mathutil.h"
12
#include "test_utils/gl_raii.h"
13
#include "util/EGLWindow.h"
14
15
#include <CoreFoundation/CoreFoundation.h>
16
#include <IOSurface/IOSurface.h>
17
18
using namespace angle;
19
20
namespace
21
{
22
23
constexpr char kIOSurfaceExt[] = "EGL_ANGLE_iosurface_client_buffer";
24
25
void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
26
{
27
CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
28
CFDictionaryAddValue(dictionary, key, number);
29
CFRelease(number);
30
}
31
32
class ScopedIOSurfaceRef : angle::NonCopyable
33
{
34
public:
35
explicit ScopedIOSurfaceRef(IOSurfaceRef surface) : mSurface(surface) {}
36
37
~ScopedIOSurfaceRef()
38
{
39
if (mSurface != nullptr)
40
{
41
CFRelease(mSurface);
42
mSurface = nullptr;
43
}
44
}
45
46
IOSurfaceRef get() const { return mSurface; }
47
48
ScopedIOSurfaceRef(ScopedIOSurfaceRef &&other)
49
{
50
if (mSurface != nullptr)
51
{
52
CFRelease(mSurface);
53
}
54
mSurface = other.mSurface;
55
other.mSurface = nullptr;
56
}
57
58
ScopedIOSurfaceRef &operator=(ScopedIOSurfaceRef &&other)
59
{
60
if (mSurface != nullptr)
61
{
62
CFRelease(mSurface);
63
}
64
mSurface = other.mSurface;
65
other.mSurface = nullptr;
66
67
return *this;
68
}
69
70
private:
71
IOSurfaceRef mSurface = nullptr;
72
};
73
74
struct IOSurfacePlaneInfo
75
{
76
int width;
77
int height;
78
int bytesPerElement;
79
};
80
81
ScopedIOSurfaceRef CreateIOSurface(int32_t format, const std::vector<IOSurfacePlaneInfo> &planes)
82
{
83
EXPECT_GT(planes.size(), 0u);
84
85
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
86
kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
87
AddIntegerValue(dict, kIOSurfaceWidth, planes[0].width);
88
AddIntegerValue(dict, kIOSurfaceHeight, planes[0].height);
89
AddIntegerValue(dict, kIOSurfacePixelFormat, format);
90
91
if (planes.size() > 1)
92
{
93
CFMutableArrayRef planesInfo =
94
CFArrayCreateMutable(kCFAllocatorDefault, planes.size(), &kCFTypeArrayCallBacks);
95
for (const IOSurfacePlaneInfo &plane : planes)
96
{
97
CFMutableDictionaryRef planeInfo =
98
CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
99
&kCFTypeDictionaryValueCallBacks);
100
AddIntegerValue(planeInfo, kIOSurfacePlaneWidth, plane.width);
101
AddIntegerValue(planeInfo, kIOSurfacePlaneHeight, plane.height);
102
AddIntegerValue(planeInfo, kIOSurfacePlaneBytesPerElement, plane.bytesPerElement);
103
104
CFArrayAppendValue(planesInfo, planeInfo);
105
CFRelease(planeInfo);
106
}
107
108
CFDictionaryAddValue(dict, kIOSurfacePlaneInfo, planesInfo);
109
CFRelease(planesInfo);
110
}
111
else
112
{
113
AddIntegerValue(dict, kIOSurfaceBytesPerElement, planes[0].bytesPerElement);
114
}
115
116
IOSurfaceRef ioSurface = IOSurfaceCreate(dict);
117
EXPECT_NE(nullptr, ioSurface);
118
CFRelease(dict);
119
120
return ScopedIOSurfaceRef(ioSurface);
121
}
122
123
ScopedIOSurfaceRef CreateSinglePlaneIOSurface(int width,
124
int height,
125
int32_t format,
126
int bytesPerElement)
127
{
128
std::vector<IOSurfacePlaneInfo> planes{{width, height, bytesPerElement}};
129
return CreateIOSurface(format, planes);
130
}
131
132
} // anonymous namespace
133
134
class IOSurfaceClientBufferTest : public ANGLETest
135
{
136
protected:
137
EGLint getTextureTarget() const
138
{
139
EGLint target = 0;
140
eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &target);
141
return target;
142
}
143
144
GLint getGLTextureTarget() const
145
{
146
EGLint targetEGL = getTextureTarget();
147
GLenum targetGL = 0;
148
switch (targetEGL)
149
{
150
case EGL_TEXTURE_2D:
151
targetGL = GL_TEXTURE_2D;
152
break;
153
case EGL_TEXTURE_RECTANGLE_ANGLE:
154
targetGL = GL_TEXTURE_RECTANGLE_ANGLE;
155
break;
156
default:
157
break;
158
}
159
return targetGL;
160
}
161
162
IOSurfaceClientBufferTest() : mConfig(0), mDisplay(nullptr) {}
163
164
void testSetUp() override
165
{
166
mConfig = getEGLWindow()->getConfig();
167
mDisplay = getEGLWindow()->getDisplay();
168
}
169
170
void createIOSurfacePbuffer(const ScopedIOSurfaceRef &ioSurface,
171
EGLint width,
172
EGLint height,
173
EGLint plane,
174
GLenum internalFormat,
175
GLenum type,
176
EGLSurface *pbuffer) const
177
{
178
// clang-format off
179
const EGLint attribs[] = {
180
EGL_WIDTH, width,
181
EGL_HEIGHT, height,
182
EGL_IOSURFACE_PLANE_ANGLE, plane,
183
EGL_TEXTURE_TARGET, getTextureTarget(),
184
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
185
static_cast<EGLint>(internalFormat),
186
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
187
EGL_TEXTURE_TYPE_ANGLE, static_cast<EGLint>(type),
188
EGL_NONE, EGL_NONE,
189
};
190
// clang-format on
191
192
*pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE, ioSurface.get(),
193
mConfig, attribs);
194
EXPECT_NE(EGL_NO_SURFACE, *pbuffer);
195
}
196
197
void bindIOSurfaceToTexture(const ScopedIOSurfaceRef &ioSurface,
198
EGLint width,
199
EGLint height,
200
EGLint plane,
201
GLenum internalFormat,
202
GLenum type,
203
EGLSurface *pbuffer,
204
GLTexture *texture) const
205
{
206
createIOSurfacePbuffer(ioSurface, width, height, plane, internalFormat, type, pbuffer);
207
208
// Bind the pbuffer
209
glBindTexture(getGLTextureTarget(), *texture);
210
EGLBoolean result = eglBindTexImage(mDisplay, *pbuffer, EGL_BACK_BUFFER);
211
EXPECT_EGL_TRUE(result);
212
EXPECT_EGL_SUCCESS();
213
}
214
215
void doClearTest(const ScopedIOSurfaceRef &ioSurface,
216
EGLint width,
217
EGLint height,
218
EGLint plane,
219
GLenum internalFormat,
220
GLenum type,
221
const GLColor &data)
222
{
223
std::array<uint8_t, 4> dataArray{data.R, data.G, data.B, data.A};
224
doClearTest(ioSurface, width, height, plane, internalFormat, type, dataArray);
225
}
226
227
template <typename T, size_t dataSize>
228
void doClearTest(const ScopedIOSurfaceRef &ioSurface,
229
EGLint width,
230
EGLint height,
231
EGLint plane,
232
GLenum internalFormat,
233
GLenum type,
234
const std::array<T, dataSize> &data)
235
{
236
// Bind the IOSurface to a texture and clear it.
237
EGLSurface pbuffer;
238
GLTexture texture;
239
bindIOSurfaceToTexture(ioSurface, width, height, plane, internalFormat, type, &pbuffer,
240
&texture);
241
242
GLFramebuffer fbo;
243
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
244
EXPECT_GL_NO_ERROR();
245
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getGLTextureTarget(), texture,
246
0);
247
EXPECT_GL_NO_ERROR();
248
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
249
EXPECT_GL_NO_ERROR();
250
251
glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f);
252
EXPECT_GL_NO_ERROR();
253
glClear(GL_COLOR_BUFFER_BIT);
254
EXPECT_GL_NO_ERROR();
255
256
// Unbind pbuffer and check content.
257
EGLBoolean result = eglReleaseTexImage(mDisplay, pbuffer, EGL_BACK_BUFFER);
258
EXPECT_EGL_TRUE(result);
259
EXPECT_EGL_SUCCESS();
260
261
// IOSurface client buffer's rendering doesn't automatically finish after
262
// eglReleaseTexImage(). Need to explicitly call glFinish().
263
glFinish();
264
265
IOSurfaceLock(ioSurface.get(), kIOSurfaceLockReadOnly, nullptr);
266
std::array<T, dataSize> iosurfaceData;
267
memcpy(iosurfaceData.data(), IOSurfaceGetBaseAddressOfPlane(ioSurface.get(), plane),
268
sizeof(T) * data.size());
269
IOSurfaceUnlock(ioSurface.get(), kIOSurfaceLockReadOnly, nullptr);
270
271
if (internalFormat == GL_RGB && IsOSX() && IsOpenGL())
272
{
273
// Ignore alpha component for BGRX, the alpha value is undefined
274
for (int i = 0; i < 3; i++)
275
{
276
ASSERT_EQ(data[i], iosurfaceData[i]);
277
}
278
}
279
else
280
{
281
ASSERT_EQ(data, iosurfaceData);
282
}
283
284
result = eglDestroySurface(mDisplay, pbuffer);
285
EXPECT_EGL_TRUE(result);
286
EXPECT_EGL_SUCCESS();
287
}
288
289
enum ColorMask
290
{
291
R = 1,
292
G = 2,
293
B = 4,
294
A = 8,
295
};
296
void doSampleTest(const ScopedIOSurfaceRef &ioSurface,
297
EGLint width,
298
EGLint height,
299
EGLint plane,
300
GLenum internalFormat,
301
GLenum type,
302
void *data,
303
size_t dataSize,
304
int mask)
305
{
306
// Write the data to the IOSurface
307
IOSurfaceLock(ioSurface.get(), 0, nullptr);
308
memcpy(IOSurfaceGetBaseAddressOfPlane(ioSurface.get(), plane), data, dataSize);
309
IOSurfaceUnlock(ioSurface.get(), 0, nullptr);
310
311
GLTexture texture;
312
glBindTexture(getGLTextureTarget(), texture);
313
glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
314
glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
315
316
// Bind the IOSurface to a texture and clear it.
317
EGLSurface pbuffer;
318
bindIOSurfaceToTexture(ioSurface, width, height, plane, internalFormat, type, &pbuffer,
319
&texture);
320
321
doSampleTestWithTexture(texture, mask);
322
323
EGLBoolean result = eglDestroySurface(mDisplay, pbuffer);
324
EXPECT_EGL_TRUE(result);
325
EXPECT_EGL_SUCCESS();
326
}
327
328
void doSampleTestWithTexture(const GLTexture &texture, int mask)
329
{
330
constexpr char kVS[] =
331
"attribute vec4 position;\n"
332
"void main()\n"
333
"{\n"
334
" gl_Position = vec4(position.xy, 0.0, 1.0);\n"
335
"}\n";
336
constexpr char kFS_rect[] =
337
"#extension GL_ARB_texture_rectangle : require\n"
338
"precision mediump float;\n"
339
"uniform sampler2DRect tex;\n"
340
"void main()\n"
341
"{\n"
342
" gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
343
"}\n";
344
constexpr char kFS_2D[] =
345
"precision mediump float;\n"
346
"uniform sampler2D tex;\n"
347
"void main()\n"
348
"{\n"
349
" gl_FragColor = texture2D(tex, vec2(0, 0));\n"
350
"}\n";
351
352
ANGLE_GL_PROGRAM(program, kVS,
353
(getTextureTarget() == EGL_TEXTURE_RECTANGLE_ANGLE ? kFS_rect : kFS_2D));
354
glUseProgram(program);
355
356
GLint location = glGetUniformLocation(program, "tex");
357
ASSERT_NE(-1, location);
358
glUniform1i(location, 0);
359
360
glClearColor(0.0, 0.0, 0.0, 0.0);
361
glClear(GL_COLOR_BUFFER_BIT);
362
drawQuad(program, "position", 0.5f, 1.0f, false);
363
364
GLColor expectedColor((mask & R) ? 1 : 0, (mask & G) ? 2 : 0, (mask & B) ? 3 : 0,
365
(mask & A) ? 4 : 255);
366
EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor);
367
ASSERT_GL_NO_ERROR();
368
}
369
370
void doBlitTest(bool ioSurfaceIsSource, int width, int height)
371
{
372
if (!hasBlitExt())
373
{
374
return;
375
}
376
377
// Create IOSurface and bind it to a texture.
378
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(width, height, 'BGRA', 4);
379
EGLSurface pbuffer;
380
GLTexture texture;
381
bindIOSurfaceToTexture(ioSurface, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &pbuffer,
382
&texture);
383
384
GLFramebuffer iosurfaceFbo;
385
glBindFramebuffer(GL_FRAMEBUFFER, iosurfaceFbo);
386
EXPECT_GL_NO_ERROR();
387
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getGLTextureTarget(), texture,
388
0);
389
EXPECT_GL_NO_ERROR();
390
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
391
EXPECT_GL_NO_ERROR();
392
393
// Create another framebuffer with a regular renderbuffer.
394
GLFramebuffer fbo;
395
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
396
EXPECT_GL_NO_ERROR();
397
GLRenderbuffer rbo;
398
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
399
EXPECT_GL_NO_ERROR();
400
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
401
EXPECT_GL_NO_ERROR();
402
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
403
EXPECT_GL_NO_ERROR();
404
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
405
EXPECT_GL_NO_ERROR();
406
407
glBindRenderbuffer(GL_RENDERBUFFER, 0);
408
EXPECT_GL_NO_ERROR();
409
glBindFramebuffer(GL_FRAMEBUFFER, 0);
410
EXPECT_GL_NO_ERROR();
411
412
// Choose which is going to be the source and destination.
413
GLFramebuffer &src = ioSurfaceIsSource ? iosurfaceFbo : fbo;
414
GLFramebuffer &dst = ioSurfaceIsSource ? fbo : iosurfaceFbo;
415
416
// Clear source to known color.
417
glBindFramebuffer(GL_FRAMEBUFFER, src);
418
glClearColor(1.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 4.0f / 255.0f);
419
EXPECT_GL_NO_ERROR();
420
glClear(GL_COLOR_BUFFER_BIT);
421
EXPECT_GL_NO_ERROR();
422
423
// Blit to destination.
424
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, dst);
425
glBlitFramebufferANGLE(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
426
GL_NEAREST);
427
428
// Read back from destination.
429
glBindFramebuffer(GL_FRAMEBUFFER, dst);
430
GLColor expectedColor(1, 2, 3, 4);
431
EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor);
432
433
// Unbind pbuffer and check content.
434
EGLBoolean result = eglReleaseTexImage(mDisplay, pbuffer, EGL_BACK_BUFFER);
435
EXPECT_EGL_TRUE(result);
436
EXPECT_EGL_SUCCESS();
437
438
result = eglDestroySurface(mDisplay, pbuffer);
439
EXPECT_EGL_TRUE(result);
440
EXPECT_EGL_SUCCESS();
441
}
442
443
bool hasIOSurfaceExt() const { return IsEGLDisplayExtensionEnabled(mDisplay, kIOSurfaceExt); }
444
bool hasBlitExt() const
445
{
446
return IsEGLDisplayExtensionEnabled(mDisplay, "ANGLE_framebuffer_blit");
447
}
448
449
EGLConfig mConfig;
450
EGLDisplay mDisplay;
451
};
452
453
// Test using BGRA8888 IOSurfaces for rendering
454
TEST_P(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
455
{
456
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
457
458
// TODO(http://anglebug.com/4369)
459
ANGLE_SKIP_TEST_IF(isSwiftshader());
460
461
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
462
463
GLColor color(3, 2, 1, 4);
464
doClearTest(ioSurface, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, color);
465
}
466
467
// Test reading from BGRA8888 IOSurfaces
468
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
469
{
470
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
471
472
// TODO(http://anglebug.com/4369)
473
ANGLE_SKIP_TEST_IF(isSwiftshader());
474
475
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
476
477
GLColor color(3, 2, 1, 4);
478
doSampleTest(ioSurface, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &color, sizeof(color),
479
R | G | B | A);
480
}
481
482
// Test using BGRX8888 IOSurfaces for rendering
483
TEST_P(IOSurfaceClientBufferTest, RenderToBGRX8888IOSurface)
484
{
485
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
486
487
// TODO(http://anglebug.com/4369)
488
ANGLE_SKIP_TEST_IF(isSwiftshader());
489
490
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
491
492
GLColor color(3, 2, 1, 255);
493
doClearTest(ioSurface, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, color);
494
}
495
496
// Test reading from BGRX8888 IOSurfaces
497
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRX8888IOSurface)
498
{
499
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
500
501
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
502
503
GLColor color(3, 2, 1, 4);
504
doSampleTest(ioSurface, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, &color, sizeof(color), R | G | B);
505
}
506
507
// Test using RG88 IOSurfaces for rendering
508
TEST_P(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
509
{
510
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
511
512
// TODO(http://anglebug.com/4369)
513
ANGLE_SKIP_TEST_IF(isSwiftshader());
514
515
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2);
516
517
std::array<uint8_t, 2> color{1, 2};
518
doClearTest(ioSurface, 1, 1, 0, GL_RG, GL_UNSIGNED_BYTE, color);
519
}
520
521
// Test reading from RG88 IOSurfaces
522
TEST_P(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
523
{
524
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
525
526
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, '2C08', 2);
527
528
uint8_t color[2] = {1, 2};
529
doSampleTest(ioSurface, 1, 1, 0, GL_RG, GL_UNSIGNED_BYTE, &color, sizeof(color), R | G);
530
}
531
532
// Test using R8 IOSurfaces for rendering
533
TEST_P(IOSurfaceClientBufferTest, RenderToR8IOSurface)
534
{
535
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
536
537
// TODO(http://anglebug.com/4369)
538
ANGLE_SKIP_TEST_IF(isSwiftshader());
539
540
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1);
541
542
std::array<uint8_t, 1> color{1};
543
doClearTest(ioSurface, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, color);
544
}
545
546
// Test reading from R8 IOSurfaces
547
TEST_P(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
548
{
549
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
550
551
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L008', 1);
552
553
uint8_t color = 1;
554
doSampleTest(ioSurface, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &color, sizeof(color), R);
555
}
556
557
// Test using R16 IOSurfaces for rendering
558
TEST_P(IOSurfaceClientBufferTest, RenderToR16IOSurface)
559
{
560
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
561
562
// This test only works on ES3 since it requires an integer texture.
563
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
564
565
// TODO(http://anglebug.com/4369)
566
ANGLE_SKIP_TEST_IF(isSwiftshader());
567
568
// HACK([email protected]) 'L016' doesn't seem to be an official pixel format but it works
569
// sooooooo let's test using it
570
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'L016', 2);
571
572
std::array<uint16_t, 1> color{257};
573
doClearTest(ioSurface, 1, 1, 0, GL_R16UI, GL_UNSIGNED_SHORT, color);
574
}
575
// TODO([email protected]): test reading from R16? It returns 0 maybe because samplerRect is
576
// only for floating textures?
577
578
// Test using BGRA_1010102 IOSurfaces for rendering
579
TEST_P(IOSurfaceClientBufferTest, RenderToBGRA1010102IOSurface)
580
{
581
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
582
583
// TODO(http://anglebug.com/4369)
584
ANGLE_SKIP_TEST_IF(isSwiftshader());
585
586
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'l10r', 4);
587
588
std::array<uint32_t, 1> color{(0 << 30) | (1 << 22) | (2 << 12) | (3 << 2)};
589
doClearTest(ioSurface, 1, 1, 0, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, color);
590
}
591
592
// Test reading from BGRA_1010102 IOSurfaces
593
TEST_P(IOSurfaceClientBufferTest, ReadFromBGRA1010102IOSurface)
594
{
595
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
596
597
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'l10r', 4);
598
599
uint32_t color = (3 << 30) | (1 << 22) | (2 << 12) | (3 << 2);
600
doSampleTest(ioSurface, 1, 1, 0, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, &color,
601
sizeof(color),
602
R | G | B); // Don't test alpha, unorm '4' can't be represented with 2 bits.
603
}
604
605
// Test using RGBA_16F IOSurfaces for rendering
606
TEST_P(IOSurfaceClientBufferTest, RenderToRGBA16FIOSurface)
607
{
608
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
609
610
// TODO(http://anglebug.com/4369)
611
ANGLE_SKIP_TEST_IF(isSwiftshader());
612
613
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'RGhA', 8);
614
615
std::array<GLushort, 4> color{
616
gl::float32ToFloat16(1.0f / 255.0f), gl::float32ToFloat16(2.0f / 255.0f),
617
gl::float32ToFloat16(3.0f / 255.0f), gl::float32ToFloat16(4.0f / 255.0f)};
618
doClearTest(ioSurface, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT, color);
619
}
620
621
// Test reading from RGBA_16F IOSurfaces
622
TEST_P(IOSurfaceClientBufferTest, ReadFromToRGBA16FIOSurface)
623
{
624
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
625
626
// TODO(http://anglebug.com/4369)
627
ANGLE_SKIP_TEST_IF(isSwiftshader());
628
629
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'RGhA', 8);
630
631
std::array<GLushort, 4> color{
632
gl::float32ToFloat16(1.0f / 255.0f), gl::float32ToFloat16(2.0f / 255.0f),
633
gl::float32ToFloat16(3.0f / 255.0f), gl::float32ToFloat16(4.0f / 255.0f)};
634
doSampleTest(ioSurface, 1, 1, 0, GL_RGBA, GL_HALF_FLOAT, color.data(), sizeof(GLushort) * 4,
635
R | G | B | A);
636
}
637
638
// Test using YUV420 IOSurfaces for rendering
639
TEST_P(IOSurfaceClientBufferTest, RenderToYUV420IOSurface)
640
{
641
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
642
643
// TODO(http://anglebug.com/4369)
644
ANGLE_SKIP_TEST_IF(isSwiftshader());
645
646
std::vector<IOSurfacePlaneInfo> planes{{2, 2, 1}, {1, 1, 2}};
647
ScopedIOSurfaceRef ioSurface = CreateIOSurface('420v', planes);
648
649
{
650
std::array<GLubyte, 1> colors{1};
651
doClearTest(ioSurface, planes[0].width, planes[0].height, 0, GL_RED, GL_UNSIGNED_BYTE,
652
colors);
653
}
654
655
{
656
std::array<GLubyte, 2> colors{1, 2};
657
doClearTest(ioSurface, planes[1].width, planes[1].height, 1, GL_RG, GL_UNSIGNED_BYTE,
658
colors);
659
}
660
}
661
662
// Test reading from YUV420 IOSurfaces
663
TEST_P(IOSurfaceClientBufferTest, ReadFromToYUV420IOSurface)
664
{
665
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
666
667
// TODO(http://anglebug.com/4369)
668
ANGLE_SKIP_TEST_IF(isSwiftshader());
669
670
std::vector<IOSurfacePlaneInfo> planes{{2, 2, 1}, {1, 1, 2}};
671
ScopedIOSurfaceRef ioSurface = CreateIOSurface('420v', planes);
672
673
{
674
std::array<GLubyte, 1> colors{1};
675
doSampleTest(ioSurface, planes[0].width, planes[0].height, 0, GL_RED, GL_UNSIGNED_BYTE,
676
colors.data(), sizeof(GLubyte) * colors.size(), R);
677
}
678
679
{
680
std::array<GLubyte, 2> colors{1, 2};
681
doSampleTest(ioSurface, planes[1].width, planes[1].height, 1, GL_RG, GL_UNSIGNED_BYTE,
682
colors.data(), sizeof(GLubyte) * colors.size(), R | G);
683
}
684
}
685
686
// Test using P010 IOSurfaces for rendering
687
TEST_P(IOSurfaceClientBufferTest, RenderToP010IOSurface)
688
{
689
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
690
691
// TODO(http://anglebug.com/4369)
692
ANGLE_SKIP_TEST_IF(isSwiftshader());
693
694
std::vector<IOSurfacePlaneInfo> planes{{2, 2, 2}, {1, 1, 4}};
695
ScopedIOSurfaceRef ioSurface = CreateIOSurface('x420', planes);
696
697
{
698
std::array<GLushort, 1> colors{257};
699
doClearTest(ioSurface, planes[0].width, planes[0].height, 0, GL_RED, GL_UNSIGNED_SHORT,
700
colors);
701
}
702
703
{
704
std::array<GLushort, 2> colors{257, 514};
705
doClearTest(ioSurface, planes[1].width, planes[1].height, 1, GL_RG, GL_UNSIGNED_SHORT,
706
colors);
707
}
708
}
709
710
// Test reading from P010 IOSurfaces
711
TEST_P(IOSurfaceClientBufferTest, ReadFromToP010IOSurface)
712
{
713
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
714
715
// TODO(http://anglebug.com/4369)
716
ANGLE_SKIP_TEST_IF(isSwiftshader());
717
718
std::vector<IOSurfacePlaneInfo> planes{{2, 2, 2}, {1, 1, 4}};
719
ScopedIOSurfaceRef ioSurface = CreateIOSurface('x420', planes);
720
721
{
722
std::array<GLushort, 1> colors{257};
723
doSampleTest(ioSurface, planes[0].width, planes[0].height, 0, GL_RED, GL_UNSIGNED_SHORT,
724
colors.data(), sizeof(GLushort) * colors.size(), R);
725
}
726
727
{
728
std::array<GLushort, 2> colors{257, 514};
729
doSampleTest(ioSurface, planes[1].width, planes[1].height, 1, GL_RG, GL_UNSIGNED_SHORT,
730
colors.data(), sizeof(GLushort) * colors.size(), R | G);
731
}
732
}
733
734
// Test blitting from IOSurface
735
TEST_P(IOSurfaceClientBufferTest, BlitFromIOSurface)
736
{
737
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
738
739
doBlitTest(true, 2, 2);
740
}
741
742
// Test blitting to IOSurface
743
TEST_P(IOSurfaceClientBufferTest, BlitToIOSurface)
744
{
745
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
746
747
doBlitTest(false, 2, 2);
748
}
749
750
// Test using glCopyTexSubImage to copy to BGRX8888 IOSurfaces works.
751
TEST_P(IOSurfaceClientBufferTest, CopySubImageToBGRX8888IOSurface)
752
{
753
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
754
755
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(1, 1, 'BGRA', 4);
756
757
GLTexture texture;
758
glBindTexture(getGLTextureTarget(), texture);
759
glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
760
glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
761
762
// Bind the IOSurface to a texture and clear it.
763
EGLSurface pbuffer;
764
bindIOSurfaceToTexture(ioSurface, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, &pbuffer, &texture);
765
766
// 1. Clear default framebuffer with desired color.
767
GLColor color(1, 2, 3, 4);
768
glClearColor(color.R / 255.f, color.G / 255.f, color.B / 255.f, color.A / 255.f);
769
glClear(GL_COLOR_BUFFER_BIT);
770
771
// 2. Copy color from default framebuffer to iosurface's bound texture.
772
glCopyTexSubImage2D(getGLTextureTarget(), 0, 0, 0, 0, 0, 1, 1);
773
EXPECT_GL_NO_ERROR();
774
775
// 3. Do texture sampling verification.
776
doSampleTestWithTexture(texture, R | G | B);
777
}
778
779
// Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with
780
// IOSurface
781
TEST_P(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
782
{
783
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
784
785
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
786
787
// Success case
788
{
789
// clang-format off
790
const EGLint attribs[] = {
791
EGL_WIDTH, 10,
792
EGL_HEIGHT, 10,
793
EGL_IOSURFACE_PLANE_ANGLE, 0,
794
EGL_TEXTURE_TARGET, getTextureTarget(),
795
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
796
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
797
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
798
EGL_NONE, EGL_NONE,
799
};
800
// clang-format off
801
802
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE, ioSurface.get(), mConfig, attribs);
803
EXPECT_NE(EGL_NO_SURFACE, pbuffer);
804
805
EGLBoolean result = eglDestroySurface(mDisplay, pbuffer);
806
EXPECT_EGL_TRUE(result);
807
EXPECT_EGL_SUCCESS();
808
}
809
810
// Missing EGL_WIDTH
811
{
812
// clang-format off
813
const EGLint attribs[] = {
814
EGL_HEIGHT, 10,
815
EGL_IOSURFACE_PLANE_ANGLE, 0,
816
EGL_TEXTURE_TARGET, getTextureTarget(),
817
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
818
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
819
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
820
EGL_NONE, EGL_NONE,
821
};
822
// clang-format on
823
824
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
825
ioSurface.get(), mConfig, attribs);
826
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
827
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
828
}
829
830
// Missing EGL_HEIGHT
831
{
832
// clang-format off
833
const EGLint attribs[] = {
834
EGL_WIDTH, 10,
835
EGL_IOSURFACE_PLANE_ANGLE, 0,
836
EGL_TEXTURE_TARGET, getTextureTarget(),
837
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
838
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
839
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
840
EGL_NONE, EGL_NONE,
841
};
842
// clang-format on
843
844
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
845
ioSurface.get(), mConfig, attribs);
846
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
847
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
848
}
849
850
// Missing EGL_IOSURFACE_PLANE_ANGLE
851
{
852
// clang-format off
853
const EGLint attribs[] = {
854
EGL_WIDTH, 10,
855
EGL_HEIGHT, 10,
856
EGL_TEXTURE_TARGET, getTextureTarget(),
857
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
858
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
859
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
860
EGL_NONE, EGL_NONE,
861
};
862
// clang-format on
863
864
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
865
ioSurface.get(), mConfig, attribs);
866
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
867
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
868
}
869
870
// Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of
871
// eglCreatePbufferFromClientBuffer
872
{
873
// clang-format off
874
const EGLint attribs[] = {
875
EGL_WIDTH, 10,
876
EGL_HEIGHT, 10,
877
EGL_IOSURFACE_PLANE_ANGLE, 0,
878
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
879
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
880
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
881
EGL_NONE, EGL_NONE,
882
};
883
// clang-format on
884
885
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
886
ioSurface.get(), mConfig, attribs);
887
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
888
EXPECT_EGL_ERROR(EGL_BAD_MATCH);
889
}
890
891
// Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE
892
{
893
// clang-format off
894
const EGLint attribs[] = {
895
EGL_WIDTH, 10,
896
EGL_HEIGHT, 10,
897
EGL_IOSURFACE_PLANE_ANGLE, 0,
898
EGL_TEXTURE_TARGET, getTextureTarget(),
899
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
900
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
901
EGL_NONE, EGL_NONE,
902
};
903
// clang-format on
904
905
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
906
ioSurface.get(), mConfig, attribs);
907
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
908
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
909
}
910
911
// Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of
912
// eglCreatePbufferFromClientBuffer
913
{
914
// clang-format off
915
const EGLint attribs[] = {
916
EGL_WIDTH, 10,
917
EGL_HEIGHT, 10,
918
EGL_IOSURFACE_PLANE_ANGLE, 0,
919
EGL_TEXTURE_TARGET, getTextureTarget(),
920
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
921
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
922
EGL_NONE, EGL_NONE,
923
};
924
// clang-format on
925
926
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
927
ioSurface.get(), mConfig, attribs);
928
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
929
EXPECT_EGL_ERROR(EGL_BAD_MATCH);
930
}
931
932
// Missing EGL_TEXTURE_TYPE_ANGLE
933
{
934
// clang-format off
935
const EGLint attribs[] = {
936
EGL_WIDTH, 10,
937
EGL_HEIGHT, 10,
938
EGL_IOSURFACE_PLANE_ANGLE, 0,
939
EGL_TEXTURE_TARGET, getTextureTarget(),
940
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
941
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
942
EGL_NONE, EGL_NONE,
943
};
944
// clang-format on
945
946
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
947
ioSurface.get(), mConfig, attribs);
948
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
949
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
950
}
951
}
952
953
// Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
954
TEST_P(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
955
{
956
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
957
958
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
959
960
// Success case
961
{
962
// clang-format off
963
const EGLint attribs[] = {
964
EGL_WIDTH, 10,
965
EGL_HEIGHT, 10,
966
EGL_IOSURFACE_PLANE_ANGLE, 0,
967
EGL_TEXTURE_TARGET, getTextureTarget(),
968
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
969
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
970
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
971
EGL_NONE, EGL_NONE,
972
};
973
// clang-format off
974
975
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE, ioSurface.get(), mConfig, attribs);
976
EXPECT_NE(EGL_NO_SURFACE, pbuffer);
977
978
EGLBoolean result = eglDestroySurface(mDisplay, pbuffer);
979
EXPECT_EGL_TRUE(result);
980
EXPECT_EGL_SUCCESS();
981
}
982
983
// EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA
984
{
985
// clang-format off
986
const EGLint attribs[] = {
987
EGL_WIDTH, 10,
988
EGL_HEIGHT, 10,
989
EGL_IOSURFACE_PLANE_ANGLE, 0,
990
EGL_TEXTURE_TARGET, getTextureTarget(),
991
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
992
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
993
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
994
EGL_NONE, EGL_NONE,
995
};
996
// clang-format on
997
998
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
999
ioSurface.get(), mConfig, attribs);
1000
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1001
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1002
}
1003
1004
// EGL_WIDTH must be at least 1
1005
{
1006
// clang-format off
1007
const EGLint attribs[] = {
1008
EGL_WIDTH, 0,
1009
EGL_HEIGHT, 10,
1010
EGL_IOSURFACE_PLANE_ANGLE, 0,
1011
EGL_TEXTURE_TARGET, getTextureTarget(),
1012
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1013
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1014
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1015
EGL_NONE, EGL_NONE,
1016
};
1017
// clang-format on
1018
1019
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1020
ioSurface.get(), mConfig, attribs);
1021
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1022
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1023
}
1024
1025
// EGL_WIDTH must be at most the width of the IOSurface
1026
{
1027
// clang-format off
1028
const EGLint attribs[] = {
1029
EGL_WIDTH, 11,
1030
EGL_HEIGHT, 10,
1031
EGL_IOSURFACE_PLANE_ANGLE, 0,
1032
EGL_TEXTURE_TARGET, getTextureTarget(),
1033
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1034
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1035
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1036
EGL_NONE, EGL_NONE,
1037
};
1038
// clang-format on
1039
1040
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1041
ioSurface.get(), mConfig, attribs);
1042
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1043
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1044
}
1045
1046
// EGL_HEIGHT must be at least 1
1047
{
1048
// clang-format off
1049
const EGLint attribs[] = {
1050
EGL_WIDTH, 10,
1051
EGL_HEIGHT, 0,
1052
EGL_IOSURFACE_PLANE_ANGLE, 0,
1053
EGL_TEXTURE_TARGET, getTextureTarget(),
1054
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1055
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1056
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1057
EGL_NONE, EGL_NONE,
1058
};
1059
// clang-format on
1060
1061
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1062
ioSurface.get(), mConfig, attribs);
1063
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1064
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1065
}
1066
1067
// EGL_HEIGHT must be at most the height of the IOSurface
1068
{
1069
// clang-format off
1070
const EGLint attribs[] = {
1071
EGL_WIDTH, 10,
1072
EGL_HEIGHT, 11,
1073
EGL_IOSURFACE_PLANE_ANGLE, 0,
1074
EGL_TEXTURE_TARGET, getTextureTarget(),
1075
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1076
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1077
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1078
EGL_NONE, EGL_NONE,
1079
};
1080
// clang-format on
1081
1082
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1083
ioSurface.get(), mConfig, attribs);
1084
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1085
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1086
}
1087
1088
// EGL_TEXTURE_FORMAT must be equal to the config's texture target
1089
{
1090
EGLint target = getTextureTarget();
1091
EGLint wrongTarget = 0;
1092
switch (target)
1093
{
1094
case EGL_TEXTURE_RECTANGLE_ANGLE:
1095
wrongTarget = EGL_TEXTURE_2D;
1096
break;
1097
case EGL_TEXTURE_2D:
1098
wrongTarget = EGL_TEXTURE_RECTANGLE_ANGLE;
1099
break;
1100
default:
1101
break;
1102
}
1103
// clang-format off
1104
const EGLint attribs[] = {
1105
EGL_WIDTH, 10,
1106
EGL_HEIGHT, 10,
1107
EGL_IOSURFACE_PLANE_ANGLE, 0,
1108
EGL_TEXTURE_TARGET, wrongTarget,
1109
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1110
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1111
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1112
EGL_NONE, EGL_NONE,
1113
};
1114
// clang-format on
1115
1116
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1117
ioSurface.get(), mConfig, attribs);
1118
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1119
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1120
}
1121
1122
// EGL_IOSURFACE_PLANE_ANGLE must be at least 0
1123
{
1124
// clang-format off
1125
const EGLint attribs[] = {
1126
EGL_WIDTH, 10,
1127
EGL_HEIGHT, 10,
1128
EGL_IOSURFACE_PLANE_ANGLE, -1,
1129
EGL_TEXTURE_TARGET, getTextureTarget(),
1130
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1131
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1132
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1133
EGL_NONE, EGL_NONE,
1134
};
1135
// clang-format on
1136
1137
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1138
ioSurface.get(), mConfig, attribs);
1139
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1140
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1141
}
1142
1143
// EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface
1144
{
1145
// clang-format off
1146
const EGLint attribs[] = {
1147
EGL_WIDTH, 10,
1148
EGL_HEIGHT, 10,
1149
EGL_IOSURFACE_PLANE_ANGLE, 1,
1150
EGL_TEXTURE_TARGET, getTextureTarget(),
1151
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1152
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1153
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1154
EGL_NONE, EGL_NONE,
1155
};
1156
// clang-format on
1157
1158
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1159
ioSurface.get(), mConfig, attribs);
1160
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1161
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1162
}
1163
1164
// The internal format / type most be listed in the table
1165
{
1166
// clang-format off
1167
const EGLint attribs[] = {
1168
EGL_WIDTH, 10,
1169
EGL_HEIGHT, 10,
1170
EGL_IOSURFACE_PLANE_ANGLE, 0,
1171
EGL_TEXTURE_TARGET, getTextureTarget(),
1172
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA,
1173
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1174
EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
1175
EGL_NONE, EGL_NONE,
1176
};
1177
// clang-format on
1178
1179
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(mDisplay, EGL_IOSURFACE_ANGLE,
1180
ioSurface.get(), mConfig, attribs);
1181
EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1182
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1183
}
1184
}
1185
1186
// Test IOSurface pbuffers can be made current
1187
TEST_P(IOSurfaceClientBufferTest, MakeCurrent)
1188
{
1189
ANGLE_SKIP_TEST_IF(!hasIOSurfaceExt());
1190
1191
ScopedIOSurfaceRef ioSurface = CreateSinglePlaneIOSurface(10, 10, 'BGRA', 4);
1192
1193
EGLSurface pbuffer;
1194
createIOSurfacePbuffer(ioSurface, 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &pbuffer);
1195
1196
EGLContext context = getEGLWindow()->getContext();
1197
EGLBoolean result = eglMakeCurrent(mDisplay, pbuffer, pbuffer, context);
1198
EXPECT_EGL_TRUE(result);
1199
EXPECT_EGL_SUCCESS();
1200
// The test harness expects the EGL state to be restored before the test exits.
1201
result = eglMakeCurrent(mDisplay, getEGLWindow()->getSurface(), getEGLWindow()->getSurface(),
1202
context);
1203
EXPECT_EGL_TRUE(result);
1204
EXPECT_EGL_SUCCESS();
1205
}
1206
1207
// TODO([email protected]): Test setting width and height to less than the IOSurface's work as
1208
// expected.
1209
1210
ANGLE_INSTANTIATE_TEST(IOSurfaceClientBufferTest,
1211
ES2_OPENGL(),
1212
ES3_OPENGL(),
1213
ES2_VULKAN_SWIFTSHADER(),
1214
ES3_VULKAN_SWIFTSHADER(),
1215
ES2_METAL());
1216
1217