Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/gl_tests/D3DTextureTest.cpp
1693 views
1
//
2
// Copyright 2015 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
// D3DTextureTest:
7
// Tests of the EGL_ANGLE_d3d_texture_client_buffer extension
8
9
#include "test_utils/ANGLETest.h"
10
#include "test_utils/gl_raii.h"
11
12
#include <d3d11.h>
13
#include <windows.h>
14
15
#include "util/EGLWindow.h"
16
#include "util/com_utils.h"
17
18
namespace angle
19
{
20
21
class D3DTextureTest : public ANGLETest
22
{
23
protected:
24
D3DTextureTest()
25
{
26
setWindowWidth(128);
27
setWindowHeight(128);
28
setConfigRedBits(8);
29
setConfigGreenBits(8);
30
setConfigBlueBits(8);
31
setConfigAlphaBits(8);
32
setConfigDepthBits(24);
33
setConfigStencilBits(8);
34
}
35
36
void testSetUp() override
37
{
38
constexpr char kVS[] =
39
R"(precision highp float;
40
attribute vec4 position;
41
varying vec2 texcoord;
42
43
void main()
44
{
45
gl_Position = position;
46
texcoord = (position.xy * 0.5) + 0.5;
47
texcoord.y = 1.0 - texcoord.y;
48
})";
49
50
constexpr char kTextureFS[] =
51
R"(precision highp float;
52
uniform sampler2D tex;
53
varying vec2 texcoord;
54
55
void main()
56
{
57
gl_FragColor = texture2D(tex, texcoord);
58
})";
59
60
constexpr char kTextureFSNoSampling[] =
61
R"(precision highp float;
62
63
void main()
64
{
65
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
66
})";
67
68
mTextureProgram = CompileProgram(kVS, kTextureFS);
69
ASSERT_NE(0u, mTextureProgram) << "shader compilation failed.";
70
71
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
72
ASSERT_NE(-1, mTextureUniformLocation);
73
74
mTextureProgramNoSampling = CompileProgram(kVS, kTextureFSNoSampling);
75
ASSERT_NE(0u, mTextureProgramNoSampling) << "shader compilation failed.";
76
77
mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
78
ASSERT_NE(nullptr, mD3D11Module);
79
80
PFN_D3D11_CREATE_DEVICE createDeviceFunc = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
81
GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
82
83
EGLWindow *window = getEGLWindow();
84
EGLDisplay display = window->getDisplay();
85
EGLDeviceEXT device = EGL_NO_DEVICE_EXT;
86
if (IsEGLClientExtensionEnabled("EGL_EXT_device_query"))
87
{
88
EGLAttrib result = 0;
89
EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
90
device = reinterpret_cast<EGLDeviceEXT>(result);
91
}
92
93
ASSERT_NE(EGL_NO_DEVICE_EXT, device);
94
95
if (IsEGLDeviceExtensionEnabled(device, "EGL_ANGLE_device_d3d"))
96
{
97
EGLAttrib result = 0;
98
if (eglQueryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &result))
99
{
100
mD3D11Device = reinterpret_cast<ID3D11Device *>(result);
101
mD3D11Device->AddRef();
102
}
103
else if (eglQueryDeviceAttribEXT(device, EGL_D3D9_DEVICE_ANGLE, &result))
104
{
105
mD3D9Device = reinterpret_cast<IDirect3DDevice9 *>(result);
106
mD3D9Device->AddRef();
107
}
108
}
109
else
110
{
111
ASSERT_TRUE(
112
SUCCEEDED(createDeviceFunc(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
113
0, D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr)));
114
}
115
}
116
117
void testTearDown() override
118
{
119
glDeleteProgram(mTextureProgram);
120
glDeleteProgram(mTextureProgramNoSampling);
121
122
if (mD3D11Device)
123
{
124
mD3D11Device->Release();
125
mD3D11Device = nullptr;
126
}
127
128
FreeLibrary(mD3D11Module);
129
mD3D11Module = nullptr;
130
131
if (mD3D9Device)
132
{
133
mD3D9Device->Release();
134
mD3D9Device = nullptr;
135
}
136
}
137
138
EGLSurface createD3D11PBuffer(size_t width,
139
size_t height,
140
UINT sampleCount,
141
UINT sampleQuality,
142
UINT bindFlags,
143
DXGI_FORMAT format,
144
const EGLint *attribs)
145
{
146
EGLWindow *window = getEGLWindow();
147
EGLDisplay display = window->getDisplay();
148
EGLConfig config = window->getConfig();
149
150
EXPECT_TRUE(mD3D11Device != nullptr);
151
ID3D11Texture2D *texture = nullptr;
152
CD3D11_TEXTURE2D_DESC desc(format, static_cast<UINT>(width), static_cast<UINT>(height), 1,
153
1, bindFlags);
154
desc.SampleDesc.Count = sampleCount;
155
desc.SampleDesc.Quality = sampleQuality;
156
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
157
158
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
159
texture, config, attribs);
160
161
texture->Release();
162
163
return pbuffer;
164
}
165
166
EGLSurface createD3D11PBuffer(size_t width,
167
size_t height,
168
EGLint eglTextureFormat,
169
EGLint eglTextureTarget,
170
UINT sampleCount,
171
UINT sampleQuality,
172
UINT bindFlags,
173
DXGI_FORMAT format)
174
{
175
EGLint attribs[] = {
176
EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
177
eglTextureTarget, EGL_NONE, EGL_NONE,
178
};
179
return createD3D11PBuffer(width, height, sampleCount, sampleQuality, bindFlags, format,
180
attribs);
181
}
182
183
EGLSurface createPBuffer(size_t width,
184
size_t height,
185
EGLint eglTextureFormat,
186
EGLint eglTextureTarget,
187
UINT sampleCount,
188
UINT sampleQuality)
189
{
190
if (mD3D11Device)
191
{
192
return createD3D11PBuffer(
193
width, height, eglTextureFormat, eglTextureTarget, sampleCount, sampleQuality,
194
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
195
}
196
197
if (mD3D9Device)
198
{
199
EGLWindow *window = getEGLWindow();
200
EGLDisplay display = window->getDisplay();
201
EGLConfig config = window->getConfig();
202
203
EGLint attribs[] = {
204
EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
205
eglTextureTarget, EGL_NONE, EGL_NONE,
206
};
207
208
// Multisampled textures are not supported on D3D9.
209
EXPECT_TRUE(sampleCount <= 1);
210
EXPECT_TRUE(sampleQuality == 0);
211
212
IDirect3DTexture9 *texture = nullptr;
213
EXPECT_TRUE(SUCCEEDED(mD3D9Device->CreateTexture(
214
static_cast<UINT>(width), static_cast<UINT>(height), 1, D3DUSAGE_RENDERTARGET,
215
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr)));
216
217
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
218
texture, config, attribs);
219
220
texture->Release();
221
222
return pbuffer;
223
}
224
else
225
{
226
return EGL_NO_SURFACE;
227
}
228
}
229
230
bool valid() const
231
{
232
EGLWindow *window = getEGLWindow();
233
EGLDisplay display = window->getDisplay();
234
if (!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_d3d_texture_client_buffer"))
235
{
236
std::cout << "Test skipped due to missing EGL_ANGLE_d3d_texture_client_buffer"
237
<< std::endl;
238
return false;
239
}
240
241
if (!mD3D11Device && !mD3D9Device)
242
{
243
std::cout << "Test skipped due to no D3D devices being available." << std::endl;
244
return false;
245
}
246
247
if (IsWindows() && IsAMD() && IsOpenGL())
248
{
249
std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
250
return false;
251
}
252
253
if (IsWindows() && IsIntel() && IsOpenGL())
254
{
255
std::cout << "Test skipped on Windows Intel OpenGL." << std::endl;
256
return false;
257
}
258
return true;
259
}
260
261
void testTextureSamplesAs50PercentGreen(GLuint texture)
262
{
263
GLFramebuffer scratchFbo;
264
glBindFramebuffer(GL_FRAMEBUFFER, scratchFbo);
265
GLTexture scratchTexture;
266
glBindTexture(GL_TEXTURE_2D, scratchTexture);
267
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
268
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scratchTexture,
269
0);
270
271
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
272
glClear(GL_COLOR_BUFFER_BIT);
273
274
glUseProgram(mTextureProgram);
275
glUniform1i(mTextureUniformLocation, 0);
276
glActiveTexture(GL_TEXTURE0);
277
glBindTexture(GL_TEXTURE_2D, texture);
278
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
279
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
280
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
281
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
282
283
drawQuad(mTextureProgram, "position", 0.5f);
284
ASSERT_GL_NO_ERROR();
285
286
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
287
}
288
289
GLuint mTextureProgram;
290
GLuint mTextureProgramNoSampling;
291
GLint mTextureUniformLocation;
292
293
HMODULE mD3D11Module = nullptr;
294
ID3D11Device *mD3D11Device = nullptr;
295
296
IDirect3DDevice9 *mD3D9Device = nullptr;
297
};
298
299
// Test creating pbuffer from textures with several different DXGI formats.
300
TEST_P(D3DTextureTest, TestD3D11SupportedFormatsSurface)
301
{
302
bool srgbSupported = IsGLExtensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
303
ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgbSupported);
304
305
const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
306
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
307
for (size_t i = 0; i < 4; ++i)
308
{
309
if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
310
{
311
if (IsOpenGL())
312
{
313
// This generates an invalid format error when calling wglDXRegisterObjectNV().
314
// Reproducible at least on NVIDIA driver 390.65 on Windows 10.
315
std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
316
continue;
317
}
318
}
319
320
EGLSurface pbuffer = createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
321
D3D11_BIND_RENDER_TARGET, formats[i]);
322
ASSERT_EGL_SUCCESS();
323
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
324
325
EGLWindow *window = getEGLWindow();
326
EGLDisplay display = window->getDisplay();
327
328
EGLint colorspace = EGL_NONE;
329
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
330
331
if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
332
formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
333
{
334
EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
335
}
336
else
337
{
338
EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
339
}
340
341
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
342
ASSERT_EGL_SUCCESS();
343
window->makeCurrent();
344
eglDestroySurface(display, pbuffer);
345
}
346
}
347
348
// Test binding a pbuffer created from a D3D texture as a texture image with several different DXGI
349
// formats. The test renders to and samples from the pbuffer.
350
TEST_P(D3DTextureTest, TestD3D11SupportedFormatsTexture)
351
{
352
bool srgb8alpha8TextureAttachmentSupported = getClientMajorVersion() >= 3;
353
ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgb8alpha8TextureAttachmentSupported);
354
355
bool srgbWriteControlSupported =
356
IsGLExtensionEnabled("GL_EXT_sRGB_write_control") && !IsOpenGL();
357
358
const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
359
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
360
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
361
for (size_t i = 0; i < 4; ++i)
362
{
363
if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
364
{
365
if (IsOpenGL())
366
{
367
// This generates an invalid format error when calling wglDXRegisterObjectNV().
368
// Reproducible at least on NVIDIA driver 390.65 on Windows 10.
369
std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
370
continue;
371
}
372
}
373
374
SCOPED_TRACE(std::string("Test case:") + std::to_string(i));
375
EGLWindow *window = getEGLWindow();
376
EGLDisplay display = window->getDisplay();
377
378
EGLSurface pbuffer =
379
createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
380
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, formats[i]);
381
ASSERT_EGL_SUCCESS();
382
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
383
384
EGLint colorspace = EGL_NONE;
385
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
386
387
GLuint texture = 0u;
388
glGenTextures(1, &texture);
389
glBindTexture(GL_TEXTURE_2D, texture);
390
EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
391
ASSERT_EGL_SUCCESS();
392
ASSERT_EGL_TRUE(result);
393
394
GLuint fbo = 0u;
395
glGenFramebuffers(1, &fbo);
396
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
397
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
398
glViewport(0, 0, 32, 32);
399
400
GLint colorEncoding = 0;
401
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
402
GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
403
&colorEncoding);
404
405
if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
406
formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
407
{
408
EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
409
EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
410
}
411
else
412
{
413
EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
414
EXPECT_EQ(GL_LINEAR, colorEncoding);
415
}
416
417
// Clear the texture with 50% green and check that the color value written is correct.
418
glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
419
420
if (colorEncoding == GL_SRGB_EXT)
421
{
422
glClear(GL_COLOR_BUFFER_BIT);
423
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 188u, 0u, 255u), 2);
424
// Disable SRGB and run the non-sRGB test case.
425
if (srgbWriteControlSupported)
426
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
427
}
428
429
if (colorEncoding == GL_LINEAR || srgbWriteControlSupported)
430
{
431
glClear(GL_COLOR_BUFFER_BIT);
432
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
433
}
434
435
// Draw with the texture to a linear framebuffer and check that the color value written is
436
// correct.
437
testTextureSamplesAs50PercentGreen(texture);
438
439
glBindFramebuffer(GL_FRAMEBUFFER, 0u);
440
glBindTexture(GL_TEXTURE_2D, 0u);
441
glDeleteTextures(1, &texture);
442
glDeleteFramebuffers(1, &fbo);
443
eglDestroySurface(display, pbuffer);
444
}
445
}
446
447
// Test binding a pbuffer created from a D3D texture as a texture image with typeless texture
448
// formats.
449
TEST_P(D3DTextureTest, TestD3D11TypelessTexture)
450
{
451
EGLWindow *window = getEGLWindow();
452
EGLDisplay display = window->getDisplay();
453
454
ANGLE_SKIP_TEST_IF(!valid());
455
456
// Typeless formats are optional in the spec and currently only supported on D3D11 backend.
457
ANGLE_SKIP_TEST_IF(!IsD3D11());
458
459
// GL_SRGB8_ALPHA8 texture attachment support is required.
460
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
461
462
const std::array<EGLint, 2> eglGlColorspaces = {EGL_GL_COLORSPACE_LINEAR,
463
EGL_GL_COLORSPACE_SRGB};
464
const std::array<DXGI_FORMAT, 2> dxgiFormats = {DXGI_FORMAT_R8G8B8A8_TYPELESS,
465
DXGI_FORMAT_B8G8R8A8_TYPELESS};
466
for (auto eglGlColorspace : eglGlColorspaces)
467
{
468
for (auto dxgiFormat : dxgiFormats)
469
{
470
SCOPED_TRACE(std::string("Test case:") + std::to_string(eglGlColorspace) + " / " +
471
std::to_string(dxgiFormat));
472
473
EGLint attribs[] = {
474
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
475
EGL_GL_COLORSPACE, eglGlColorspace, EGL_NONE, EGL_NONE,
476
};
477
478
EGLSurface pbuffer = createD3D11PBuffer(
479
32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, dxgiFormat,
480
attribs);
481
482
ASSERT_EGL_SUCCESS();
483
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
484
485
EGLint colorspace = EGL_NONE;
486
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
487
488
GLuint texture = 0u;
489
glGenTextures(1, &texture);
490
glBindTexture(GL_TEXTURE_2D, texture);
491
EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
492
ASSERT_EGL_SUCCESS();
493
ASSERT_EGL_TRUE(result);
494
495
GLuint fbo = 0u;
496
glGenFramebuffers(1, &fbo);
497
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
498
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
499
glViewport(0, 0, 32, 32);
500
501
GLint colorEncoding = 0;
502
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
503
GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
504
&colorEncoding);
505
506
if (eglGlColorspace == EGL_GL_COLORSPACE_LINEAR)
507
{
508
EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
509
EXPECT_EQ(GL_LINEAR, colorEncoding);
510
}
511
else
512
{
513
EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
514
EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
515
}
516
517
// Clear the texture with 50% green and check that the color value written is correct.
518
glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
519
520
if (colorEncoding == GL_SRGB_EXT)
521
{
522
glClear(GL_COLOR_BUFFER_BIT);
523
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 188u, 0u, 255u), 2);
524
}
525
if (colorEncoding == GL_LINEAR)
526
{
527
glClear(GL_COLOR_BUFFER_BIT);
528
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
529
}
530
531
// Draw with the texture to a linear framebuffer and check that the color value written
532
// is correct.
533
testTextureSamplesAs50PercentGreen(texture);
534
535
glBindFramebuffer(GL_FRAMEBUFFER, 0u);
536
glBindTexture(GL_TEXTURE_2D, 0u);
537
glDeleteTextures(1, &texture);
538
glDeleteFramebuffers(1, &fbo);
539
eglDestroySurface(display, pbuffer);
540
}
541
}
542
}
543
544
class D3DTextureTestES3 : public D3DTextureTest
545
{
546
protected:
547
D3DTextureTestES3() : D3DTextureTest() {}
548
};
549
550
// Test swizzling a pbuffer created from a D3D texture as a texture image with typeless texture
551
// formats.
552
TEST_P(D3DTextureTestES3, TestD3D11TypelessTextureSwizzle)
553
{
554
EGLWindow *window = getEGLWindow();
555
EGLDisplay display = window->getDisplay();
556
557
ANGLE_SKIP_TEST_IF(!valid());
558
559
// Typeless formats are optional in the spec and currently only supported on D3D11 backend.
560
ANGLE_SKIP_TEST_IF(!IsD3D11());
561
562
const std::array<EGLint, 2> eglGlColorspaces = {EGL_GL_COLORSPACE_LINEAR,
563
EGL_GL_COLORSPACE_SRGB};
564
const std::array<DXGI_FORMAT, 2> dxgiFormats = {DXGI_FORMAT_R8G8B8A8_TYPELESS,
565
DXGI_FORMAT_B8G8R8A8_TYPELESS};
566
for (auto eglGlColorspace : eglGlColorspaces)
567
{
568
for (auto dxgiFormat : dxgiFormats)
569
{
570
SCOPED_TRACE(std::string("Test case:") + std::to_string(eglGlColorspace) + " / " +
571
std::to_string(dxgiFormat));
572
573
EGLint attribs[] = {
574
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
575
EGL_GL_COLORSPACE, eglGlColorspace, EGL_NONE, EGL_NONE,
576
};
577
578
EGLSurface pbuffer = createD3D11PBuffer(
579
32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, dxgiFormat,
580
attribs);
581
582
ASSERT_EGL_SUCCESS();
583
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
584
585
EGLint colorspace = EGL_NONE;
586
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
587
588
GLuint texture = 0u;
589
glGenTextures(1, &texture);
590
glBindTexture(GL_TEXTURE_2D, texture);
591
EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
592
ASSERT_EGL_SUCCESS();
593
ASSERT_EGL_TRUE(result);
594
595
GLuint fbo = 0u;
596
glGenFramebuffers(1, &fbo);
597
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
598
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
599
glViewport(0, 0, 32, 32);
600
601
GLint colorEncoding = 0;
602
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
603
GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
604
&colorEncoding);
605
606
// Clear the texture with 50% blue and check that the color value written is correct.
607
glClearColor(0.0f, 0.0f, 0.5f, 1.0f);
608
609
if (colorEncoding == GL_SRGB_EXT)
610
{
611
glClear(GL_COLOR_BUFFER_BIT);
612
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 0u, 188u, 255u), 2);
613
}
614
if (colorEncoding == GL_LINEAR)
615
{
616
glClear(GL_COLOR_BUFFER_BIT);
617
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 0u, 127u, 255u), 2);
618
}
619
620
// Swizzle the green channel to be sampled from the blue channel of the texture and vice
621
// versa.
622
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
623
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
624
ASSERT_GL_NO_ERROR();
625
626
// Draw with the texture to a linear framebuffer and check that the color value written
627
// is correct.
628
testTextureSamplesAs50PercentGreen(texture);
629
630
glBindFramebuffer(GL_FRAMEBUFFER, 0u);
631
glBindTexture(GL_TEXTURE_2D, 0u);
632
glDeleteTextures(1, &texture);
633
glDeleteFramebuffers(1, &fbo);
634
eglDestroySurface(display, pbuffer);
635
}
636
}
637
}
638
639
// Test that EGL_GL_COLORSPACE attrib is not allowed for typed D3D textures.
640
TEST_P(D3DTextureTest, GlColorspaceNotAllowedForTypedD3DTexture)
641
{
642
ANGLE_SKIP_TEST_IF(!valid());
643
644
// D3D11 device is required to be able to create the texture.
645
ANGLE_SKIP_TEST_IF(!mD3D11Device);
646
647
// SRGB support is required.
648
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3);
649
650
EGLint attribsExplicitColorspace[] = {
651
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
652
EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB, EGL_NONE, EGL_NONE,
653
};
654
EGLSurface pbuffer =
655
createD3D11PBuffer(32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
656
DXGI_FORMAT_R8G8B8A8_UNORM, attribsExplicitColorspace);
657
658
ASSERT_EGL_ERROR(EGL_BAD_MATCH);
659
ASSERT_EQ(EGL_NO_SURFACE, pbuffer);
660
}
661
662
// Test that trying to create a pbuffer from a typeless texture fails as expected on the backends
663
// where they are known not to be supported.
664
TEST_P(D3DTextureTest, TypelessD3DTextureNotSupported)
665
{
666
ANGLE_SKIP_TEST_IF(!valid());
667
668
// D3D11 device is required to be able to create the texture.
669
ANGLE_SKIP_TEST_IF(!mD3D11Device);
670
671
// Currently typeless textures are supported on the D3D11 backend. We're testing the backends
672
// where there is no support.
673
ANGLE_SKIP_TEST_IF(IsD3D11());
674
675
// SRGB support is required.
676
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3);
677
678
EGLint attribs[] = {
679
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET,
680
EGL_TEXTURE_2D, EGL_NONE, EGL_NONE,
681
};
682
EGLSurface pbuffer =
683
createD3D11PBuffer(32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
684
DXGI_FORMAT_R8G8B8A8_TYPELESS, attribs);
685
ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
686
ASSERT_EQ(EGL_NO_SURFACE, pbuffer);
687
}
688
689
// Test creating a pbuffer with unnecessary EGL_WIDTH and EGL_HEIGHT attributes because that's what
690
// Chromium does. This is a regression test for crbug.com/794086
691
TEST_P(D3DTextureTest, UnnecessaryWidthHeightAttributes)
692
{
693
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
694
ASSERT_TRUE(mD3D11Device != nullptr);
695
ID3D11Texture2D *texture = nullptr;
696
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
697
desc.SampleDesc.Count = 1;
698
desc.SampleDesc.Quality = 0;
699
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
700
701
EGLint attribs[] = {
702
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
703
EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
704
EGL_WIDTH, 1,
705
EGL_HEIGHT, 1,
706
EGL_NONE, EGL_NONE,
707
};
708
709
EGLWindow *window = getEGLWindow();
710
EGLDisplay display = window->getDisplay();
711
EGLConfig config = window->getConfig();
712
713
EGLSurface pbuffer =
714
eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE, texture, config, attribs);
715
716
ASSERT_EGL_SUCCESS();
717
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
718
719
texture->Release();
720
721
// Make current with fixture EGL to ensure the Surface can be released immediately.
722
getEGLWindow()->makeCurrent();
723
eglDestroySurface(display, pbuffer);
724
}
725
726
// Test creating a pbuffer from a d3d surface and clearing it
727
TEST_P(D3DTextureTest, Clear)
728
{
729
if (!valid())
730
{
731
return;
732
}
733
734
EGLWindow *window = getEGLWindow();
735
EGLDisplay display = window->getDisplay();
736
737
const size_t bufferSize = 32;
738
739
EGLSurface pbuffer =
740
createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
741
ASSERT_EGL_SUCCESS();
742
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
743
744
// Apply the Pbuffer and clear it to purple and verify
745
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
746
ASSERT_EGL_SUCCESS();
747
748
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
749
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
750
glClear(GL_COLOR_BUFFER_BIT);
751
ASSERT_GL_NO_ERROR();
752
753
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
754
255, 255);
755
756
// Make current with fixture EGL to ensure the Surface can be released immediately.
757
getEGLWindow()->makeCurrent();
758
eglDestroySurface(display, pbuffer);
759
}
760
761
// Test creating a pbuffer with a D3D texture and depth stencil bits in the EGL config creates keeps
762
// its depth stencil buffer
763
TEST_P(D3DTextureTest, DepthStencil)
764
{
765
if (!valid())
766
{
767
return;
768
}
769
770
EGLWindow *window = getEGLWindow();
771
EGLDisplay display = window->getDisplay();
772
773
const size_t bufferSize = 32;
774
775
EGLSurface pbuffer =
776
createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
777
ASSERT_EGL_SUCCESS();
778
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
779
780
// Apply the Pbuffer and clear it to purple and verify
781
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
782
ASSERT_EGL_SUCCESS();
783
784
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
785
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
786
glClearDepthf(0.5f);
787
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
788
ASSERT_GL_NO_ERROR();
789
790
glEnable(GL_DEPTH_TEST);
791
glDepthMask(GL_FALSE);
792
793
glUseProgram(mTextureProgram);
794
glUniform1i(mTextureUniformLocation, 0);
795
796
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
797
798
// Draw a quad that will fail the depth test and verify that the buffer is unchanged
799
drawQuad(mTextureProgram, "position", 1.0f);
800
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
801
GLColor::cyan);
802
803
// Draw a quad that will pass the depth test and verify that the buffer is green
804
drawQuad(mTextureProgram, "position", -1.0f);
805
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
806
GLColor::green);
807
808
// Make current with fixture EGL to ensure the Surface can be released immediately.
809
getEGLWindow()->makeCurrent();
810
eglDestroySurface(display, pbuffer);
811
}
812
813
// Test creating a pbuffer from a d3d surface and binding it to a texture
814
TEST_P(D3DTextureTest, BindTexImage)
815
{
816
if (!valid())
817
{
818
return;
819
}
820
821
EGLWindow *window = getEGLWindow();
822
EGLDisplay display = window->getDisplay();
823
824
const size_t bufferSize = 32;
825
826
EGLSurface pbuffer =
827
createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0);
828
ASSERT_EGL_SUCCESS();
829
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
830
831
// Apply the Pbuffer and clear it to purple
832
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
833
ASSERT_EGL_SUCCESS();
834
835
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
836
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
837
glClear(GL_COLOR_BUFFER_BIT);
838
ASSERT_GL_NO_ERROR();
839
840
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
841
255, 255);
842
843
// Apply the window surface
844
eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
845
846
// Create a texture and bind the Pbuffer to it
847
GLuint texture = 0;
848
glGenTextures(1, &texture);
849
glBindTexture(GL_TEXTURE_2D, texture);
850
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
851
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
852
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
853
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
854
EXPECT_GL_NO_ERROR();
855
856
eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
857
glViewport(0, 0, getWindowWidth(), getWindowHeight());
858
ASSERT_EGL_SUCCESS();
859
860
// Draw a quad and verify that it is purple
861
glUseProgram(mTextureProgram);
862
glUniform1i(mTextureUniformLocation, 0);
863
864
drawQuad(mTextureProgram, "position", 0.5f);
865
EXPECT_GL_NO_ERROR();
866
867
// Unbind the texture
868
eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
869
ASSERT_EGL_SUCCESS();
870
871
// Verify that purple was drawn
872
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
873
874
glDeleteTextures(1, &texture);
875
876
// Make current with fixture EGL to ensure the Surface can be released immediately.
877
getEGLWindow()->makeCurrent();
878
eglDestroySurface(display, pbuffer);
879
}
880
881
// Verify that creating a pbuffer with a multisampled texture will fail on a non-multisampled
882
// window.
883
TEST_P(D3DTextureTest, CheckSampleMismatch)
884
{
885
if (!valid())
886
{
887
return;
888
}
889
890
// Multisampling is not supported on D3D9 or OpenGL.
891
ANGLE_SKIP_TEST_IF(IsD3D9() || IsOpenGL());
892
893
constexpr size_t bufferSize = 32;
894
895
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
896
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
897
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
898
EXPECT_EQ(pbuffer, nullptr);
899
}
900
901
// Tests what happens when we make a PBuffer that isn't shader-readable.
902
TEST_P(D3DTextureTest, NonReadablePBuffer)
903
{
904
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
905
906
constexpr size_t bufferSize = 32;
907
908
EGLSurface pbuffer =
909
createD3D11PBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
910
D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
911
912
ASSERT_EGL_SUCCESS();
913
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
914
915
EGLWindow *window = getEGLWindow();
916
EGLDisplay display = window->getDisplay();
917
918
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
919
ASSERT_EGL_SUCCESS();
920
921
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
922
923
// Clear to green.
924
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
925
glClear(GL_COLOR_BUFFER_BIT);
926
ASSERT_GL_NO_ERROR();
927
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
928
929
// Copy the green color to a texture.
930
GLTexture tex;
931
glBindTexture(GL_TEXTURE_2D, tex);
932
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
933
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
934
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, bufferSize, bufferSize, 0);
935
ASSERT_GL_NO_ERROR();
936
937
// Clear to red.
938
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
939
glClear(GL_COLOR_BUFFER_BIT);
940
ASSERT_GL_NO_ERROR();
941
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
942
943
// Draw with the texture and expect green.
944
draw2DTexturedQuad(0.5f, 1.0f, false);
945
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
946
947
// Make current with fixture EGL to ensure the Surface can be released immediately.
948
getEGLWindow()->makeCurrent();
949
eglDestroySurface(display, pbuffer);
950
}
951
952
class D3DTextureTestMS : public D3DTextureTest
953
{
954
protected:
955
D3DTextureTestMS() : D3DTextureTest()
956
{
957
setSamples(4);
958
setMultisampleEnabled(true);
959
}
960
};
961
962
// Test creating a pbuffer from a multisampled d3d surface and clearing it.
963
TEST_P(D3DTextureTestMS, Clear)
964
{
965
EGLWindow *window = getEGLWindow();
966
EGLDisplay display = window->getDisplay();
967
968
constexpr size_t bufferSize = 32;
969
constexpr UINT testpoint = bufferSize / 2;
970
971
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
972
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
973
ASSERT_EGL_SUCCESS();
974
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
975
976
// Apply the Pbuffer and clear it to magenta and verify
977
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
978
ASSERT_EGL_SUCCESS();
979
980
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
981
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
982
glClear(GL_COLOR_BUFFER_BIT);
983
ASSERT_GL_NO_ERROR();
984
EXPECT_PIXEL_COLOR_EQ(testpoint, testpoint, GLColor::magenta);
985
986
// Make current with fixture EGL to ensure the Surface can be released immediately.
987
getEGLWindow()->makeCurrent();
988
eglDestroySurface(display, pbuffer);
989
}
990
991
// Test creating a pbuffer from a multisampled d3d surface and drawing with a program.
992
TEST_P(D3DTextureTestMS, DrawProgram)
993
{
994
EGLWindow *window = getEGLWindow();
995
EGLDisplay display = window->getDisplay();
996
997
constexpr size_t bufferSize = 32;
998
999
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1000
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1001
ASSERT_EGL_SUCCESS();
1002
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
1003
1004
// Apply the Pbuffer and clear it to magenta
1005
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1006
ASSERT_EGL_SUCCESS();
1007
1008
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1009
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1010
glClear(GL_COLOR_BUFFER_BIT);
1011
ASSERT_GL_NO_ERROR();
1012
1013
constexpr GLint testPoint = bufferSize / 2;
1014
EXPECT_PIXEL_COLOR_EQ(testPoint, testPoint, GLColor::magenta);
1015
1016
// Apply the window surface
1017
eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
1018
ASSERT_EGL_SUCCESS();
1019
1020
glViewport(0, 0, getWindowWidth(), getWindowHeight());
1021
ASSERT_EGL_SUCCESS();
1022
1023
// Draw a quad and verify that it is magenta
1024
glUseProgram(mTextureProgramNoSampling);
1025
EXPECT_GL_NO_ERROR();
1026
1027
drawQuad(mTextureProgramNoSampling, "position", 0.5f);
1028
EXPECT_GL_NO_ERROR();
1029
1030
// Verify that magenta was drawn
1031
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::magenta);
1032
1033
// Make current with fixture EGL to ensure the Surface can be released immediately.
1034
getEGLWindow()->makeCurrent();
1035
eglDestroySurface(display, pbuffer);
1036
}
1037
1038
// Test for failure when creating a pbuffer from a multisampled d3d surface to bind to a texture.
1039
TEST_P(D3DTextureTestMS, BindTexture)
1040
{
1041
constexpr size_t bufferSize = 32;
1042
1043
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 4,
1044
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1045
1046
EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1047
EXPECT_EQ(pbuffer, nullptr);
1048
}
1049
1050
// Verify that creating a pbuffer from a multisampled texture with a multisampled window will fail
1051
// when the sample counts do not match.
1052
TEST_P(D3DTextureTestMS, CheckSampleMismatch)
1053
{
1054
constexpr size_t bufferSize = 32;
1055
1056
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
1057
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1058
1059
EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1060
EXPECT_EQ(pbuffer, nullptr);
1061
}
1062
1063
// Test creating a pbuffer with a D3D texture and depth stencil bits in the EGL config creates keeps
1064
// its depth stencil buffer
1065
TEST_P(D3DTextureTestMS, DepthStencil)
1066
{
1067
EGLWindow *window = getEGLWindow();
1068
EGLDisplay display = window->getDisplay();
1069
1070
const size_t bufferSize = 32;
1071
1072
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1073
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1074
ASSERT_EGL_SUCCESS();
1075
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1076
1077
// Apply the Pbuffer and clear it to purple and verify
1078
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1079
ASSERT_EGL_SUCCESS();
1080
1081
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1082
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
1083
glClearDepthf(0.5f);
1084
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1085
ASSERT_GL_NO_ERROR();
1086
1087
glEnable(GL_DEPTH_TEST);
1088
glDepthMask(GL_FALSE);
1089
1090
glUseProgram(mTextureProgram);
1091
glUniform1i(mTextureUniformLocation, 0);
1092
1093
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1094
1095
// Draw a quad that will fail the depth test and verify that the buffer is unchanged
1096
drawQuad(mTextureProgram, "position", 1.0f);
1097
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1098
GLColor::cyan);
1099
1100
// Draw a quad that will pass the depth test and verify that the buffer is green
1101
drawQuad(mTextureProgram, "position", -1.0f);
1102
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1103
GLColor::green);
1104
1105
// Make current with fixture EGL to ensure the Surface can be released immediately.
1106
getEGLWindow()->makeCurrent();
1107
eglDestroySurface(display, pbuffer);
1108
}
1109
1110
// Test copyTexImage2D with a multisampled resource
1111
TEST_P(D3DTextureTestMS, CopyTexImage2DTest)
1112
{
1113
EGLWindow *window = getEGLWindow();
1114
EGLDisplay display = window->getDisplay();
1115
1116
constexpr size_t bufferSize = 32;
1117
1118
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1119
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1120
ASSERT_EGL_SUCCESS();
1121
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1122
1123
// Apply the Pbuffer and clear it to magenta and verify
1124
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1125
ASSERT_EGL_SUCCESS();
1126
1127
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1128
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1129
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1130
ASSERT_GL_NO_ERROR();
1131
1132
glUseProgram(mTextureProgram);
1133
glUniform1i(mTextureUniformLocation, 0);
1134
1135
// Specify a 2D texture and set it to green
1136
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1137
1138
// Copy from the multisampled framebuffer to the 2D texture
1139
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
1140
1141
// Draw a quad and verify the color is magenta, not green
1142
drawQuad(mTextureProgram, "position", 1.0f);
1143
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1144
GLColor::magenta);
1145
ASSERT_GL_NO_ERROR();
1146
1147
// Make current with fixture EGL to ensure the Surface can be released immediately.
1148
getEGLWindow()->makeCurrent();
1149
eglDestroySurface(display, pbuffer);
1150
}
1151
1152
// Test copyTexSubImage2D with a multisampled resource
1153
TEST_P(D3DTextureTestMS, CopyTexSubImage2DTest)
1154
{
1155
EGLWindow *window = getEGLWindow();
1156
EGLDisplay display = window->getDisplay();
1157
1158
constexpr size_t bufferSize = 32;
1159
1160
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1161
static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1162
ASSERT_EGL_SUCCESS();
1163
ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1164
1165
// Apply the Pbuffer and clear it to magenta and verify
1166
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1167
ASSERT_EGL_SUCCESS();
1168
1169
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1170
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1171
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1172
ASSERT_GL_NO_ERROR();
1173
1174
glUseProgram(mTextureProgram);
1175
glUniform1i(mTextureUniformLocation, 0);
1176
1177
// Specify a 2D texture and set it to green
1178
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1179
1180
// Copy from the multisampled framebuffer to the 2D texture
1181
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1182
1183
// Draw a quad and verify the color is magenta, not green
1184
drawQuad(mTextureProgram, "position", 1.0f);
1185
EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1186
GLColor::magenta);
1187
ASSERT_GL_NO_ERROR();
1188
1189
// Make current with fixture EGL to ensure the Surface can be released immediately.
1190
getEGLWindow()->makeCurrent();
1191
eglDestroySurface(display, pbuffer);
1192
}
1193
1194
TEST_P(D3DTextureTest, ClearTextureImage)
1195
{
1196
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1197
1198
EGLWindow *window = getEGLWindow();
1199
EGLDisplay display = window->getDisplay();
1200
1201
window->makeCurrent();
1202
1203
const UINT bufferSize = 32;
1204
EXPECT_TRUE(mD3D11Device != nullptr);
1205
ID3D11Texture2D *d3d11_texture = nullptr;
1206
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1207
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1208
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
1209
1210
const EGLint attribs[] = {EGL_NONE};
1211
1212
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1213
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
1214
ASSERT_EGL_SUCCESS();
1215
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1216
1217
GLuint texture;
1218
glGenTextures(1, &texture);
1219
glBindTexture(GL_TEXTURE_2D, texture);
1220
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1221
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1222
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1223
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1224
ASSERT_GL_NO_ERROR();
1225
1226
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1227
ASSERT_GL_NO_ERROR();
1228
1229
GLuint fbo;
1230
glGenFramebuffers(1, &fbo);
1231
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1232
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1233
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1234
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1235
ASSERT_GL_NO_ERROR();
1236
1237
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1238
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1239
glClear(GL_COLOR_BUFFER_BIT);
1240
ASSERT_GL_NO_ERROR();
1241
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1242
255, 255);
1243
1244
glDeleteFramebuffers(1, &fbo);
1245
glDeleteTextures(1, &texture);
1246
eglDestroyImageKHR(display, image);
1247
1248
d3d11_texture->Release();
1249
}
1250
1251
TEST_P(D3DTextureTest, NonRenderableTextureImage)
1252
{
1253
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1254
1255
EGLWindow *window = getEGLWindow();
1256
EGLDisplay display = window->getDisplay();
1257
1258
window->makeCurrent();
1259
1260
const UINT bufferSize = 32;
1261
EXPECT_TRUE(mD3D11Device != nullptr);
1262
ID3D11Texture2D *d3d11_texture = nullptr;
1263
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1264
D3D11_BIND_SHADER_RESOURCE);
1265
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
1266
1267
const EGLint attribs[] = {EGL_NONE};
1268
1269
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1270
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
1271
ASSERT_EGL_SUCCESS();
1272
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1273
1274
GLuint texture;
1275
glGenTextures(1, &texture);
1276
glBindTexture(GL_TEXTURE_2D, texture);
1277
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1278
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1279
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1280
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1281
ASSERT_GL_NO_ERROR();
1282
1283
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1284
ASSERT_GL_NO_ERROR();
1285
1286
GLuint fbo;
1287
glGenFramebuffers(1, &fbo);
1288
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1289
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1290
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1291
static_cast<unsigned>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
1292
ASSERT_GL_NO_ERROR();
1293
1294
glDeleteFramebuffers(1, &fbo);
1295
glDeleteTextures(1, &texture);
1296
eglDestroyImageKHR(display, image);
1297
1298
d3d11_texture->Release();
1299
}
1300
1301
TEST_P(D3DTextureTest, RGBEmulationTextureImage)
1302
{
1303
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1304
1305
EGLWindow *window = getEGLWindow();
1306
EGLDisplay display = window->getDisplay();
1307
1308
window->makeCurrent();
1309
1310
const UINT bufferSize = 32;
1311
EXPECT_TRUE(mD3D11Device != nullptr);
1312
ID3D11Texture2D *d3d11_texture = nullptr;
1313
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1314
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1315
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
1316
1317
const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGB, EGL_NONE};
1318
1319
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1320
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
1321
ASSERT_EGL_SUCCESS();
1322
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1323
1324
GLuint texture;
1325
glGenTextures(1, &texture);
1326
glBindTexture(GL_TEXTURE_2D, texture);
1327
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1328
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1329
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1330
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1331
ASSERT_GL_NO_ERROR();
1332
1333
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1334
ASSERT_GL_NO_ERROR();
1335
1336
GLuint fbo;
1337
glGenFramebuffers(1, &fbo);
1338
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1339
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1340
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1341
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1342
ASSERT_GL_NO_ERROR();
1343
1344
// Although we are writing 0.5 to the alpha channel it should have the same
1345
// side effects as if alpha were 1.0.
1346
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1347
glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1348
glClear(GL_COLOR_BUFFER_BIT);
1349
ASSERT_GL_NO_ERROR();
1350
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1351
255, 255);
1352
1353
GLuint rgbaRbo;
1354
glGenRenderbuffers(1, &rgbaRbo);
1355
glBindRenderbuffer(GL_RENDERBUFFER, rgbaRbo);
1356
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, bufferSize, bufferSize);
1357
1358
GLuint rgbaFbo;
1359
glGenFramebuffers(1, &rgbaFbo);
1360
glBindFramebuffer(GL_FRAMEBUFFER, rgbaFbo);
1361
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbaRbo);
1362
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1363
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1364
ASSERT_GL_NO_ERROR();
1365
1366
// BlitFramebuffer from/to RGBA framebuffer fails.
1367
glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbaFbo);
1368
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1369
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1370
GL_COLOR_BUFFER_BIT, GL_NEAREST);
1371
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1372
ASSERT_GL_NO_ERROR();
1373
1374
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1375
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbaFbo);
1376
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1377
GL_COLOR_BUFFER_BIT, GL_NEAREST);
1378
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1379
ASSERT_GL_NO_ERROR();
1380
1381
GLuint rgbRbo;
1382
glGenRenderbuffers(1, &rgbRbo);
1383
glBindRenderbuffer(GL_RENDERBUFFER, rgbRbo);
1384
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, bufferSize, bufferSize);
1385
1386
GLuint rgbFbo;
1387
glGenFramebuffers(1, &rgbFbo);
1388
glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1389
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbRbo);
1390
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1391
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1392
ASSERT_GL_NO_ERROR();
1393
glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1394
glClear(GL_COLOR_BUFFER_BIT);
1395
ASSERT_GL_NO_ERROR();
1396
1397
// Clear texture framebuffer.
1398
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1399
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1400
glClear(GL_COLOR_BUFFER_BIT);
1401
ASSERT_GL_NO_ERROR();
1402
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1403
255);
1404
1405
// BlitFramebuffer from/to RGB framebuffer succeeds.
1406
glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbFbo);
1407
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1408
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1409
GL_COLOR_BUFFER_BIT, GL_NEAREST);
1410
ASSERT_GL_NO_ERROR();
1411
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1412
255, 255);
1413
1414
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1415
glClear(GL_COLOR_BUFFER_BIT);
1416
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1417
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbFbo);
1418
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1419
GL_COLOR_BUFFER_BIT, GL_NEAREST);
1420
ASSERT_GL_NO_ERROR();
1421
glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1422
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1423
255);
1424
1425
glDeleteFramebuffers(1, &rgbFbo);
1426
glDeleteRenderbuffers(1, &rgbRbo);
1427
glDeleteFramebuffers(1, &rgbaFbo);
1428
glDeleteRenderbuffers(1, &rgbaRbo);
1429
glDeleteFramebuffers(1, &fbo);
1430
glDeleteTextures(1, &texture);
1431
eglDestroyImageKHR(display, image);
1432
1433
d3d11_texture->Release();
1434
}
1435
1436
TEST_P(D3DTextureTest, TextureArrayImage)
1437
{
1438
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1439
1440
EGLWindow *window = getEGLWindow();
1441
EGLDisplay display = window->getDisplay();
1442
1443
window->makeCurrent();
1444
1445
const UINT bufferSize = 32;
1446
const UINT arraySize = 4;
1447
1448
ID3D11Texture2D *d3d11_texture = nullptr;
1449
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, arraySize, 1,
1450
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1451
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
1452
1453
const unsigned char kRFill = 0x12;
1454
const unsigned char kGFill = 0x23;
1455
const unsigned char kBFill = 0x34;
1456
const unsigned char kAFill = 0x45;
1457
1458
std::vector<unsigned char> imageData(bufferSize * bufferSize * 4, 0);
1459
for (size_t i = 0; i < imageData.size(); i += 4)
1460
{
1461
imageData[i] = kRFill;
1462
imageData[i + 1] = kGFill;
1463
imageData[i + 2] = kBFill;
1464
imageData[i + 3] = kAFill;
1465
}
1466
1467
ID3D11DeviceContext *context = nullptr;
1468
mD3D11Device->GetImmediateContext(&context);
1469
ASSERT_NE(context, nullptr);
1470
1471
D3D11_BOX dstBox = {0, 0, 0, bufferSize, bufferSize, 1};
1472
context->UpdateSubresource(d3d11_texture, arraySize - 1, &dstBox, imageData.data(),
1473
bufferSize * 4, imageData.size());
1474
1475
const EGLint attribs[] = {EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, arraySize - 1, EGL_NONE};
1476
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1477
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
1478
ASSERT_EGL_SUCCESS();
1479
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1480
1481
GLuint texture;
1482
glGenTextures(1, &texture);
1483
glBindTexture(GL_TEXTURE_2D, texture);
1484
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1485
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1486
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1487
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1488
ASSERT_GL_NO_ERROR();
1489
1490
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1491
ASSERT_GL_NO_ERROR();
1492
1493
GLuint fbo;
1494
glGenFramebuffers(1, &fbo);
1495
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1496
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1497
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1498
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1499
ASSERT_GL_NO_ERROR();
1500
1501
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, kRFill,
1502
kGFill, kBFill, kAFill);
1503
1504
glDeleteFramebuffers(1, &fbo);
1505
glDeleteTextures(1, &texture);
1506
eglDestroyImageKHR(display, image);
1507
1508
d3d11_texture->Release();
1509
}
1510
1511
class D3DTextureYUVTest : public D3DTextureTest
1512
{
1513
protected:
1514
D3DTextureYUVTest() : D3DTextureTest() {}
1515
1516
void RunYUVTest(DXGI_FORMAT format)
1517
{
1518
ASSERT_TRUE(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1519
format == DXGI_FORMAT_P016);
1520
UINT formatSupport;
1521
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1522
FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1523
ASSERT_TRUE(formatSupport &
1524
(D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE));
1525
1526
constexpr char kVS[] =
1527
R"(precision highp float;
1528
attribute vec4 position;
1529
varying vec2 texcoord;
1530
1531
void main()
1532
{
1533
gl_Position = position;
1534
texcoord = (position.xy * 0.5) + 0.5;
1535
texcoord.y = 1.0 - texcoord.y;
1536
})";
1537
1538
constexpr char kTextureExternalOESFS[] =
1539
R"(#extension GL_OES_EGL_image_external : require
1540
precision highp float;
1541
uniform samplerExternalOES tex;
1542
varying vec2 texcoord;
1543
1544
void main()
1545
{
1546
gl_FragColor = texture2D(tex, texcoord);
1547
})";
1548
1549
GLuint textureExternalOESProgram = CompileProgram(kVS, kTextureExternalOESFS);
1550
ASSERT_NE(0u, textureExternalOESProgram) << "shader compilation failed.";
1551
1552
GLint textureExternalOESUniformLocation =
1553
glGetUniformLocation(textureExternalOESProgram, "tex");
1554
ASSERT_NE(-1, textureExternalOESUniformLocation);
1555
1556
EGLWindow *window = getEGLWindow();
1557
EGLDisplay display = window->getDisplay();
1558
1559
window->makeCurrent();
1560
1561
const UINT bufferSize = 32;
1562
EXPECT_TRUE(mD3D11Device != nullptr);
1563
ID3D11Texture2D *d3d11_texture = nullptr;
1564
CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1565
D3D11_BIND_SHADER_RESOURCE);
1566
1567
const bool isNV12 = (format == DXGI_FORMAT_NV12);
1568
const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1569
const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1570
const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1571
1572
std::vector<unsigned char> imageData;
1573
1574
if (isNV12)
1575
{
1576
imageData.resize(bufferSize * bufferSize * 3 / 2);
1577
memset(imageData.data(), kYFillValue, bufferSize * bufferSize);
1578
const size_t kUVOffset = bufferSize * bufferSize;
1579
for (size_t i = 0; i < bufferSize * bufferSize / 2; i += 2)
1580
{
1581
imageData[kUVOffset + i] = kUFillValue;
1582
imageData[kUVOffset + i + 1] = kVFillValue;
1583
}
1584
}
1585
else
1586
{
1587
imageData.resize(bufferSize * bufferSize * 3);
1588
const size_t kUVOffset = bufferSize * bufferSize * 2;
1589
for (size_t i = 0; i < kUVOffset; i += 2)
1590
{
1591
imageData[i] = kYFillValue & 0xff;
1592
imageData[i + 1] = (kYFillValue >> 8) & 0xff;
1593
if (kUVOffset + i < imageData.size())
1594
{
1595
// Interleave U & V samples.
1596
const unsigned fill = (i % 4 == 0) ? kUFillValue : kVFillValue;
1597
imageData[kUVOffset + i] = fill & 0xff;
1598
imageData[kUVOffset + i + 1] = (fill >> 8) & 0xff;
1599
}
1600
}
1601
}
1602
1603
D3D11_SUBRESOURCE_DATA data = {};
1604
data.pSysMem = static_cast<const void *>(imageData.data());
1605
data.SysMemPitch = isNV12 ? bufferSize : bufferSize * 2;
1606
1607
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, &data, &d3d11_texture)));
1608
1609
const EGLint yAttribs[] = {EGL_D3D11_TEXTURE_PLANE_ANGLE, 0, EGL_NONE};
1610
EGLImage yImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1611
static_cast<EGLClientBuffer>(d3d11_texture), yAttribs);
1612
ASSERT_EGL_SUCCESS();
1613
ASSERT_NE(yImage, EGL_NO_IMAGE_KHR);
1614
1615
// Create and bind Y plane texture to image.
1616
GLuint yTexture;
1617
glGenTextures(1, &yTexture);
1618
glActiveTexture(GL_TEXTURE0);
1619
glBindTexture(GL_TEXTURE_EXTERNAL_OES, yTexture);
1620
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1621
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1622
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1623
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1624
ASSERT_GL_NO_ERROR();
1625
1626
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yImage);
1627
ASSERT_GL_NO_ERROR();
1628
1629
GLuint rbo;
1630
glGenRenderbuffers(1, &rbo);
1631
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1632
glRenderbufferStorage(GL_RENDERBUFFER, isNV12 ? GL_RGBA8_OES : GL_RGBA16_EXT, bufferSize,
1633
bufferSize);
1634
ASSERT_GL_NO_ERROR();
1635
1636
GLuint fbo;
1637
glGenFramebuffers(1, &fbo);
1638
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1639
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1640
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1641
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1642
ASSERT_GL_NO_ERROR();
1643
1644
// Draw the Y plane using a shader.
1645
glUseProgram(textureExternalOESProgram);
1646
glUniform1i(textureExternalOESUniformLocation, 0);
1647
ASSERT_GL_NO_ERROR();
1648
1649
glViewport(0, 0, bufferSize, bufferSize);
1650
drawQuad(textureExternalOESProgram, "position", 1.0f);
1651
ASSERT_GL_NO_ERROR();
1652
1653
if (isNV12)
1654
{
1655
1656
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1657
kYFillValue, 0, 0, 0xff);
1658
}
1659
else
1660
{
1661
EXPECT_PIXEL_16UI(static_cast<GLint>(bufferSize) / 2,
1662
static_cast<GLint>(bufferSize) / 2, kYFillValue, 0, 0, 0xffff);
1663
}
1664
ASSERT_GL_NO_ERROR();
1665
1666
const EGLint uvAttribs[] = {EGL_D3D11_TEXTURE_PLANE_ANGLE, 1, EGL_NONE};
1667
EGLImage uvImage =
1668
eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1669
static_cast<EGLClientBuffer>(d3d11_texture), uvAttribs);
1670
ASSERT_EGL_SUCCESS();
1671
ASSERT_NE(uvImage, EGL_NO_IMAGE_KHR);
1672
1673
// Create and bind UV plane texture to image.
1674
GLuint uvTexture;
1675
glGenTextures(1, &uvTexture);
1676
glActiveTexture(GL_TEXTURE0);
1677
glBindTexture(GL_TEXTURE_EXTERNAL_OES, uvTexture);
1678
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1679
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1680
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1681
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1682
ASSERT_GL_NO_ERROR();
1683
1684
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, uvImage);
1685
ASSERT_GL_NO_ERROR();
1686
1687
// Draw the UV plane using a shader.
1688
glUseProgram(textureExternalOESProgram);
1689
glUniform1i(textureExternalOESUniformLocation, 0);
1690
ASSERT_GL_NO_ERROR();
1691
1692
// Use only half of the framebuffer to match UV plane dimensions.
1693
glViewport(0, 0, bufferSize / 2, bufferSize / 2);
1694
drawQuad(textureExternalOESProgram, "position", 1.0f);
1695
ASSERT_GL_NO_ERROR();
1696
1697
if (isNV12)
1698
{
1699
1700
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 4, static_cast<GLint>(bufferSize) / 4,
1701
kUFillValue, kVFillValue, 0, 0xff);
1702
}
1703
else
1704
{
1705
EXPECT_PIXEL_16UI(static_cast<GLint>(bufferSize) / 4,
1706
static_cast<GLint>(bufferSize) / 4, kUFillValue, kVFillValue, 0,
1707
0xffff);
1708
}
1709
ASSERT_GL_NO_ERROR();
1710
1711
glDeleteProgram(textureExternalOESProgram);
1712
glDeleteTextures(1, &yTexture);
1713
glDeleteTextures(1, &uvTexture);
1714
glDeleteFramebuffers(1, &fbo);
1715
glDeleteRenderbuffers(1, &rbo);
1716
eglDestroyImageKHR(display, yImage);
1717
eglDestroyImageKHR(display, uvImage);
1718
1719
d3d11_texture->Release();
1720
}
1721
};
1722
1723
TEST_P(D3DTextureYUVTest, NV12TextureImage)
1724
{
1725
RunYUVTest(DXGI_FORMAT_NV12);
1726
}
1727
1728
// Reading back from RGBA16_EXT renderbuffer needs GL_EXT_texture_norm16 which is ES3 only.
1729
class D3DTextureYUVTestES3 : public D3DTextureYUVTest
1730
{
1731
protected:
1732
D3DTextureYUVTestES3() : D3DTextureYUVTest() {}
1733
};
1734
1735
TEST_P(D3DTextureYUVTestES3, P010TextureImage)
1736
{
1737
RunYUVTest(DXGI_FORMAT_P010);
1738
}
1739
1740
TEST_P(D3DTextureYUVTestES3, P016TextureImage)
1741
{
1742
RunYUVTest(DXGI_FORMAT_P016);
1743
}
1744
1745
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
1746
// tests should be run against.
1747
ANGLE_INSTANTIATE_TEST_ES2(D3DTextureTest);
1748
ANGLE_INSTANTIATE_TEST_ES2(D3DTextureYUVTest);
1749
ANGLE_INSTANTIATE_TEST_ES3(D3DTextureTestES3);
1750
ANGLE_INSTANTIATE_TEST_ES3(D3DTextureYUVTestES3);
1751
// D3D Debug device reports an error. http://anglebug.com/3513
1752
// ANGLE_INSTANTIATE_TEST(D3DTextureTestMS, ES2_D3D11());
1753
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(D3DTextureTestMS);
1754
} // namespace angle
1755
1756