xref: /aosp_15_r20/external/angle/src/tests/gl_tests/D3DTextureTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 <d3d9.h>
14 #include <dxgiformat.h>
15 #include <windows.h>
16 #include <wrl/client.h>
17 
18 #include "util/EGLWindow.h"
19 #include "util/com_utils.h"
20 
21 namespace angle
22 {
23 
24 class D3DTextureTest : public ANGLETest<>
25 {
26   protected:
D3DTextureTest()27     D3DTextureTest()
28     {
29         setWindowWidth(128);
30         setWindowHeight(128);
31         setConfigRedBits(8);
32         setConfigGreenBits(8);
33         setConfigBlueBits(8);
34         setConfigAlphaBits(8);
35         setConfigDepthBits(24);
36         setConfigStencilBits(8);
37     }
38 
testSetUp()39     void testSetUp() override
40     {
41         constexpr char kVS[] =
42             R"(precision highp float;
43             attribute vec4 position;
44             varying vec2 texcoord;
45 
46             void main()
47             {
48                 gl_Position = position;
49                 texcoord = (position.xy * 0.5) + 0.5;
50                 texcoord.y = 1.0 - texcoord.y;
51             })";
52 
53         constexpr char kTextureFS[] =
54             R"(precision highp float;
55             uniform sampler2D tex;
56             varying vec2 texcoord;
57 
58             void main()
59             {
60                 gl_FragColor = texture2D(tex, texcoord);
61             })";
62 
63         constexpr char kTextureFSNoSampling[] =
64             R"(precision highp float;
65 
66             void main()
67             {
68                 gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
69             })";
70 
71         mTextureProgram = CompileProgram(kVS, kTextureFS);
72         ASSERT_NE(0u, mTextureProgram) << "shader compilation failed.";
73 
74         mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
75         ASSERT_NE(-1, mTextureUniformLocation);
76 
77         mTextureProgramNoSampling = CompileProgram(kVS, kTextureFSNoSampling);
78         ASSERT_NE(0u, mTextureProgramNoSampling) << "shader compilation failed.";
79 
80         mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
81         ASSERT_NE(nullptr, mD3D11Module);
82 
83         PFN_D3D11_CREATE_DEVICE createDeviceFunc = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
84             GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
85 
86         EGLWindow *window   = getEGLWindow();
87         EGLDisplay display  = window->getDisplay();
88         EGLDeviceEXT device = EGL_NO_DEVICE_EXT;
89         if (IsEGLClientExtensionEnabled("EGL_EXT_device_query"))
90         {
91             EGLAttrib result = 0;
92             EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
93             device = reinterpret_cast<EGLDeviceEXT>(result);
94         }
95 
96         ASSERT_NE(EGL_NO_DEVICE_EXT, device);
97 
98         if (IsEGLDeviceExtensionEnabled(device, "EGL_ANGLE_device_d3d"))
99         {
100             EGLAttrib result = 0;
101             if (eglQueryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &result))
102             {
103                 mD3D11Device = reinterpret_cast<ID3D11Device *>(result);
104                 mD3D11Device->AddRef();
105             }
106             else if (eglQueryDeviceAttribEXT(device, EGL_D3D9_DEVICE_ANGLE, &result))
107             {
108                 mD3D9Device = reinterpret_cast<IDirect3DDevice9 *>(result);
109                 mD3D9Device->AddRef();
110             }
111         }
112         else
113         {
114             ASSERT_TRUE(
115                 SUCCEEDED(createDeviceFunc(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
116                                            0, D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr)));
117         }
118     }
119 
testTearDown()120     void testTearDown() override
121     {
122         glDeleteProgram(mTextureProgram);
123         glDeleteProgram(mTextureProgramNoSampling);
124 
125         if (mD3D11Device)
126         {
127             mD3D11Device->Release();
128             mD3D11Device = nullptr;
129         }
130 
131         FreeLibrary(mD3D11Module);
132         mD3D11Module = nullptr;
133 
134         if (mD3D9Device)
135         {
136             mD3D9Device->Release();
137             mD3D9Device = nullptr;
138         }
139     }
140 
createD3D11PBuffer(size_t width,size_t height,UINT sampleCount,UINT sampleQuality,UINT bindFlags,DXGI_FORMAT format,const EGLint * attribs)141     EGLSurface createD3D11PBuffer(size_t width,
142                                   size_t height,
143                                   UINT sampleCount,
144                                   UINT sampleQuality,
145                                   UINT bindFlags,
146                                   DXGI_FORMAT format,
147                                   const EGLint *attribs)
148     {
149         EGLWindow *window  = getEGLWindow();
150         EGLDisplay display = window->getDisplay();
151         EGLConfig config   = window->getConfig();
152 
153         EXPECT_TRUE(mD3D11Device != nullptr);
154         ID3D11Texture2D *texture = nullptr;
155         CD3D11_TEXTURE2D_DESC desc(format, static_cast<UINT>(width), static_cast<UINT>(height), 1,
156                                    1, bindFlags);
157         desc.SampleDesc.Count   = sampleCount;
158         desc.SampleDesc.Quality = sampleQuality;
159         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
160 
161         EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
162                                                               texture, config, attribs);
163 
164         texture->Release();
165 
166         return pbuffer;
167     }
168 
createD3D11PBuffer(size_t width,size_t height,EGLint eglTextureFormat,EGLint eglTextureTarget,UINT sampleCount,UINT sampleQuality,UINT bindFlags,DXGI_FORMAT format)169     EGLSurface createD3D11PBuffer(size_t width,
170                                   size_t height,
171                                   EGLint eglTextureFormat,
172                                   EGLint eglTextureTarget,
173                                   UINT sampleCount,
174                                   UINT sampleQuality,
175                                   UINT bindFlags,
176                                   DXGI_FORMAT format)
177     {
178         EGLint attribs[] = {
179             EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
180             eglTextureTarget,   EGL_NONE,         EGL_NONE,
181         };
182         return createD3D11PBuffer(width, height, sampleCount, sampleQuality, bindFlags, format,
183                                   attribs);
184     }
185 
createPBuffer(size_t width,size_t height,EGLint eglTextureFormat,EGLint eglTextureTarget,UINT sampleCount,UINT sampleQuality)186     EGLSurface createPBuffer(size_t width,
187                              size_t height,
188                              EGLint eglTextureFormat,
189                              EGLint eglTextureTarget,
190                              UINT sampleCount,
191                              UINT sampleQuality)
192     {
193         if (mD3D11Device)
194         {
195             return createD3D11PBuffer(
196                 width, height, eglTextureFormat, eglTextureTarget, sampleCount, sampleQuality,
197                 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
198         }
199 
200         if (mD3D9Device)
201         {
202             EGLWindow *window  = getEGLWindow();
203             EGLDisplay display = window->getDisplay();
204             EGLConfig config   = window->getConfig();
205 
206             EGLint attribs[] = {
207                 EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
208                 eglTextureTarget,   EGL_NONE,         EGL_NONE,
209             };
210 
211             // Multisampled textures are not supported on D3D9.
212             EXPECT_TRUE(sampleCount <= 1);
213             EXPECT_TRUE(sampleQuality == 0);
214 
215             IDirect3DTexture9 *texture = nullptr;
216             EXPECT_TRUE(SUCCEEDED(mD3D9Device->CreateTexture(
217                 static_cast<UINT>(width), static_cast<UINT>(height), 1, D3DUSAGE_RENDERTARGET,
218                 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr)));
219 
220             EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
221                                                                   texture, config, attribs);
222 
223             texture->Release();
224 
225             return pbuffer;
226         }
227         else
228         {
229             return EGL_NO_SURFACE;
230         }
231     }
232 
valid() const233     bool valid() const
234     {
235         EGLWindow *window  = getEGLWindow();
236         EGLDisplay display = window->getDisplay();
237         if (!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_d3d_texture_client_buffer"))
238         {
239             std::cout << "Test skipped due to missing EGL_ANGLE_d3d_texture_client_buffer"
240                       << std::endl;
241             return false;
242         }
243 
244         if (!mD3D11Device && !mD3D9Device)
245         {
246             std::cout << "Test skipped due to no D3D devices being available." << std::endl;
247             return false;
248         }
249 
250         if (IsWindows() && IsAMD() && IsOpenGL())
251         {
252             std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
253             return false;
254         }
255 
256         if (IsWindows() && IsIntel() && IsOpenGL())
257         {
258             std::cout << "Test skipped on Windows Intel OpenGL." << std::endl;
259             return false;
260         }
261         return true;
262     }
263 
testTextureSamplesAs50PercentGreen(GLuint texture)264     void testTextureSamplesAs50PercentGreen(GLuint texture)
265     {
266         GLFramebuffer scratchFbo;
267         glBindFramebuffer(GL_FRAMEBUFFER, scratchFbo);
268         GLTexture scratchTexture;
269         glBindTexture(GL_TEXTURE_2D, scratchTexture);
270         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
271         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scratchTexture,
272                                0);
273 
274         glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
275         glClear(GL_COLOR_BUFFER_BIT);
276 
277         glUseProgram(mTextureProgram);
278         glUniform1i(mTextureUniformLocation, 0);
279         glActiveTexture(GL_TEXTURE0);
280         glBindTexture(GL_TEXTURE_2D, texture);
281         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
282         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
283         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
284         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
285 
286         drawQuad(mTextureProgram, "position", 0.5f);
287         ASSERT_GL_NO_ERROR();
288 
289         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
290     }
291 
292     GLuint mTextureProgram;
293     GLuint mTextureProgramNoSampling;
294     GLint mTextureUniformLocation;
295 
296     HMODULE mD3D11Module       = nullptr;
297     ID3D11Device *mD3D11Device = nullptr;
298 
299     IDirect3DDevice9 *mD3D9Device = nullptr;
300 };
301 
302 // Test creating pbuffer from textures with several different DXGI formats.
TEST_P(D3DTextureTest,TestD3D11SupportedFormatsSurface)303 TEST_P(D3DTextureTest, TestD3D11SupportedFormatsSurface)
304 {
305     bool srgbSupported = IsGLExtensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
306     ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgbSupported);
307 
308     const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
309                                    DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
310     for (size_t i = 0; i < 4; ++i)
311     {
312         if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
313         {
314             if (IsOpenGL())
315             {
316                 // This generates an invalid format error when calling wglDXRegisterObjectNV().
317                 // Reproducible at least on NVIDIA driver 390.65 on Windows 10.
318                 std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
319                 continue;
320             }
321         }
322 
323         EGLSurface pbuffer = createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
324                                                 D3D11_BIND_RENDER_TARGET, formats[i]);
325         ASSERT_EGL_SUCCESS();
326         ASSERT_NE(EGL_NO_SURFACE, pbuffer);
327 
328         EGLWindow *window  = getEGLWindow();
329         EGLDisplay display = window->getDisplay();
330 
331         EGLint colorspace = EGL_NONE;
332         eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
333 
334         if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
335             formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
336         {
337             EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
338         }
339         else
340         {
341             EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
342         }
343 
344         eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
345         ASSERT_EGL_SUCCESS();
346         window->makeCurrent();
347         eglDestroySurface(display, pbuffer);
348     }
349 }
350 
351 // Test binding a pbuffer created from a D3D texture as a texture image with several different DXGI
352 // formats. The test renders to and samples from the pbuffer.
TEST_P(D3DTextureTest,TestD3D11SupportedFormatsTexture)353 TEST_P(D3DTextureTest, TestD3D11SupportedFormatsTexture)
354 {
355     bool srgb8alpha8TextureAttachmentSupported = getClientMajorVersion() >= 3;
356     ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgb8alpha8TextureAttachmentSupported);
357 
358     bool srgbWriteControlSupported =
359         IsGLExtensionEnabled("GL_EXT_sRGB_write_control") && !IsOpenGL();
360 
361     const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
362                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
363                                    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
364     for (size_t i = 0; i < 4; ++i)
365     {
366         if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
367         {
368             if (IsOpenGL())
369             {
370                 // This generates an invalid format error when calling wglDXRegisterObjectNV().
371                 // Reproducible at least on NVIDIA driver 390.65 on Windows 10.
372                 std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
373                 continue;
374             }
375         }
376 
377         SCOPED_TRACE(std::string("Test case:") + std::to_string(i));
378         EGLWindow *window  = getEGLWindow();
379         EGLDisplay display = window->getDisplay();
380 
381         EGLSurface pbuffer =
382             createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
383                                D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, formats[i]);
384         ASSERT_EGL_SUCCESS();
385         ASSERT_NE(EGL_NO_SURFACE, pbuffer);
386 
387         EGLint colorspace = EGL_NONE;
388         eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
389 
390         GLuint texture = 0u;
391         glGenTextures(1, &texture);
392         glBindTexture(GL_TEXTURE_2D, texture);
393         EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
394         ASSERT_EGL_SUCCESS();
395         ASSERT_EGL_TRUE(result);
396 
397         GLuint fbo = 0u;
398         glGenFramebuffers(1, &fbo);
399         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
400         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
401         glViewport(0, 0, 32, 32);
402 
403         GLint colorEncoding = 0;
404         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
405                                               GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
406                                               &colorEncoding);
407 
408         if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
409             formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
410         {
411             EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
412             EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
413         }
414         else
415         {
416             EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
417             EXPECT_EQ(GL_LINEAR, colorEncoding);
418         }
419 
420         // Clear the texture with 50% green and check that the color value written is correct.
421         glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
422 
423         if (colorEncoding == GL_SRGB_EXT)
424         {
425             glClear(GL_COLOR_BUFFER_BIT);
426             EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 188u, 0u, 255u), 2);
427             // Disable SRGB and run the non-sRGB test case.
428             if (srgbWriteControlSupported)
429                 glDisable(GL_FRAMEBUFFER_SRGB_EXT);
430         }
431 
432         if (colorEncoding == GL_LINEAR || srgbWriteControlSupported)
433         {
434             glClear(GL_COLOR_BUFFER_BIT);
435             EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
436         }
437 
438         // Draw with the texture to a linear framebuffer and check that the color value written is
439         // correct.
440         testTextureSamplesAs50PercentGreen(texture);
441 
442         glBindFramebuffer(GL_FRAMEBUFFER, 0u);
443         glBindTexture(GL_TEXTURE_2D, 0u);
444         glDeleteTextures(1, &texture);
445         glDeleteFramebuffers(1, &fbo);
446         eglDestroySurface(display, pbuffer);
447     }
448 }
449 
450 // Test binding a pbuffer created from a D3D texture as a texture image with typeless texture
451 // formats.
TEST_P(D3DTextureTest,TestD3D11TypelessTexture)452 TEST_P(D3DTextureTest, TestD3D11TypelessTexture)
453 {
454     EGLWindow *window  = getEGLWindow();
455     EGLDisplay display = window->getDisplay();
456 
457     ANGLE_SKIP_TEST_IF(!valid());
458 
459     // Typeless formats are optional in the spec and currently only supported on D3D11 backend.
460     ANGLE_SKIP_TEST_IF(!IsD3D11());
461 
462     // GL_SRGB8_ALPHA8 texture attachment support is required.
463     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
464 
465     const std::array<EGLint, 2> eglGlColorspaces = {EGL_GL_COLORSPACE_LINEAR,
466                                                     EGL_GL_COLORSPACE_SRGB};
467     const std::array<DXGI_FORMAT, 2> dxgiFormats = {DXGI_FORMAT_R8G8B8A8_TYPELESS,
468                                                     DXGI_FORMAT_B8G8R8A8_TYPELESS};
469     for (auto eglGlColorspace : eglGlColorspaces)
470     {
471         for (auto dxgiFormat : dxgiFormats)
472         {
473             SCOPED_TRACE(std::string("Test case:") + std::to_string(eglGlColorspace) + " / " +
474                          std::to_string(dxgiFormat));
475 
476             EGLint attribs[] = {
477                 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
478                 EGL_GL_COLORSPACE,  eglGlColorspace,  EGL_NONE,           EGL_NONE,
479             };
480 
481             EGLSurface pbuffer = createD3D11PBuffer(
482                 32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, dxgiFormat,
483                 attribs);
484 
485             ASSERT_EGL_SUCCESS();
486             ASSERT_NE(EGL_NO_SURFACE, pbuffer);
487 
488             EGLint colorspace = EGL_NONE;
489             eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
490 
491             GLuint texture = 0u;
492             glGenTextures(1, &texture);
493             glBindTexture(GL_TEXTURE_2D, texture);
494             EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
495             ASSERT_EGL_SUCCESS();
496             ASSERT_EGL_TRUE(result);
497 
498             GLuint fbo = 0u;
499             glGenFramebuffers(1, &fbo);
500             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
501             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
502             glViewport(0, 0, 32, 32);
503 
504             GLint colorEncoding = 0;
505             glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
506                                                   GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
507                                                   &colorEncoding);
508 
509             if (eglGlColorspace == EGL_GL_COLORSPACE_LINEAR)
510             {
511                 EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
512                 EXPECT_EQ(GL_LINEAR, colorEncoding);
513             }
514             else
515             {
516                 EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
517                 EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
518             }
519 
520             // Clear the texture with 50% green and check that the color value written is correct.
521             glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
522 
523             if (colorEncoding == GL_SRGB_EXT)
524             {
525                 glClear(GL_COLOR_BUFFER_BIT);
526                 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 188u, 0u, 255u), 2);
527             }
528             if (colorEncoding == GL_LINEAR)
529             {
530                 glClear(GL_COLOR_BUFFER_BIT);
531                 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
532             }
533 
534             // Draw with the texture to a linear framebuffer and check that the color value written
535             // is correct.
536             testTextureSamplesAs50PercentGreen(texture);
537 
538             glBindFramebuffer(GL_FRAMEBUFFER, 0u);
539             glBindTexture(GL_TEXTURE_2D, 0u);
540             glDeleteTextures(1, &texture);
541             glDeleteFramebuffers(1, &fbo);
542             eglDestroySurface(display, pbuffer);
543         }
544     }
545 }
546 
547 class D3DTextureTestES3 : public D3DTextureTest
548 {
549   protected:
D3DTextureTestES3()550     D3DTextureTestES3() : D3DTextureTest() {}
551 };
552 
553 // Test swizzling a pbuffer created from a D3D texture as a texture image with typeless texture
554 // formats.
TEST_P(D3DTextureTestES3,TestD3D11TypelessTextureSwizzle)555 TEST_P(D3DTextureTestES3, TestD3D11TypelessTextureSwizzle)
556 {
557     EGLWindow *window  = getEGLWindow();
558     EGLDisplay display = window->getDisplay();
559 
560     ANGLE_SKIP_TEST_IF(!valid());
561 
562     // Typeless formats are optional in the spec and currently only supported on D3D11 backend.
563     ANGLE_SKIP_TEST_IF(!IsD3D11());
564 
565     const std::array<EGLint, 2> eglGlColorspaces = {EGL_GL_COLORSPACE_LINEAR,
566                                                     EGL_GL_COLORSPACE_SRGB};
567     const std::array<DXGI_FORMAT, 2> dxgiFormats = {DXGI_FORMAT_R8G8B8A8_TYPELESS,
568                                                     DXGI_FORMAT_B8G8R8A8_TYPELESS};
569     for (auto eglGlColorspace : eglGlColorspaces)
570     {
571         for (auto dxgiFormat : dxgiFormats)
572         {
573             SCOPED_TRACE(std::string("Test case:") + std::to_string(eglGlColorspace) + " / " +
574                          std::to_string(dxgiFormat));
575 
576             EGLint attribs[] = {
577                 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
578                 EGL_GL_COLORSPACE,  eglGlColorspace,  EGL_NONE,           EGL_NONE,
579             };
580 
581             EGLSurface pbuffer = createD3D11PBuffer(
582                 32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, dxgiFormat,
583                 attribs);
584 
585             ASSERT_EGL_SUCCESS();
586             ASSERT_NE(EGL_NO_SURFACE, pbuffer);
587 
588             EGLint colorspace = EGL_NONE;
589             eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
590 
591             GLuint texture = 0u;
592             glGenTextures(1, &texture);
593             glBindTexture(GL_TEXTURE_2D, texture);
594             EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
595             ASSERT_EGL_SUCCESS();
596             ASSERT_EGL_TRUE(result);
597 
598             GLuint fbo = 0u;
599             glGenFramebuffers(1, &fbo);
600             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
601             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
602             glViewport(0, 0, 32, 32);
603 
604             GLint colorEncoding = 0;
605             glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
606                                                   GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
607                                                   &colorEncoding);
608 
609             // Clear the texture with 50% blue and check that the color value written is correct.
610             glClearColor(0.0f, 0.0f, 0.5f, 1.0f);
611 
612             if (colorEncoding == GL_SRGB_EXT)
613             {
614                 glClear(GL_COLOR_BUFFER_BIT);
615                 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 0u, 188u, 255u), 2);
616             }
617             if (colorEncoding == GL_LINEAR)
618             {
619                 glClear(GL_COLOR_BUFFER_BIT);
620                 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 0u, 127u, 255u), 2);
621             }
622 
623             // Swizzle the green channel to be sampled from the blue channel of the texture and vice
624             // versa.
625             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
626             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_GREEN);
627             ASSERT_GL_NO_ERROR();
628 
629             // Draw with the texture to a linear framebuffer and check that the color value written
630             // is correct.
631             testTextureSamplesAs50PercentGreen(texture);
632 
633             glBindFramebuffer(GL_FRAMEBUFFER, 0u);
634             glBindTexture(GL_TEXTURE_2D, 0u);
635             glDeleteTextures(1, &texture);
636             glDeleteFramebuffers(1, &fbo);
637             eglDestroySurface(display, pbuffer);
638         }
639     }
640 }
641 
642 // Test that EGL_GL_COLORSPACE attrib is not allowed for typed D3D textures.
TEST_P(D3DTextureTest,GlColorspaceNotAllowedForTypedD3DTexture)643 TEST_P(D3DTextureTest, GlColorspaceNotAllowedForTypedD3DTexture)
644 {
645     ANGLE_SKIP_TEST_IF(!valid());
646 
647     // D3D11 device is required to be able to create the texture.
648     ANGLE_SKIP_TEST_IF(!mD3D11Device);
649 
650     // SRGB support is required.
651     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3);
652 
653     EGLint attribsExplicitColorspace[] = {
654         EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,       EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
655         EGL_GL_COLORSPACE,  EGL_GL_COLORSPACE_SRGB, EGL_NONE,           EGL_NONE,
656     };
657     EGLSurface pbuffer =
658         createD3D11PBuffer(32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
659                            DXGI_FORMAT_R8G8B8A8_UNORM, attribsExplicitColorspace);
660 
661     ASSERT_EGL_ERROR(EGL_BAD_MATCH);
662     ASSERT_EQ(EGL_NO_SURFACE, pbuffer);
663 }
664 
665 // Test that trying to create a pbuffer from a typeless texture fails as expected on the backends
666 // where they are known not to be supported.
TEST_P(D3DTextureTest,TypelessD3DTextureNotSupported)667 TEST_P(D3DTextureTest, TypelessD3DTextureNotSupported)
668 {
669     ANGLE_SKIP_TEST_IF(!valid());
670 
671     // D3D11 device is required to be able to create the texture.
672     ANGLE_SKIP_TEST_IF(!mD3D11Device);
673 
674     // Currently typeless textures are supported on the D3D11 backend. We're testing the backends
675     // where there is no support.
676     ANGLE_SKIP_TEST_IF(IsD3D11());
677 
678     // SRGB support is required.
679     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3);
680 
681     EGLint attribs[] = {
682         EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET,
683         EGL_TEXTURE_2D,     EGL_NONE,         EGL_NONE,
684     };
685     EGLSurface pbuffer =
686         createD3D11PBuffer(32, 32, 1, 0, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
687                            DXGI_FORMAT_R8G8B8A8_TYPELESS, attribs);
688     ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
689     ASSERT_EQ(EGL_NO_SURFACE, pbuffer);
690 }
691 
692 // Test creating a pbuffer with unnecessary EGL_WIDTH and EGL_HEIGHT attributes because that's what
693 // Chromium does. This is a regression test for crbug.com/794086
TEST_P(D3DTextureTest,UnnecessaryWidthHeightAttributes)694 TEST_P(D3DTextureTest, UnnecessaryWidthHeightAttributes)
695 {
696     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
697     ASSERT_TRUE(mD3D11Device != nullptr);
698     ID3D11Texture2D *texture = nullptr;
699     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
700     desc.SampleDesc.Count   = 1;
701     desc.SampleDesc.Quality = 0;
702     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
703 
704     EGLint attribs[] = {
705         EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
706         EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
707         EGL_WIDTH,          1,
708         EGL_HEIGHT,         1,
709         EGL_NONE,           EGL_NONE,
710     };
711 
712     EGLWindow *window  = getEGLWindow();
713     EGLDisplay display = window->getDisplay();
714     EGLConfig config   = window->getConfig();
715 
716     EGLSurface pbuffer =
717         eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE, texture, config, attribs);
718 
719     ASSERT_EGL_SUCCESS();
720     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
721 
722     texture->Release();
723 
724     // Make current with fixture EGL to ensure the Surface can be released immediately.
725     getEGLWindow()->makeCurrent();
726     eglDestroySurface(display, pbuffer);
727 }
728 
729 // Test creating a pbuffer from a d3d surface and clearing it
TEST_P(D3DTextureTest,Clear)730 TEST_P(D3DTextureTest, Clear)
731 {
732     if (!valid())
733     {
734         return;
735     }
736 
737     EGLWindow *window  = getEGLWindow();
738     EGLDisplay display = window->getDisplay();
739 
740     const size_t bufferSize = 32;
741 
742     EGLSurface pbuffer =
743         createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
744     ASSERT_EGL_SUCCESS();
745     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
746 
747     // Apply the Pbuffer and clear it to purple and verify
748     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
749     ASSERT_EGL_SUCCESS();
750 
751     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
752     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
753     glClear(GL_COLOR_BUFFER_BIT);
754     ASSERT_GL_NO_ERROR();
755 
756     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
757                     255, 255);
758 
759     // Make current with fixture EGL to ensure the Surface can be released immediately.
760     getEGLWindow()->makeCurrent();
761     eglDestroySurface(display, pbuffer);
762 }
763 
764 // Test creating a pbuffer with a D3D texture and depth stencil bits in the EGL config creates keeps
765 // its depth stencil buffer
TEST_P(D3DTextureTest,DepthStencil)766 TEST_P(D3DTextureTest, DepthStencil)
767 {
768     if (!valid())
769     {
770         return;
771     }
772 
773     EGLWindow *window  = getEGLWindow();
774     EGLDisplay display = window->getDisplay();
775 
776     const size_t bufferSize = 32;
777 
778     EGLSurface pbuffer =
779         createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 1, 0);
780     ASSERT_EGL_SUCCESS();
781     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
782 
783     // Apply the Pbuffer and clear it to purple and verify
784     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
785     ASSERT_EGL_SUCCESS();
786 
787     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
788     glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
789     glClearDepthf(0.5f);
790     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
791     ASSERT_GL_NO_ERROR();
792 
793     glEnable(GL_DEPTH_TEST);
794     glDepthMask(GL_FALSE);
795 
796     glUseProgram(mTextureProgram);
797     glUniform1i(mTextureUniformLocation, 0);
798 
799     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
800 
801     // Draw a quad that will fail the depth test and verify that the buffer is unchanged
802     drawQuad(mTextureProgram, "position", 1.0f);
803     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
804                           GLColor::cyan);
805 
806     // Draw a quad that will pass the depth test and verify that the buffer is green
807     drawQuad(mTextureProgram, "position", -1.0f);
808     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
809                           GLColor::green);
810 
811     // Make current with fixture EGL to ensure the Surface can be released immediately.
812     getEGLWindow()->makeCurrent();
813     eglDestroySurface(display, pbuffer);
814 }
815 
816 // Test creating a pbuffer from a d3d surface and binding it to a texture
TEST_P(D3DTextureTest,BindTexImage)817 TEST_P(D3DTextureTest, BindTexImage)
818 {
819     if (!valid())
820     {
821         return;
822     }
823 
824     EGLWindow *window  = getEGLWindow();
825     EGLDisplay display = window->getDisplay();
826 
827     const size_t bufferSize = 32;
828 
829     EGLSurface pbuffer =
830         createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0);
831     ASSERT_EGL_SUCCESS();
832     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
833 
834     // Apply the Pbuffer and clear it to purple
835     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
836     ASSERT_EGL_SUCCESS();
837 
838     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
839     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
840     glClear(GL_COLOR_BUFFER_BIT);
841     ASSERT_GL_NO_ERROR();
842 
843     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
844                     255, 255);
845 
846     // Apply the window surface
847     eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
848 
849     // Create a texture and bind the Pbuffer to it
850     GLuint texture = 0;
851     glGenTextures(1, &texture);
852     glBindTexture(GL_TEXTURE_2D, texture);
853     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
854     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
855     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
856     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
857     EXPECT_GL_NO_ERROR();
858 
859     eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
860     glViewport(0, 0, getWindowWidth(), getWindowHeight());
861     ASSERT_EGL_SUCCESS();
862 
863     // Draw a quad and verify that it is purple
864     glUseProgram(mTextureProgram);
865     glUniform1i(mTextureUniformLocation, 0);
866 
867     drawQuad(mTextureProgram, "position", 0.5f);
868     EXPECT_GL_NO_ERROR();
869 
870     // Unbind the texture
871     eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
872     ASSERT_EGL_SUCCESS();
873 
874     // Verify that purple was drawn
875     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
876 
877     glDeleteTextures(1, &texture);
878 
879     // Make current with fixture EGL to ensure the Surface can be released immediately.
880     getEGLWindow()->makeCurrent();
881     eglDestroySurface(display, pbuffer);
882 }
883 
884 // Verify that creating a pbuffer with a multisampled texture will fail on a non-multisampled
885 // window.
TEST_P(D3DTextureTest,CheckSampleMismatch)886 TEST_P(D3DTextureTest, CheckSampleMismatch)
887 {
888     if (!valid())
889     {
890         return;
891     }
892 
893     // Multisampling is not supported on D3D9 or OpenGL.
894     ANGLE_SKIP_TEST_IF(IsD3D9() || IsOpenGL());
895 
896     constexpr size_t bufferSize = 32;
897 
898     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
899                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
900     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
901     EXPECT_EQ(pbuffer, nullptr);
902 }
903 
904 // Tests what happens when we make a PBuffer that isn't shader-readable.
TEST_P(D3DTextureTest,NonReadablePBuffer)905 TEST_P(D3DTextureTest, NonReadablePBuffer)
906 {
907     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
908 
909     constexpr size_t bufferSize = 32;
910 
911     EGLSurface pbuffer =
912         createD3D11PBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
913                            D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
914 
915     ASSERT_EGL_SUCCESS();
916     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
917 
918     EGLWindow *window  = getEGLWindow();
919     EGLDisplay display = window->getDisplay();
920 
921     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
922     ASSERT_EGL_SUCCESS();
923 
924     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
925 
926     // Clear to green.
927     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
928     glClear(GL_COLOR_BUFFER_BIT);
929     ASSERT_GL_NO_ERROR();
930     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
931 
932     // Copy the green color to a texture.
933     GLTexture tex;
934     glBindTexture(GL_TEXTURE_2D, tex);
935     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
936     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
937     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, bufferSize, bufferSize, 0);
938     ASSERT_GL_NO_ERROR();
939 
940     // Clear to red.
941     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
942     glClear(GL_COLOR_BUFFER_BIT);
943     ASSERT_GL_NO_ERROR();
944     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
945 
946     // Draw with the texture and expect green.
947     draw2DTexturedQuad(0.5f, 1.0f, false);
948     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
949 
950     // Make current with fixture EGL to ensure the Surface can be released immediately.
951     getEGLWindow()->makeCurrent();
952     eglDestroySurface(display, pbuffer);
953 }
954 
955 class D3DTextureTestMS : public D3DTextureTest
956 {
957   protected:
D3DTextureTestMS()958     D3DTextureTestMS() : D3DTextureTest()
959     {
960         setSamples(4);
961         setMultisampleEnabled(true);
962     }
963 };
964 
965 // Test creating a pbuffer from a multisampled d3d surface and clearing it.
TEST_P(D3DTextureTestMS,Clear)966 TEST_P(D3DTextureTestMS, Clear)
967 {
968     EGLWindow *window  = getEGLWindow();
969     EGLDisplay display = window->getDisplay();
970 
971     constexpr size_t bufferSize = 32;
972     constexpr UINT testpoint    = bufferSize / 2;
973 
974     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
975                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
976     ASSERT_EGL_SUCCESS();
977     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
978 
979     // Apply the Pbuffer and clear it to magenta and verify
980     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
981     ASSERT_EGL_SUCCESS();
982 
983     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
984     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
985     glClear(GL_COLOR_BUFFER_BIT);
986     ASSERT_GL_NO_ERROR();
987     EXPECT_PIXEL_COLOR_EQ(testpoint, testpoint, GLColor::magenta);
988 
989     // Make current with fixture EGL to ensure the Surface can be released immediately.
990     getEGLWindow()->makeCurrent();
991     eglDestroySurface(display, pbuffer);
992 }
993 
994 // Test creating a pbuffer from a multisampled d3d surface and drawing with a program.
TEST_P(D3DTextureTestMS,DrawProgram)995 TEST_P(D3DTextureTestMS, DrawProgram)
996 {
997     EGLWindow *window  = getEGLWindow();
998     EGLDisplay display = window->getDisplay();
999 
1000     constexpr size_t bufferSize = 32;
1001 
1002     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1003                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1004     ASSERT_EGL_SUCCESS();
1005     ASSERT_NE(pbuffer, EGL_NO_SURFACE);
1006 
1007     // Apply the Pbuffer and clear it to magenta
1008     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1009     ASSERT_EGL_SUCCESS();
1010 
1011     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1012     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1013     glClear(GL_COLOR_BUFFER_BIT);
1014     ASSERT_GL_NO_ERROR();
1015 
1016     constexpr GLint testPoint = bufferSize / 2;
1017     EXPECT_PIXEL_COLOR_EQ(testPoint, testPoint, GLColor::magenta);
1018 
1019     // Apply the window surface
1020     eglMakeCurrent(display, window->getSurface(), window->getSurface(), window->getContext());
1021     ASSERT_EGL_SUCCESS();
1022 
1023     glViewport(0, 0, getWindowWidth(), getWindowHeight());
1024     ASSERT_EGL_SUCCESS();
1025 
1026     // Draw a quad and verify that it is magenta
1027     glUseProgram(mTextureProgramNoSampling);
1028     EXPECT_GL_NO_ERROR();
1029 
1030     drawQuad(mTextureProgramNoSampling, "position", 0.5f);
1031     EXPECT_GL_NO_ERROR();
1032 
1033     // Verify that magenta was drawn
1034     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::magenta);
1035 
1036     // Make current with fixture EGL to ensure the Surface can be released immediately.
1037     getEGLWindow()->makeCurrent();
1038     eglDestroySurface(display, pbuffer);
1039 }
1040 
1041 // Test for failure when creating a pbuffer from a multisampled d3d surface to bind to a texture.
TEST_P(D3DTextureTestMS,BindTexture)1042 TEST_P(D3DTextureTestMS, BindTexture)
1043 {
1044     constexpr size_t bufferSize = 32;
1045 
1046     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 4,
1047                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1048 
1049     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
1050     EXPECT_EQ(pbuffer, nullptr);
1051 }
1052 
1053 // Verify that creating a pbuffer from a multisampled texture with a multisampled window will fail
1054 // when the sample counts do not match.
TEST_P(D3DTextureTestMS,CheckSampleMismatch)1055 TEST_P(D3DTextureTestMS, CheckSampleMismatch)
1056 {
1057     constexpr size_t bufferSize = 32;
1058 
1059     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 2,
1060                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1061 
1062     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1063     EXPECT_EQ(pbuffer, nullptr);
1064 }
1065 
1066 // Test creating a pbuffer with a D3D texture and depth stencil bits in the EGL config creates keeps
1067 // its depth stencil buffer
TEST_P(D3DTextureTestMS,DepthStencil)1068 TEST_P(D3DTextureTestMS, DepthStencil)
1069 {
1070     EGLWindow *window  = getEGLWindow();
1071     EGLDisplay display = window->getDisplay();
1072 
1073     const size_t bufferSize = 32;
1074 
1075     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1076                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1077     ASSERT_EGL_SUCCESS();
1078     ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1079 
1080     // Apply the Pbuffer and clear it to purple and verify
1081     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1082     ASSERT_EGL_SUCCESS();
1083 
1084     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1085     glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
1086     glClearDepthf(0.5f);
1087     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1088     ASSERT_GL_NO_ERROR();
1089 
1090     glEnable(GL_DEPTH_TEST);
1091     glDepthMask(GL_FALSE);
1092 
1093     glUseProgram(mTextureProgram);
1094     glUniform1i(mTextureUniformLocation, 0);
1095 
1096     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1097 
1098     // Draw a quad that will fail the depth test and verify that the buffer is unchanged
1099     drawQuad(mTextureProgram, "position", 1.0f);
1100     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1101                           GLColor::cyan);
1102 
1103     // Draw a quad that will pass the depth test and verify that the buffer is green
1104     drawQuad(mTextureProgram, "position", -1.0f);
1105     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1106                           GLColor::green);
1107 
1108     // Make current with fixture EGL to ensure the Surface can be released immediately.
1109     getEGLWindow()->makeCurrent();
1110     eglDestroySurface(display, pbuffer);
1111 }
1112 
1113 // Test copyTexImage2D with a multisampled resource
TEST_P(D3DTextureTestMS,CopyTexImage2DTest)1114 TEST_P(D3DTextureTestMS, CopyTexImage2DTest)
1115 {
1116     EGLWindow *window  = getEGLWindow();
1117     EGLDisplay display = window->getDisplay();
1118 
1119     constexpr size_t bufferSize = 32;
1120 
1121     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1122                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1123     ASSERT_EGL_SUCCESS();
1124     ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1125 
1126     // Apply the Pbuffer and clear it to magenta and verify
1127     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1128     ASSERT_EGL_SUCCESS();
1129 
1130     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1131     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1132     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1133     ASSERT_GL_NO_ERROR();
1134 
1135     glUseProgram(mTextureProgram);
1136     glUniform1i(mTextureUniformLocation, 0);
1137 
1138     // Specify a 2D texture and set it to green
1139     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1140 
1141     // Copy from the multisampled framebuffer to the 2D texture
1142     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
1143 
1144     // Draw a quad and verify the color is magenta, not green
1145     drawQuad(mTextureProgram, "position", 1.0f);
1146     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1147                           GLColor::magenta);
1148     ASSERT_GL_NO_ERROR();
1149 
1150     // Make current with fixture EGL to ensure the Surface can be released immediately.
1151     getEGLWindow()->makeCurrent();
1152     eglDestroySurface(display, pbuffer);
1153 }
1154 
1155 // Test copyTexSubImage2D with a multisampled resource
TEST_P(D3DTextureTestMS,CopyTexSubImage2DTest)1156 TEST_P(D3DTextureTestMS, CopyTexSubImage2DTest)
1157 {
1158     EGLWindow *window  = getEGLWindow();
1159     EGLDisplay display = window->getDisplay();
1160 
1161     constexpr size_t bufferSize = 32;
1162 
1163     EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE, 4,
1164                                        static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN));
1165     ASSERT_EGL_SUCCESS();
1166     ASSERT_NE(EGL_NO_SURFACE, pbuffer);
1167 
1168     // Apply the Pbuffer and clear it to magenta and verify
1169     eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
1170     ASSERT_EGL_SUCCESS();
1171 
1172     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1173     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
1174     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1175     ASSERT_GL_NO_ERROR();
1176 
1177     glUseProgram(mTextureProgram);
1178     glUniform1i(mTextureUniformLocation, 0);
1179 
1180     // Specify a 2D texture and set it to green
1181     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1182 
1183     // Copy from the multisampled framebuffer to the 2D texture
1184     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
1185 
1186     // Draw a quad and verify the color is magenta, not green
1187     drawQuad(mTextureProgram, "position", 1.0f);
1188     EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1189                           GLColor::magenta);
1190     ASSERT_GL_NO_ERROR();
1191 
1192     // Make current with fixture EGL to ensure the Surface can be released immediately.
1193     getEGLWindow()->makeCurrent();
1194     eglDestroySurface(display, pbuffer);
1195 }
1196 
1197 class D3DTextureClearTest : public D3DTextureTest
1198 {
1199   protected:
D3DTextureClearTest()1200     D3DTextureClearTest() : D3DTextureTest() {}
1201 
RunClearTest(DXGI_FORMAT format)1202     void RunClearTest(DXGI_FORMAT format)
1203     {
1204         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1205 
1206         EGLWindow *window  = getEGLWindow();
1207         EGLDisplay display = window->getDisplay();
1208 
1209         window->makeCurrent();
1210 
1211         const UINT bufferSize = 32;
1212         EXPECT_TRUE(mD3D11Device != nullptr);
1213         ID3D11Texture2D *d3d11Texture = nullptr;
1214         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1215                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1216         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1217 
1218         // Can use unsized formats for all cases, but use sized ones to match Chromium.
1219         EGLint internalFormat = GL_NONE;
1220         switch (format)
1221         {
1222             case DXGI_FORMAT_R8G8B8A8_UNORM:
1223             case DXGI_FORMAT_R16G16B16A16_FLOAT:
1224                 internalFormat = GL_RGBA;
1225                 break;
1226             case DXGI_FORMAT_B8G8R8A8_UNORM:
1227                 internalFormat = GL_BGRA_EXT;
1228                 break;
1229             case DXGI_FORMAT_R8_UNORM:
1230                 internalFormat = GL_RED_EXT;
1231                 break;
1232             case DXGI_FORMAT_R8G8_UNORM:
1233                 internalFormat = GL_RG_EXT;
1234                 break;
1235             case DXGI_FORMAT_R10G10B10A2_UNORM:
1236                 internalFormat = GL_RGB10_A2_EXT;
1237                 break;
1238             case DXGI_FORMAT_R16_UNORM:
1239                 internalFormat = GL_R16_EXT;
1240                 break;
1241             case DXGI_FORMAT_R16G16_UNORM:
1242                 internalFormat = GL_RG16_EXT;
1243                 break;
1244             default:
1245                 ASSERT_TRUE(false);
1246                 break;
1247         }
1248 
1249         const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, internalFormat, EGL_NONE};
1250 
1251         EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1252                                            static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1253         ASSERT_EGL_SUCCESS();
1254         ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1255 
1256         GLuint texture;
1257         glGenTextures(1, &texture);
1258         glBindTexture(GL_TEXTURE_2D, texture);
1259         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1260         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1261         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1262         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1263         ASSERT_GL_NO_ERROR();
1264 
1265         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1266         ASSERT_GL_NO_ERROR();
1267 
1268         GLuint fbo;
1269         glGenFramebuffers(1, &fbo);
1270         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1271         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1272         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1273                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1274         ASSERT_GL_NO_ERROR();
1275 
1276         glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1277         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1278         glClear(GL_COLOR_BUFFER_BIT);
1279         ASSERT_GL_NO_ERROR();
1280 
1281         if (format == DXGI_FORMAT_R16G16B16A16_FLOAT)
1282         {
1283             EXPECT_PIXEL_32F_EQ(static_cast<GLint>(bufferSize) / 2,
1284                                 static_cast<GLint>(bufferSize) / 2, 1.0f, 1.0f, 1.0f, 1.0f);
1285         }
1286         else if (format == DXGI_FORMAT_R16_UNORM)
1287         {
1288             EXPECT_PIXEL_16_NEAR(static_cast<GLint>(bufferSize) / 2,
1289                                  static_cast<GLint>(bufferSize) / 2, 65535, 0, 0, 65535, 0);
1290         }
1291         else if (format == DXGI_FORMAT_R16G16_UNORM)
1292         {
1293             EXPECT_PIXEL_16_NEAR(static_cast<GLint>(bufferSize) / 2,
1294                                  static_cast<GLint>(bufferSize) / 2, 65535, 65535, 0, 65535, 0);
1295         }
1296         else
1297         {
1298             GLuint readColor[4] = {0, 0, 0, 255};
1299             switch (internalFormat)
1300             {
1301                 case GL_RGBA:
1302                 case GL_BGRA_EXT:
1303                 case GL_RGB10_A2_EXT:
1304                     readColor[0] = readColor[1] = readColor[2] = 255;
1305                     break;
1306                 case GL_RG_EXT:
1307                     readColor[0] = readColor[1] = 255;
1308                     break;
1309                 case GL_RED_EXT:
1310                     readColor[0] = 255;
1311                     break;
1312             }
1313             // Read back as GL_UNSIGNED_BYTE even though the texture might have more than 8bpc.
1314             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1315                             readColor[0], readColor[1], readColor[2], readColor[3]);
1316         }
1317 
1318         glDeleteFramebuffers(1, &fbo);
1319         glDeleteTextures(1, &texture);
1320         eglDestroyImageKHR(display, image);
1321 
1322         d3d11Texture->Release();
1323     }
1324 };
1325 
TEST_P(D3DTextureClearTest,ClearRGBA8)1326 TEST_P(D3DTextureClearTest, ClearRGBA8)
1327 {
1328     RunClearTest(DXGI_FORMAT_R8G8B8A8_UNORM);
1329 }
1330 
TEST_P(D3DTextureClearTest,ClearBGRA8)1331 TEST_P(D3DTextureClearTest, ClearBGRA8)
1332 {
1333     RunClearTest(DXGI_FORMAT_B8G8R8A8_UNORM);
1334 }
1335 
TEST_P(D3DTextureClearTest,ClearR8)1336 TEST_P(D3DTextureClearTest, ClearR8)
1337 {
1338     RunClearTest(DXGI_FORMAT_R8_UNORM);
1339 }
1340 
TEST_P(D3DTextureClearTest,ClearRG8)1341 TEST_P(D3DTextureClearTest, ClearRG8)
1342 {
1343     RunClearTest(DXGI_FORMAT_R8G8_UNORM);
1344 }
1345 
TEST_P(D3DTextureClearTest,ClearRGB10A2)1346 TEST_P(D3DTextureClearTest, ClearRGB10A2)
1347 {
1348     RunClearTest(DXGI_FORMAT_R10G10B10A2_UNORM);
1349 }
1350 
TEST_P(D3DTextureClearTest,ClearRGBAF16)1351 TEST_P(D3DTextureClearTest, ClearRGBAF16)
1352 {
1353     RunClearTest(DXGI_FORMAT_R16G16B16A16_FLOAT);
1354 }
1355 
TEST_P(D3DTextureClearTest,ClearR16)1356 TEST_P(D3DTextureClearTest, ClearR16)
1357 {
1358     RunClearTest(DXGI_FORMAT_R16_UNORM);
1359 }
1360 
TEST_P(D3DTextureClearTest,ClearRG16)1361 TEST_P(D3DTextureClearTest, ClearRG16)
1362 {
1363     RunClearTest(DXGI_FORMAT_R16G16_UNORM);
1364 }
1365 
TEST_P(D3DTextureTest,NonRenderableTextureImage)1366 TEST_P(D3DTextureTest, NonRenderableTextureImage)
1367 {
1368     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1369 
1370     EGLWindow *window  = getEGLWindow();
1371     EGLDisplay display = window->getDisplay();
1372 
1373     window->makeCurrent();
1374 
1375     const UINT bufferSize = 32;
1376     EXPECT_TRUE(mD3D11Device != nullptr);
1377     ID3D11Texture2D *d3d11Texture = nullptr;
1378     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1379                                D3D11_BIND_SHADER_RESOURCE);
1380     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1381 
1382     const EGLint attribs[] = {EGL_NONE};
1383 
1384     EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1385                                        static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1386     ASSERT_EGL_SUCCESS();
1387     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1388 
1389     GLuint texture;
1390     glGenTextures(1, &texture);
1391     glBindTexture(GL_TEXTURE_2D, texture);
1392     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1393     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1394     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1395     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1396     ASSERT_GL_NO_ERROR();
1397 
1398     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1399     ASSERT_GL_NO_ERROR();
1400 
1401     GLuint fbo;
1402     glGenFramebuffers(1, &fbo);
1403     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1404     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1405     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1406               static_cast<unsigned>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
1407     ASSERT_GL_NO_ERROR();
1408 
1409     glDeleteFramebuffers(1, &fbo);
1410     glDeleteTextures(1, &texture);
1411     eglDestroyImageKHR(display, image);
1412 
1413     d3d11Texture->Release();
1414 }
1415 
TEST_P(D3DTextureTest,RGBEmulationTextureImage)1416 TEST_P(D3DTextureTest, RGBEmulationTextureImage)
1417 {
1418     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1419 
1420     EGLWindow *window  = getEGLWindow();
1421     EGLDisplay display = window->getDisplay();
1422 
1423     window->makeCurrent();
1424 
1425     const UINT bufferSize = 32;
1426     EXPECT_TRUE(mD3D11Device != nullptr);
1427     ID3D11Texture2D *d3d11Texture = nullptr;
1428     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1429                                D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1430     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1431 
1432     const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGB, EGL_NONE};
1433 
1434     EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1435                                        static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1436     ASSERT_EGL_SUCCESS();
1437     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1438 
1439     GLuint texture;
1440     glGenTextures(1, &texture);
1441     glBindTexture(GL_TEXTURE_2D, texture);
1442     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1443     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1444     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1445     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1446     ASSERT_GL_NO_ERROR();
1447 
1448     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1449     ASSERT_GL_NO_ERROR();
1450 
1451     GLuint fbo;
1452     glGenFramebuffers(1, &fbo);
1453     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1454     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1455     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1456               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1457     ASSERT_GL_NO_ERROR();
1458 
1459     // Although we are writing 0.5 to the alpha channel it should have the same
1460     // side effects as if alpha were 1.0.
1461     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1462     glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1463     glClear(GL_COLOR_BUFFER_BIT);
1464     ASSERT_GL_NO_ERROR();
1465     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1466                     255, 255);
1467 
1468     GLuint rgbaRbo;
1469     glGenRenderbuffers(1, &rgbaRbo);
1470     glBindRenderbuffer(GL_RENDERBUFFER, rgbaRbo);
1471     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, bufferSize, bufferSize);
1472 
1473     GLuint rgbaFbo;
1474     glGenFramebuffers(1, &rgbaFbo);
1475     glBindFramebuffer(GL_FRAMEBUFFER, rgbaFbo);
1476     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbaRbo);
1477     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1478               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1479     ASSERT_GL_NO_ERROR();
1480 
1481     // BlitFramebuffer from/to RGBA framebuffer fails.
1482     glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbaFbo);
1483     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1484     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1485                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1486     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1487     ASSERT_GL_NO_ERROR();
1488 
1489     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1490     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbaFbo);
1491     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1492                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1493     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1494     ASSERT_GL_NO_ERROR();
1495 
1496     GLuint rgbRbo;
1497     glGenRenderbuffers(1, &rgbRbo);
1498     glBindRenderbuffer(GL_RENDERBUFFER, rgbRbo);
1499     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, bufferSize, bufferSize);
1500 
1501     GLuint rgbFbo;
1502     glGenFramebuffers(1, &rgbFbo);
1503     glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1504     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbRbo);
1505     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1506               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1507     ASSERT_GL_NO_ERROR();
1508     glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1509     glClear(GL_COLOR_BUFFER_BIT);
1510     ASSERT_GL_NO_ERROR();
1511 
1512     // Clear texture framebuffer.
1513     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1514     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1515     glClear(GL_COLOR_BUFFER_BIT);
1516     ASSERT_GL_NO_ERROR();
1517     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1518                     255);
1519 
1520     // BlitFramebuffer from/to RGB framebuffer succeeds.
1521     glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbFbo);
1522     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1523     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1524                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1525     ASSERT_GL_NO_ERROR();
1526     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1527                     255, 255);
1528 
1529     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1530     glClear(GL_COLOR_BUFFER_BIT);
1531     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1532     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbFbo);
1533     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1534                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1535     ASSERT_GL_NO_ERROR();
1536     glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1537     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1538                     255);
1539 
1540     glDeleteFramebuffers(1, &rgbFbo);
1541     glDeleteRenderbuffers(1, &rgbRbo);
1542     glDeleteFramebuffers(1, &rgbaFbo);
1543     glDeleteRenderbuffers(1, &rgbaRbo);
1544     glDeleteFramebuffers(1, &fbo);
1545     glDeleteTextures(1, &texture);
1546     eglDestroyImageKHR(display, image);
1547 
1548     d3d11Texture->Release();
1549 }
1550 
TEST_P(D3DTextureTest,TextureArray)1551 TEST_P(D3DTextureTest, TextureArray)
1552 {
1553     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1554 
1555     EGLWindow *window  = getEGLWindow();
1556     EGLDisplay display = window->getDisplay();
1557 
1558     window->makeCurrent();
1559 
1560     const UINT bufferSize = 32;
1561     const UINT arraySize  = 4;
1562 
1563     ID3D11Texture2D *d3d11Texture = nullptr;
1564     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, arraySize, 1,
1565                                D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1566     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1567 
1568     const unsigned char kRFill = 0x12;
1569     const unsigned char kGFill = 0x23;
1570     const unsigned char kBFill = 0x34;
1571     const unsigned char kAFill = 0x45;
1572 
1573     std::vector<unsigned char> imageData(bufferSize * bufferSize * 4, 0);
1574     for (size_t i = 0; i < imageData.size(); i += 4)
1575     {
1576         imageData[i]     = kRFill;
1577         imageData[i + 1] = kGFill;
1578         imageData[i + 2] = kBFill;
1579         imageData[i + 3] = kAFill;
1580     }
1581 
1582     ID3D11DeviceContext *context = nullptr;
1583     mD3D11Device->GetImmediateContext(&context);
1584     ASSERT_NE(context, nullptr);
1585 
1586     D3D11_BOX dstBox = {0, 0, 0, bufferSize, bufferSize, 1};
1587     context->UpdateSubresource(d3d11Texture, arraySize - 1, &dstBox, imageData.data(),
1588                                bufferSize * 4, imageData.size());
1589 
1590     const EGLint attribs[] = {EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, arraySize - 1, EGL_NONE};
1591     EGLImage image         = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1592                                                static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1593     ASSERT_EGL_SUCCESS();
1594     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1595 
1596     GLuint texture;
1597     glGenTextures(1, &texture);
1598     glBindTexture(GL_TEXTURE_2D, texture);
1599     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1600     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1601     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1602     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1603     ASSERT_GL_NO_ERROR();
1604 
1605     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1606     ASSERT_GL_NO_ERROR();
1607 
1608     GLuint fbo;
1609     glGenFramebuffers(1, &fbo);
1610     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1611     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1612     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1613               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1614     ASSERT_GL_NO_ERROR();
1615 
1616     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, kRFill,
1617                     kGFill, kBFill, kAFill);
1618 
1619     glDeleteFramebuffers(1, &fbo);
1620     glDeleteTextures(1, &texture);
1621     eglDestroyImageKHR(display, image);
1622 
1623     d3d11Texture->Release();
1624 }
1625 
1626 class D3DTextureYUVTest : public D3DTextureTest
1627 {
1628   protected:
CreateAndBindImageToTexture(EGLDisplay display,ID3D11Texture2D * d3d11Texture,EGLint plane,GLenum internalFormat,GLenum target,EGLImage * image,GLuint * texture)1629     void CreateAndBindImageToTexture(EGLDisplay display,
1630                                      ID3D11Texture2D *d3d11Texture,
1631                                      EGLint plane,
1632                                      GLenum internalFormat,
1633                                      GLenum target,
1634                                      EGLImage *image,
1635                                      GLuint *texture)
1636     {
1637         const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
1638                                   static_cast<EGLint>(internalFormat),
1639                                   EGL_D3D11_TEXTURE_PLANE_ANGLE, plane, EGL_NONE};
1640         *image                 = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1641                                                    static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1642         ASSERT_EGL_SUCCESS();
1643         ASSERT_NE(*image, EGL_NO_IMAGE_KHR);
1644 
1645         // Create and bind Y plane texture to image.
1646         glGenTextures(1, texture);
1647         glActiveTexture(GL_TEXTURE0);
1648         glBindTexture(target, *texture);
1649         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1650         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1651         glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1652         glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1653         ASSERT_GL_NO_ERROR();
1654 
1655         glEGLImageTargetTexture2DOES(target, *image);
1656         ASSERT_GL_NO_ERROR();
1657     }
1658 
RunYUVSamplerTest(DXGI_FORMAT format)1659     void RunYUVSamplerTest(DXGI_FORMAT format)
1660     {
1661         ASSERT_TRUE(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1662                     format == DXGI_FORMAT_P016);
1663         UINT formatSupport;
1664         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1665                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1666         ASSERT_TRUE(formatSupport &
1667                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE));
1668 
1669         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1670         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1671         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1672         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1673 
1674         constexpr char kVS[] =
1675             R"(precision highp float;
1676             attribute vec4 position;
1677             varying vec2 texcoord;
1678 
1679             void main()
1680             {
1681                 gl_Position = position;
1682                 texcoord = (position.xy * 0.5) + 0.5;
1683                 texcoord.y = 1.0 - texcoord.y;
1684             })";
1685 
1686         constexpr char kFS[] =
1687             R"(#extension GL_OES_EGL_image_external : require
1688             precision highp float;
1689             uniform samplerExternalOES tex;
1690             varying vec2 texcoord;
1691 
1692             void main()
1693             {
1694                 gl_FragColor = texture2D(tex, texcoord);
1695             })";
1696 
1697         GLuint program = CompileProgram(kVS, kFS);
1698         ASSERT_NE(0u, program) << "shader compilation failed.";
1699 
1700         GLint textureLocation = glGetUniformLocation(program, "tex");
1701         ASSERT_NE(-1, textureLocation);
1702 
1703         EGLWindow *window  = getEGLWindow();
1704         EGLDisplay display = window->getDisplay();
1705 
1706         window->makeCurrent();
1707 
1708         const UINT bufferSize = 32;
1709         EXPECT_TRUE(mD3D11Device != nullptr);
1710         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
1711         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1712                                    D3D11_BIND_SHADER_RESOURCE);
1713 
1714         std::vector<unsigned char> imageData;
1715 
1716         if (isNV12)
1717         {
1718             imageData.resize(bufferSize * bufferSize * 3 / 2);
1719             memset(imageData.data(), kYFillValue, bufferSize * bufferSize);
1720             const size_t kUVOffset = bufferSize * bufferSize;
1721             for (size_t i = 0; i < bufferSize * bufferSize / 2; i += 2)
1722             {
1723                 imageData[kUVOffset + i]     = kUFillValue;
1724                 imageData[kUVOffset + i + 1] = kVFillValue;
1725             }
1726         }
1727         else
1728         {
1729             imageData.resize(bufferSize * bufferSize * 3);
1730             const size_t kUVOffset = bufferSize * bufferSize * 2;
1731             for (size_t i = 0; i < kUVOffset; i += 2)
1732             {
1733                 imageData[i]     = kYFillValue & 0xff;
1734                 imageData[i + 1] = (kYFillValue >> 8) & 0xff;
1735                 if (kUVOffset + i < imageData.size())
1736                 {
1737                     // Interleave U & V samples.
1738                     const unsigned fill          = (i % 4 == 0) ? kUFillValue : kVFillValue;
1739                     imageData[kUVOffset + i]     = fill & 0xff;
1740                     imageData[kUVOffset + i + 1] = (fill >> 8) & 0xff;
1741                 }
1742             }
1743         }
1744 
1745         D3D11_SUBRESOURCE_DATA data = {};
1746         data.pSysMem                = static_cast<const void *>(imageData.data());
1747         data.SysMemPitch            = isNV12 ? bufferSize : bufferSize * 2;
1748 
1749         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, &data, &d3d11Texture)));
1750 
1751         // Create and bind Y plane texture to image.
1752         EGLImage yImage;
1753         GLuint yTexture;
1754 
1755         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
1756         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat,
1757                                     GL_TEXTURE_EXTERNAL_OES, &yImage, &yTexture);
1758 
1759         GLuint rbo;
1760         glGenRenderbuffers(1, &rbo);
1761         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1762         glRenderbufferStorage(GL_RENDERBUFFER, isNV12 ? GL_RGBA8_OES : GL_RGBA16_EXT, bufferSize,
1763                               bufferSize);
1764         ASSERT_GL_NO_ERROR();
1765 
1766         GLuint fbo;
1767         glGenFramebuffers(1, &fbo);
1768         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1769         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1770         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1771                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1772         ASSERT_GL_NO_ERROR();
1773 
1774         // Draw the Y plane using a shader.
1775         glUseProgram(program);
1776         glUniform1i(textureLocation, 0);
1777         ASSERT_GL_NO_ERROR();
1778 
1779         glViewport(0, 0, bufferSize, bufferSize);
1780         drawQuad(program, "position", 1.0f);
1781         ASSERT_GL_NO_ERROR();
1782 
1783         if (isNV12)
1784         {
1785 
1786             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1787                             kYFillValue, 0, 0, 0xff);
1788         }
1789         else
1790         {
1791             EXPECT_PIXEL_16_NEAR(static_cast<GLint>(bufferSize) / 2,
1792                                  static_cast<GLint>(bufferSize) / 2, kYFillValue, 0, 0, 0xffff, 0);
1793         }
1794         ASSERT_GL_NO_ERROR();
1795 
1796         // Create and bind UV plane texture to image.
1797         EGLImage uvImage;
1798         GLuint uvTexture;
1799 
1800         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
1801         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat,
1802                                     GL_TEXTURE_EXTERNAL_OES, &uvImage, &uvTexture);
1803 
1804         // Draw the UV plane using a shader.
1805         glUseProgram(program);
1806         glUniform1i(textureLocation, 0);
1807         ASSERT_GL_NO_ERROR();
1808 
1809         // Use only half of the framebuffer to match UV plane dimensions.
1810         glViewport(0, 0, bufferSize / 2, bufferSize / 2);
1811         drawQuad(program, "position", 1.0f);
1812         ASSERT_GL_NO_ERROR();
1813 
1814         if (isNV12)
1815         {
1816 
1817             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 4, static_cast<GLint>(bufferSize) / 4,
1818                             kUFillValue, kVFillValue, 0, 0xff);
1819         }
1820         else
1821         {
1822             EXPECT_PIXEL_16_NEAR(static_cast<GLint>(bufferSize) / 4,
1823                                  static_cast<GLint>(bufferSize) / 4, kUFillValue, kVFillValue, 0,
1824                                  0xffff, 0);
1825         }
1826         ASSERT_GL_NO_ERROR();
1827 
1828         glDeleteProgram(program);
1829         glDeleteTextures(1, &yTexture);
1830         glDeleteTextures(1, &uvTexture);
1831         glDeleteFramebuffers(1, &fbo);
1832         glDeleteRenderbuffers(1, &rbo);
1833         eglDestroyImageKHR(display, yImage);
1834         eglDestroyImageKHR(display, uvImage);
1835     }
1836 
RunYUVRenderTest(DXGI_FORMAT format)1837     void RunYUVRenderTest(DXGI_FORMAT format)
1838     {
1839         ASSERT(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1840                format == DXGI_FORMAT_P016);
1841         UINT formatSupport;
1842         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1843                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1844         ASSERT_TRUE(formatSupport &
1845                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET));
1846 
1847         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1848         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1849         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1850         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1851 
1852         constexpr char kVS[] =
1853             R"(precision highp float;
1854             attribute vec4 position;
1855             varying vec2 texcoord;
1856 
1857             void main()
1858             {
1859                 gl_Position = position;
1860                 texcoord = (position.xy * 0.5) + 0.5;
1861                 texcoord.y = 1.0 - texcoord.y;
1862             })";
1863 
1864         constexpr char kFS[] =
1865             R"(precision highp float;
1866             uniform vec4 color;
1867             varying vec2 texcoord;
1868 
1869             void main()
1870             {
1871                 gl_FragColor = color;
1872             })";
1873 
1874         GLuint program = CompileProgram(kVS, kFS);
1875         ASSERT_NE(0u, program) << "shader compilation failed.";
1876 
1877         GLint colorLocation = glGetUniformLocation(program, "color");
1878         ASSERT_NE(-1, colorLocation);
1879 
1880         EGLWindow *window  = getEGLWindow();
1881         EGLDisplay display = window->getDisplay();
1882 
1883         window->makeCurrent();
1884 
1885         const UINT bufferSize = 32;
1886         EXPECT_TRUE(mD3D11Device != nullptr);
1887         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
1888         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1889                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1890 
1891         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1892 
1893         // Create and bind Y plane texture to image.
1894         EGLImage yImage;
1895         GLuint yTexture;
1896 
1897         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
1898         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat, GL_TEXTURE_2D,
1899                                     &yImage, &yTexture);
1900 
1901         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, yImage);
1902         ASSERT_GL_NO_ERROR();
1903 
1904         GLuint fbo;
1905         glGenFramebuffers(1, &fbo);
1906         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1907         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
1908         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1909                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1910         ASSERT_GL_NO_ERROR();
1911 
1912         // Draw the Y plane using a shader.
1913         glUseProgram(program);
1914         glUniform4f(colorLocation, kYFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0, 0);
1915         ASSERT_GL_NO_ERROR();
1916 
1917         drawQuad(program, "position", 1.0f);
1918         ASSERT_GL_NO_ERROR();
1919 
1920         // Create and bind UV plane texture to image.
1921         EGLImage uvImage;
1922         GLuint uvTexture;
1923 
1924         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
1925         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat, GL_TEXTURE_2D,
1926                                     &uvImage, &uvTexture);
1927 
1928         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
1929         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1930                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1931         ASSERT_GL_NO_ERROR();
1932 
1933         // Draw the UV plane using a shader.
1934         glUseProgram(program);
1935         glUniform4f(colorLocation, kUFillValue * 1.0f / (isNV12 ? 0xff : 0xffff),
1936                     kVFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0);
1937         ASSERT_GL_NO_ERROR();
1938 
1939         drawQuad(program, "position", 1.0f);
1940         ASSERT_GL_NO_ERROR();
1941 
1942         Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
1943         CD3D11_TEXTURE2D_DESC stagingDesc = desc;
1944         stagingDesc.BindFlags             = 0;
1945         stagingDesc.Usage                 = D3D11_USAGE_STAGING;
1946         stagingDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;
1947 
1948         EXPECT_TRUE(
1949             SUCCEEDED(mD3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture)));
1950 
1951         Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
1952         mD3D11Device->GetImmediateContext(&context);
1953 
1954         context->CopyResource(stagingTexture.Get(), d3d11Texture.Get());
1955         ASSERT_GL_NO_ERROR();
1956 
1957         D3D11_MAPPED_SUBRESOURCE mapped = {};
1958         EXPECT_TRUE(SUCCEEDED(context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped)));
1959 
1960         uint8_t *yPlane  = reinterpret_cast<uint8_t *>(mapped.pData);
1961         uint8_t *uvPlane = yPlane + bufferSize * mapped.RowPitch;
1962         if (isNV12)
1963         {
1964             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue);
1965             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue);
1966             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], kVFillValue);
1967         }
1968         else
1969         {
1970             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue & 0xff);
1971             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2 + 1], (kYFillValue >> 8) & 0xff);
1972             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue & 0xff);
1973             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], (kUFillValue >> 8) & 0xff);
1974             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 2], kVFillValue & 0xff);
1975             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 3], (kVFillValue >> 8) & 0xff);
1976         }
1977 
1978         context->Unmap(stagingTexture.Get(), 0);
1979 
1980         glDeleteProgram(program);
1981         glDeleteTextures(1, &yTexture);
1982         glDeleteTextures(1, &uvTexture);
1983         glDeleteFramebuffers(1, &fbo);
1984         eglDestroyImageKHR(display, yImage);
1985         eglDestroyImageKHR(display, uvImage);
1986     }
1987 
RunYUVReadPixelTest(DXGI_FORMAT format)1988     void RunYUVReadPixelTest(DXGI_FORMAT format)
1989     {
1990         ASSERT(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1991                format == DXGI_FORMAT_P016);
1992         UINT formatSupport;
1993         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1994                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1995         ASSERT_TRUE(formatSupport &
1996                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET));
1997 
1998         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1999         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
2000         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
2001         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
2002 
2003         constexpr char kVS[] =
2004             R"(precision highp float;
2005             attribute vec4 position;
2006             varying vec2 texcoord;
2007 
2008             void main()
2009             {
2010                 gl_Position = position;
2011                 texcoord = (position.xy * 0.5) + 0.5;
2012                 texcoord.y = 1.0 - texcoord.y;
2013             })";
2014 
2015         constexpr char kFS[] =
2016             R"(precision highp float;
2017             uniform vec4 color;
2018             varying vec2 texcoord;
2019 
2020             void main()
2021             {
2022                 gl_FragColor = color;
2023             })";
2024 
2025         GLuint program = CompileProgram(kVS, kFS);
2026         ASSERT_NE(0u, program) << "shader compilation failed.";
2027 
2028         GLint colorLocation = glGetUniformLocation(program, "color");
2029         ASSERT_NE(-1, colorLocation);
2030 
2031         EGLWindow *window  = getEGLWindow();
2032         EGLDisplay display = window->getDisplay();
2033 
2034         window->makeCurrent();
2035 
2036         const UINT bufferSize = 32;
2037         EXPECT_TRUE(mD3D11Device != nullptr);
2038         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
2039         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
2040                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
2041 
2042         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
2043 
2044         // Create and bind Y plane texture to image.
2045         EGLImage yImage;
2046         GLuint yTexture;
2047 
2048         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
2049         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat, GL_TEXTURE_2D,
2050                                     &yImage, &yTexture);
2051 
2052         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, yImage);
2053         ASSERT_GL_NO_ERROR();
2054 
2055         GLuint fbo;
2056         glGenFramebuffers(1, &fbo);
2057         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2058         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
2059         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2060                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2061         ASSERT_GL_NO_ERROR();
2062 
2063         // Draw the Y plane using a shader.
2064         glUseProgram(program);
2065         glUniform4f(colorLocation, kYFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0, 0);
2066         ASSERT_GL_NO_ERROR();
2067 
2068         drawQuad(program, "position", 1.0f);
2069         ASSERT_GL_NO_ERROR();
2070 
2071         // Read the Y plane pixels.
2072         if (isNV12)
2073         {
2074             GLubyte yPixels[4] = {};
2075             glReadPixels(0, bufferSize / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, yPixels);
2076             EXPECT_EQ(yPixels[0], kYFillValue);
2077         }
2078         else
2079         {
2080             GLushort yPixels[4] = {};
2081             glReadPixels(0, bufferSize / 2, 1, 1, GL_RGBA, GL_UNSIGNED_SHORT, yPixels);
2082             EXPECT_EQ(yPixels[0], kYFillValue);
2083         }
2084 
2085         // Create and bind UV plane texture to image.
2086         EGLImage uvImage;
2087         GLuint uvTexture;
2088 
2089         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
2090         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat, GL_TEXTURE_2D,
2091                                     &uvImage, &uvTexture);
2092 
2093         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
2094         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2095                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2096         ASSERT_GL_NO_ERROR();
2097 
2098         // Draw the UV plane using a shader.
2099         glUseProgram(program);
2100         glUniform4f(colorLocation, kUFillValue * 1.0f / (isNV12 ? 0xff : 0xffff),
2101                     kVFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0);
2102         ASSERT_GL_NO_ERROR();
2103 
2104         drawQuad(program, "position", 1.0f);
2105         ASSERT_GL_NO_ERROR();
2106 
2107         // Read the UV plane pixels.
2108         if (isNV12)
2109         {
2110             GLubyte uvPixels[4] = {};
2111             glReadPixels(0, bufferSize / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, uvPixels);
2112             EXPECT_EQ(uvPixels[0], kUFillValue);
2113             EXPECT_EQ(uvPixels[1], kVFillValue);
2114         }
2115         else
2116         {
2117             GLushort uvPixels[4] = {};
2118             glReadPixels(0, bufferSize / 4, 1, 1, GL_RGBA, GL_UNSIGNED_SHORT, uvPixels);
2119             EXPECT_EQ(uvPixels[0], kUFillValue);
2120             EXPECT_EQ(uvPixels[1], kVFillValue);
2121         }
2122 
2123         Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
2124         CD3D11_TEXTURE2D_DESC stagingDesc = desc;
2125         stagingDesc.BindFlags             = 0;
2126         stagingDesc.Usage                 = D3D11_USAGE_STAGING;
2127         stagingDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;
2128 
2129         EXPECT_TRUE(
2130             SUCCEEDED(mD3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture)));
2131 
2132         Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
2133         mD3D11Device->GetImmediateContext(&context);
2134 
2135         context->CopyResource(stagingTexture.Get(), d3d11Texture.Get());
2136         ASSERT_GL_NO_ERROR();
2137 
2138         D3D11_MAPPED_SUBRESOURCE mapped = {};
2139         EXPECT_TRUE(SUCCEEDED(context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped)));
2140 
2141         uint8_t *yPlane  = reinterpret_cast<uint8_t *>(mapped.pData);
2142         uint8_t *uvPlane = yPlane + bufferSize * mapped.RowPitch;
2143         if (isNV12)
2144         {
2145             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue);
2146             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue);
2147             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], kVFillValue);
2148         }
2149         else
2150         {
2151             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue & 0xff);
2152             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2 + 1], (kYFillValue >> 8) & 0xff);
2153             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue & 0xff);
2154             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], (kUFillValue >> 8) & 0xff);
2155             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 2], kVFillValue & 0xff);
2156             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 3], (kVFillValue >> 8) & 0xff);
2157         }
2158 
2159         context->Unmap(stagingTexture.Get(), 0);
2160 
2161         glDeleteProgram(program);
2162         glDeleteTextures(1, &yTexture);
2163         glDeleteTextures(1, &uvTexture);
2164         glDeleteFramebuffers(1, &fbo);
2165         eglDestroyImageKHR(display, yImage);
2166         eglDestroyImageKHR(display, uvImage);
2167     }
2168 
2169     template <typename T>
RunYUVWritePixelTest(DXGI_FORMAT format)2170     void RunYUVWritePixelTest(DXGI_FORMAT format)
2171     {
2172         ASSERT(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
2173                format == DXGI_FORMAT_P016);
2174         UINT formatSupport;
2175         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
2176                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
2177         ASSERT_TRUE(formatSupport &
2178                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET));
2179 
2180         const bool isNV12                = (format == DXGI_FORMAT_NV12);
2181         const unsigned kYFillValueFull   = isNV12 ? 0x12 : 0x1234;
2182         const unsigned kUFillValueFull   = isNV12 ? 0x23 : 0x2345;
2183         const unsigned kVFillValueFull   = isNV12 ? 0x34 : 0x3456;
2184         const unsigned kYFillValueOffset = isNV12 ? 0x56 : 0x5678;
2185         const unsigned kUFillValueOffset = isNV12 ? 0x67 : 0x6789;
2186         const unsigned kVFillValueOffset = isNV12 ? 0x78 : 0x7890;
2187 
2188         EGLWindow *window  = getEGLWindow();
2189         EGLDisplay display = window->getDisplay();
2190         window->makeCurrent();
2191 
2192         const UINT bufferSize = 32;
2193         EXPECT_TRUE(mD3D11Device != nullptr);
2194         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
2195         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
2196                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
2197 
2198         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
2199 
2200         // Create and bind Y plane texture to image.
2201         EGLImage yImage;
2202         GLuint yTexture;
2203         GLenum internalFormat = isNV12 ? GL_RED_EXT : GL_R16_EXT;
2204         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat, GL_TEXTURE_2D,
2205                                     &yImage, &yTexture);
2206         ASSERT_GL_NO_ERROR();
2207 
2208         // Write the Y plane data to full texture (0, 0) to (32, 32).
2209         GLenum type = isNV12 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
2210         std::vector<T> yData(bufferSize * bufferSize, kYFillValueFull);
2211         glTexSubImage2D(GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/0, /*yoffset=*/0,
2212                         /*width=*/bufferSize,
2213                         /*height=*/bufferSize, GL_RED_EXT, type, yData.data());
2214         ASSERT_GL_NO_ERROR();
2215 
2216         GLuint fbo;
2217         glGenFramebuffers(1, &fbo);
2218         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2219         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
2220         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2221                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2222         ASSERT_GL_NO_ERROR();
2223 
2224         // Read the Y plane pixels for a region starting at 0, 0 offsets.
2225         // yPixels of size (4*4) region (*4) bytes per RGBA pixel
2226         T yPixels[4 * 4 * 4] = {};
2227         glReadPixels(/*x=*/0, /*y=*/0, /*width*/ 4, /*height=*/4, GL_RGBA, type, yPixels);
2228         EXPECT_EQ(yPixels[0], kYFillValueFull);
2229         EXPECT_EQ(yPixels[4], kYFillValueFull);
2230         EXPECT_EQ(yPixels[16], kYFillValueFull);
2231 
2232         // Write the Y plane data with offseted values for subregion (16, 16) - (32, 32).
2233         std::vector<T> yDataOffset(bufferSize * bufferSize, kYFillValueOffset);
2234         glTexSubImage2D(GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/bufferSize / 2,
2235                         /*yoffset=*/bufferSize / 2, /*width=*/bufferSize / 2,
2236                         /*height=*/bufferSize / 2, GL_RED_EXT, type, yDataOffset.data());
2237         ASSERT_GL_NO_ERROR();
2238 
2239         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
2240         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2241                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2242         ASSERT_GL_NO_ERROR();
2243 
2244         // Read the Y plane pixels for a region starting at some offsets.
2245         // yPixels of size (16*16) region (*4) bytes per RGBA pixel
2246         T yPixelsOffset[16 * 16 * 4] = {};
2247         glReadPixels(/*x=*/bufferSize / 2, /*y=*/bufferSize / 2, /*width=*/bufferSize / 2,
2248                      /*height=*/bufferSize / 2, GL_RGBA, type, yPixelsOffset);
2249         EXPECT_EQ(yPixelsOffset[0], kYFillValueOffset);
2250         EXPECT_EQ(yPixelsOffset[12], kYFillValueOffset);
2251 
2252         // Create and bind UV plane texture to image.
2253         EGLImage uvImage;
2254         GLuint uvTexture;
2255         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
2256         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat, GL_TEXTURE_2D,
2257                                     &uvImage, &uvTexture);
2258         ASSERT_GL_NO_ERROR();
2259 
2260         // Write the UV plane data to texture's full uv plane (0, 0,) - (16, 16).
2261         std::vector<T> uvData((bufferSize * bufferSize) / 2);
2262         for (UINT i = 0; i < (bufferSize * bufferSize) / 2; i++)
2263         {
2264             uvData[i] = i % 2 == 0 ? kUFillValueFull : kVFillValueFull;
2265         }
2266         glTexSubImage2D(GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/0, /*yoffset=*/0,
2267                         /*width=*/bufferSize / 2,
2268                         /*height=*/bufferSize / 2, GL_RG_EXT, type, uvData.data());
2269         ASSERT_GL_NO_ERROR();
2270 
2271         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
2272         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2273                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2274         ASSERT_GL_NO_ERROR();
2275 
2276         // Read the UV plane pixels for a region starting at 0, 0 offsets.
2277         // uvPixels of size (4*4) region (*4) bytes per RGBA pixel
2278         T uvPixels[4 * 4 * 4] = {};
2279         glReadPixels(/*x=*/0, /*y=*/0, /*width=*/4, /*height=*/4, GL_RGBA, type, uvPixels);
2280         EXPECT_EQ(uvPixels[0], kUFillValueFull);
2281         EXPECT_EQ(uvPixels[1], kVFillValueFull);
2282         EXPECT_EQ(uvPixels[4], kUFillValueFull);
2283         EXPECT_EQ(uvPixels[5], kVFillValueFull);
2284         EXPECT_EQ(uvPixels[16], kUFillValueFull);
2285         EXPECT_EQ(uvPixels[17], kVFillValueFull);
2286 
2287         // Write the UV plane data with offset values for subregion (8, 8) - (16, 16).
2288         std::vector<T> uvDataOffset((bufferSize * bufferSize) / 2);
2289         for (UINT i = 0; i < (bufferSize * bufferSize) / 2; i++)
2290         {
2291             uvDataOffset[i] = i % 2 == 0 ? kUFillValueOffset : kVFillValueOffset;
2292         }
2293         glTexSubImage2D(GL_TEXTURE_2D, /*level=*/0, /*xoffset=*/bufferSize / 4,
2294                         /*yoffset=*/bufferSize / 4, /*width=*/bufferSize / 4,
2295                         /*height=*/bufferSize / 4, GL_RG_EXT, type, uvDataOffset.data());
2296         ASSERT_GL_NO_ERROR();
2297 
2298         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
2299         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2300                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2301         ASSERT_GL_NO_ERROR();
2302 
2303         // Read the UV plane pixels for a region starting at some offsets.
2304         // uvPixels of size (8*8) region (*4) bytes per RGBA pixel
2305         T uvPixelsOffset[8 * 8 * 4] = {};
2306         glReadPixels(/*x=*/bufferSize / 4, /*y=*/bufferSize / 4, /*width=*/bufferSize / 4,
2307                      /*height=*/bufferSize / 4, GL_RGBA, type, uvPixelsOffset);
2308         EXPECT_EQ(uvPixelsOffset[0], kUFillValueOffset);
2309         EXPECT_EQ(uvPixelsOffset[1], kVFillValueOffset);
2310         EXPECT_EQ(uvPixelsOffset[12], kUFillValueOffset);
2311         EXPECT_EQ(uvPixelsOffset[13], kVFillValueOffset);
2312 
2313         Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
2314         CD3D11_TEXTURE2D_DESC stagingDesc = desc;
2315         stagingDesc.BindFlags             = 0;
2316         stagingDesc.Usage                 = D3D11_USAGE_STAGING;
2317         stagingDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;
2318 
2319         EXPECT_TRUE(
2320             SUCCEEDED(mD3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture)));
2321 
2322         Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
2323         mD3D11Device->GetImmediateContext(&context);
2324 
2325         context->CopyResource(stagingTexture.Get(), d3d11Texture.Get());
2326         ASSERT_GL_NO_ERROR();
2327 
2328         D3D11_MAPPED_SUBRESOURCE mapped = {};
2329         EXPECT_TRUE(SUCCEEDED(context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped)));
2330 
2331         uint8_t *yPlane  = reinterpret_cast<uint8_t *>(mapped.pData);
2332         uint8_t *uvPlane = yPlane + bufferSize * mapped.RowPitch;
2333         auto getYValue   = [&](int x, int y) {
2334             const T *lineStart = reinterpret_cast<const T *>(yPlane + y * mapped.RowPitch);
2335             return lineStart[x];
2336         };
2337 
2338         auto getUValue = [&](int x, int y) {
2339             const T *lineStart = reinterpret_cast<const T *>(uvPlane + y * mapped.RowPitch);
2340             return lineStart[x * 2 + 0];
2341         };
2342 
2343         auto getVValue = [&](int x, int y) {
2344             const T *lineStart = reinterpret_cast<const T *>(uvPlane + y * mapped.RowPitch);
2345             return lineStart[x * 2 + 1];
2346         };
2347         // Compare first y pixel with full write values.
2348         EXPECT_EQ(getYValue(0, 0), kYFillValueFull);
2349         // Compare last y pixel with overwritten subregion values.
2350         EXPECT_EQ(getYValue(bufferSize - 1, bufferSize - 1), kYFillValueOffset);
2351         // Compare first uv pixel with full write values.
2352         EXPECT_EQ(getUValue(0, 0), kUFillValueFull);
2353         EXPECT_EQ(getVValue(0, 0), kVFillValueFull);
2354         // Compare last uv pixel with overwritten subregion values.
2355         EXPECT_EQ(getUValue(bufferSize / 2 - 1, bufferSize / 2 - 1), kUFillValueOffset);
2356         EXPECT_EQ(getVValue(bufferSize / 2 - 1, bufferSize / 2 - 1), kVFillValueOffset);
2357 
2358         context->Unmap(stagingTexture.Get(), 0);
2359 
2360         glDeleteTextures(1, &yTexture);
2361         glDeleteTextures(1, &uvTexture);
2362         glDeleteFramebuffers(1, &fbo);
2363         eglDestroyImageKHR(display, yImage);
2364         eglDestroyImageKHR(display, uvImage);
2365     }
2366 };
2367 
2368 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and the resulting GL
2369 // textures can be sampled from.
TEST_P(D3DTextureYUVTest,NV12TextureImageSampler)2370 TEST_P(D3DTextureYUVTest, NV12TextureImageSampler)
2371 {
2372     RunYUVSamplerTest(DXGI_FORMAT_NV12);
2373 }
2374 
2375 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2376 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageSampler)2377 TEST_P(D3DTextureYUVTest, P010TextureImageSampler)
2378 {
2379     RunYUVSamplerTest(DXGI_FORMAT_P010);
2380 }
2381 
2382 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2383 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageSampler)2384 TEST_P(D3DTextureYUVTest, P016TextureImageSampler)
2385 {
2386     RunYUVSamplerTest(DXGI_FORMAT_P016);
2387 }
2388 
2389 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and rendered to as
2390 // framebuffer attachments.
TEST_P(D3DTextureYUVTest,NV12TextureImageRender)2391 TEST_P(D3DTextureYUVTest, NV12TextureImageRender)
2392 {
2393     RunYUVRenderTest(DXGI_FORMAT_NV12);
2394 }
2395 
2396 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2397 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageRender)2398 TEST_P(D3DTextureYUVTest, P010TextureImageRender)
2399 {
2400     RunYUVRenderTest(DXGI_FORMAT_P010);
2401 }
2402 
2403 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2404 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageRender)2405 TEST_P(D3DTextureYUVTest, P016TextureImageRender)
2406 {
2407     RunYUVRenderTest(DXGI_FORMAT_P016);
2408 }
2409 
2410 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and rendered to as
2411 // framebuffer attachments and then read from as individual planes.
TEST_P(D3DTextureYUVTest,NV12TextureImageReadPixel)2412 TEST_P(D3DTextureYUVTest, NV12TextureImageReadPixel)
2413 {
2414     RunYUVReadPixelTest(DXGI_FORMAT_NV12);
2415 }
2416 
2417 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2418 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageReadPixel)2419 TEST_P(D3DTextureYUVTest, P010TextureImageReadPixel)
2420 {
2421     RunYUVReadPixelTest(DXGI_FORMAT_P010);
2422 }
2423 
2424 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2425 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageReadPixel)2426 TEST_P(D3DTextureYUVTest, P016TextureImageReadPixel)
2427 {
2428     RunYUVReadPixelTest(DXGI_FORMAT_P016);
2429 }
2430 
2431 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and write data to
2432 // them through glTexSubImage2D and then rendered to as framebuffer attachments and then read from
2433 // as individual planes.
TEST_P(D3DTextureYUVTest,NV12TextureImageWritePixel)2434 TEST_P(D3DTextureYUVTest, NV12TextureImageWritePixel)
2435 {
2436     RunYUVWritePixelTest<uint8_t>(DXGI_FORMAT_NV12);
2437 }
2438 
2439 // Test that an P010 D3D11 texture can be imported as two R16 and RG16 EGLImages and write data to
2440 // them through glTexSubImage2D and then rendered to as framebuffer attachments and then read from
2441 // as individual planes.
TEST_P(D3DTextureYUVTest,P010TextureImageWritePixel)2442 TEST_P(D3DTextureYUVTest, P010TextureImageWritePixel)
2443 {
2444     RunYUVWritePixelTest<uint16_t>(DXGI_FORMAT_P010);
2445 }
2446 
2447 // Test that an P016 D3D11 texture can be imported as two R16 and RG16 EGLImages and write data to
2448 // them through glTexSubImage2D and then rendered to as framebuffer attachments and then read from
2449 // as individual planes.
TEST_P(D3DTextureYUVTest,P016TextureImageWritePixel)2450 TEST_P(D3DTextureYUVTest, P016TextureImageWritePixel)
2451 {
2452     RunYUVWritePixelTest<uint16_t>(DXGI_FORMAT_P016);
2453 }
2454 
2455 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
2456 // tests should be run against.
2457 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureTest);
2458 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureClearTest);
2459 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureYUVTest);
2460 ANGLE_INSTANTIATE_TEST_ES3(D3DTextureTestES3);
2461 // D3D Debug device reports an error. http://anglebug.com/40096593
2462 // ANGLE_INSTANTIATE_TEST(D3DTextureTestMS, ES2_D3D11());
2463 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(D3DTextureTestMS);
2464 }  // namespace angle
2465