• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
1287         {
1288             GLuint readColor[4] = {0, 0, 0, 255};
1289             switch (internalFormat)
1290             {
1291                 case GL_RGBA:
1292                 case GL_BGRA_EXT:
1293                 case GL_RGB10_A2_EXT:
1294                     readColor[0] = readColor[1] = readColor[2] = 255;
1295                     break;
1296                 case GL_RG_EXT:
1297                 case GL_RG16_EXT:
1298                     readColor[0] = readColor[1] = 255;
1299                     break;
1300                 case GL_RED_EXT:
1301                 case GL_R16_EXT:
1302                     readColor[0] = 255;
1303                     break;
1304             }
1305             // Read back as GL_UNSIGNED_BYTE even though the texture might have more than 8bpc.
1306             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1307                             readColor[0], readColor[1], readColor[2], readColor[3]);
1308         }
1309 
1310         glDeleteFramebuffers(1, &fbo);
1311         glDeleteTextures(1, &texture);
1312         eglDestroyImageKHR(display, image);
1313 
1314         d3d11Texture->Release();
1315     }
1316 };
1317 
TEST_P(D3DTextureClearTest,ClearRGBA8)1318 TEST_P(D3DTextureClearTest, ClearRGBA8)
1319 {
1320     RunClearTest(DXGI_FORMAT_R8G8B8A8_UNORM);
1321 }
1322 
TEST_P(D3DTextureClearTest,ClearBGRA8)1323 TEST_P(D3DTextureClearTest, ClearBGRA8)
1324 {
1325     RunClearTest(DXGI_FORMAT_B8G8R8A8_UNORM);
1326 }
1327 
TEST_P(D3DTextureClearTest,ClearR8)1328 TEST_P(D3DTextureClearTest, ClearR8)
1329 {
1330     RunClearTest(DXGI_FORMAT_R8_UNORM);
1331 }
1332 
TEST_P(D3DTextureClearTest,ClearRG8)1333 TEST_P(D3DTextureClearTest, ClearRG8)
1334 {
1335     RunClearTest(DXGI_FORMAT_R8G8_UNORM);
1336 }
1337 
TEST_P(D3DTextureClearTest,ClearRGB10A2)1338 TEST_P(D3DTextureClearTest, ClearRGB10A2)
1339 {
1340     RunClearTest(DXGI_FORMAT_R10G10B10A2_UNORM);
1341 }
1342 
TEST_P(D3DTextureClearTest,ClearRGBAF16)1343 TEST_P(D3DTextureClearTest, ClearRGBAF16)
1344 {
1345     RunClearTest(DXGI_FORMAT_R16G16B16A16_FLOAT);
1346 }
1347 
TEST_P(D3DTextureClearTest,ClearR16)1348 TEST_P(D3DTextureClearTest, ClearR16)
1349 {
1350     RunClearTest(DXGI_FORMAT_R16_UNORM);
1351 }
1352 
TEST_P(D3DTextureClearTest,ClearRG16)1353 TEST_P(D3DTextureClearTest, ClearRG16)
1354 {
1355     RunClearTest(DXGI_FORMAT_R16G16_UNORM);
1356 }
1357 
TEST_P(D3DTextureTest,NonRenderableTextureImage)1358 TEST_P(D3DTextureTest, NonRenderableTextureImage)
1359 {
1360     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1361 
1362     EGLWindow *window  = getEGLWindow();
1363     EGLDisplay display = window->getDisplay();
1364 
1365     window->makeCurrent();
1366 
1367     const UINT bufferSize = 32;
1368     EXPECT_TRUE(mD3D11Device != nullptr);
1369     ID3D11Texture2D *d3d11Texture = nullptr;
1370     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1371                                D3D11_BIND_SHADER_RESOURCE);
1372     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1373 
1374     const EGLint attribs[] = {EGL_NONE};
1375 
1376     EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1377                                        static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1378     ASSERT_EGL_SUCCESS();
1379     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1380 
1381     GLuint texture;
1382     glGenTextures(1, &texture);
1383     glBindTexture(GL_TEXTURE_2D, texture);
1384     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1385     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1386     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1387     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1388     ASSERT_GL_NO_ERROR();
1389 
1390     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1391     ASSERT_GL_NO_ERROR();
1392 
1393     GLuint fbo;
1394     glGenFramebuffers(1, &fbo);
1395     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1396     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1397     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1398               static_cast<unsigned>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
1399     ASSERT_GL_NO_ERROR();
1400 
1401     glDeleteFramebuffers(1, &fbo);
1402     glDeleteTextures(1, &texture);
1403     eglDestroyImageKHR(display, image);
1404 
1405     d3d11Texture->Release();
1406 }
1407 
TEST_P(D3DTextureTest,RGBEmulationTextureImage)1408 TEST_P(D3DTextureTest, RGBEmulationTextureImage)
1409 {
1410     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1411 
1412     EGLWindow *window  = getEGLWindow();
1413     EGLDisplay display = window->getDisplay();
1414 
1415     window->makeCurrent();
1416 
1417     const UINT bufferSize = 32;
1418     EXPECT_TRUE(mD3D11Device != nullptr);
1419     ID3D11Texture2D *d3d11Texture = nullptr;
1420     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
1421                                D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1422     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1423 
1424     const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGB, EGL_NONE};
1425 
1426     EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1427                                        static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1428     ASSERT_EGL_SUCCESS();
1429     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1430 
1431     GLuint texture;
1432     glGenTextures(1, &texture);
1433     glBindTexture(GL_TEXTURE_2D, texture);
1434     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1435     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1436     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1437     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1438     ASSERT_GL_NO_ERROR();
1439 
1440     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1441     ASSERT_GL_NO_ERROR();
1442 
1443     GLuint fbo;
1444     glGenFramebuffers(1, &fbo);
1445     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1446     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1447     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1448               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1449     ASSERT_GL_NO_ERROR();
1450 
1451     // Although we are writing 0.5 to the alpha channel it should have the same
1452     // side effects as if alpha were 1.0.
1453     glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
1454     glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1455     glClear(GL_COLOR_BUFFER_BIT);
1456     ASSERT_GL_NO_ERROR();
1457     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1458                     255, 255);
1459 
1460     GLuint rgbaRbo;
1461     glGenRenderbuffers(1, &rgbaRbo);
1462     glBindRenderbuffer(GL_RENDERBUFFER, rgbaRbo);
1463     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, bufferSize, bufferSize);
1464 
1465     GLuint rgbaFbo;
1466     glGenFramebuffers(1, &rgbaFbo);
1467     glBindFramebuffer(GL_FRAMEBUFFER, rgbaFbo);
1468     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbaRbo);
1469     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1470               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1471     ASSERT_GL_NO_ERROR();
1472 
1473     // BlitFramebuffer from/to RGBA framebuffer fails.
1474     glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbaFbo);
1475     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1476     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1477                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1478     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1479     ASSERT_GL_NO_ERROR();
1480 
1481     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1482     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbaFbo);
1483     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1484                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1485     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1486     ASSERT_GL_NO_ERROR();
1487 
1488     GLuint rgbRbo;
1489     glGenRenderbuffers(1, &rgbRbo);
1490     glBindRenderbuffer(GL_RENDERBUFFER, rgbRbo);
1491     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, bufferSize, bufferSize);
1492 
1493     GLuint rgbFbo;
1494     glGenFramebuffers(1, &rgbFbo);
1495     glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1496     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbRbo);
1497     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1498               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1499     ASSERT_GL_NO_ERROR();
1500     glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
1501     glClear(GL_COLOR_BUFFER_BIT);
1502     ASSERT_GL_NO_ERROR();
1503 
1504     // Clear texture framebuffer.
1505     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1506     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1507     glClear(GL_COLOR_BUFFER_BIT);
1508     ASSERT_GL_NO_ERROR();
1509     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1510                     255);
1511 
1512     // BlitFramebuffer from/to RGB framebuffer succeeds.
1513     glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbFbo);
1514     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1515     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1516                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1517     ASSERT_GL_NO_ERROR();
1518     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
1519                     255, 255);
1520 
1521     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1522     glClear(GL_COLOR_BUFFER_BIT);
1523     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1524     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbFbo);
1525     glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
1526                            GL_COLOR_BUFFER_BIT, GL_NEAREST);
1527     ASSERT_GL_NO_ERROR();
1528     glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
1529     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
1530                     255);
1531 
1532     glDeleteFramebuffers(1, &rgbFbo);
1533     glDeleteRenderbuffers(1, &rgbRbo);
1534     glDeleteFramebuffers(1, &rgbaFbo);
1535     glDeleteRenderbuffers(1, &rgbaRbo);
1536     glDeleteFramebuffers(1, &fbo);
1537     glDeleteTextures(1, &texture);
1538     eglDestroyImageKHR(display, image);
1539 
1540     d3d11Texture->Release();
1541 }
1542 
TEST_P(D3DTextureTest,TextureArray)1543 TEST_P(D3DTextureTest, TextureArray)
1544 {
1545     ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
1546 
1547     EGLWindow *window  = getEGLWindow();
1548     EGLDisplay display = window->getDisplay();
1549 
1550     window->makeCurrent();
1551 
1552     const UINT bufferSize = 32;
1553     const UINT arraySize  = 4;
1554 
1555     ID3D11Texture2D *d3d11Texture = nullptr;
1556     CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, arraySize, 1,
1557                                D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1558     EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1559 
1560     const unsigned char kRFill = 0x12;
1561     const unsigned char kGFill = 0x23;
1562     const unsigned char kBFill = 0x34;
1563     const unsigned char kAFill = 0x45;
1564 
1565     std::vector<unsigned char> imageData(bufferSize * bufferSize * 4, 0);
1566     for (size_t i = 0; i < imageData.size(); i += 4)
1567     {
1568         imageData[i]     = kRFill;
1569         imageData[i + 1] = kGFill;
1570         imageData[i + 2] = kBFill;
1571         imageData[i + 3] = kAFill;
1572     }
1573 
1574     ID3D11DeviceContext *context = nullptr;
1575     mD3D11Device->GetImmediateContext(&context);
1576     ASSERT_NE(context, nullptr);
1577 
1578     D3D11_BOX dstBox = {0, 0, 0, bufferSize, bufferSize, 1};
1579     context->UpdateSubresource(d3d11Texture, arraySize - 1, &dstBox, imageData.data(),
1580                                bufferSize * 4, imageData.size());
1581 
1582     const EGLint attribs[] = {EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, arraySize - 1, EGL_NONE};
1583     EGLImage image         = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1584                                                static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1585     ASSERT_EGL_SUCCESS();
1586     ASSERT_NE(image, EGL_NO_IMAGE_KHR);
1587 
1588     GLuint texture;
1589     glGenTextures(1, &texture);
1590     glBindTexture(GL_TEXTURE_2D, texture);
1591     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1592     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1593     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1594     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1595     ASSERT_GL_NO_ERROR();
1596 
1597     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
1598     ASSERT_GL_NO_ERROR();
1599 
1600     GLuint fbo;
1601     glGenFramebuffers(1, &fbo);
1602     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1603     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1604     EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1605               static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1606     ASSERT_GL_NO_ERROR();
1607 
1608     EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, kRFill,
1609                     kGFill, kBFill, kAFill);
1610 
1611     glDeleteFramebuffers(1, &fbo);
1612     glDeleteTextures(1, &texture);
1613     eglDestroyImageKHR(display, image);
1614 
1615     d3d11Texture->Release();
1616 }
1617 
1618 class D3DTextureYUVTest : public D3DTextureTest
1619 {
1620   protected:
CreateAndBindImageToTexture(EGLDisplay display,ID3D11Texture2D * d3d11Texture,EGLint plane,GLenum internalFormat,GLenum target,EGLImage * image,GLuint * texture)1621     void CreateAndBindImageToTexture(EGLDisplay display,
1622                                      ID3D11Texture2D *d3d11Texture,
1623                                      EGLint plane,
1624                                      GLenum internalFormat,
1625                                      GLenum target,
1626                                      EGLImage *image,
1627                                      GLuint *texture)
1628     {
1629         const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
1630                                   static_cast<EGLint>(internalFormat),
1631                                   EGL_D3D11_TEXTURE_PLANE_ANGLE, plane, EGL_NONE};
1632         *image                 = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
1633                                                    static_cast<EGLClientBuffer>(d3d11Texture), attribs);
1634         ASSERT_EGL_SUCCESS();
1635         ASSERT_NE(*image, EGL_NO_IMAGE_KHR);
1636 
1637         // Create and bind Y plane texture to image.
1638         glGenTextures(1, texture);
1639         glActiveTexture(GL_TEXTURE0);
1640         glBindTexture(target, *texture);
1641         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1642         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1643         glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1644         glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1645         ASSERT_GL_NO_ERROR();
1646 
1647         glEGLImageTargetTexture2DOES(target, *image);
1648         ASSERT_GL_NO_ERROR();
1649     }
1650 
RunYUVSamplerTest(DXGI_FORMAT format)1651     void RunYUVSamplerTest(DXGI_FORMAT format)
1652     {
1653         ASSERT_TRUE(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1654                     format == DXGI_FORMAT_P016);
1655         UINT formatSupport;
1656         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1657                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1658         ASSERT_TRUE(formatSupport &
1659                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE));
1660 
1661         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1662         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1663         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1664         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1665 
1666         constexpr char kVS[] =
1667             R"(precision highp float;
1668             attribute vec4 position;
1669             varying vec2 texcoord;
1670 
1671             void main()
1672             {
1673                 gl_Position = position;
1674                 texcoord = (position.xy * 0.5) + 0.5;
1675                 texcoord.y = 1.0 - texcoord.y;
1676             })";
1677 
1678         constexpr char kFS[] =
1679             R"(#extension GL_OES_EGL_image_external : require
1680             precision highp float;
1681             uniform samplerExternalOES tex;
1682             varying vec2 texcoord;
1683 
1684             void main()
1685             {
1686                 gl_FragColor = texture2D(tex, texcoord);
1687             })";
1688 
1689         GLuint program = CompileProgram(kVS, kFS);
1690         ASSERT_NE(0u, program) << "shader compilation failed.";
1691 
1692         GLint textureLocation = glGetUniformLocation(program, "tex");
1693         ASSERT_NE(-1, textureLocation);
1694 
1695         EGLWindow *window  = getEGLWindow();
1696         EGLDisplay display = window->getDisplay();
1697 
1698         window->makeCurrent();
1699 
1700         const UINT bufferSize = 32;
1701         EXPECT_TRUE(mD3D11Device != nullptr);
1702         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
1703         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1704                                    D3D11_BIND_SHADER_RESOURCE);
1705 
1706         std::vector<unsigned char> imageData;
1707 
1708         if (isNV12)
1709         {
1710             imageData.resize(bufferSize * bufferSize * 3 / 2);
1711             memset(imageData.data(), kYFillValue, bufferSize * bufferSize);
1712             const size_t kUVOffset = bufferSize * bufferSize;
1713             for (size_t i = 0; i < bufferSize * bufferSize / 2; i += 2)
1714             {
1715                 imageData[kUVOffset + i]     = kUFillValue;
1716                 imageData[kUVOffset + i + 1] = kVFillValue;
1717             }
1718         }
1719         else
1720         {
1721             imageData.resize(bufferSize * bufferSize * 3);
1722             const size_t kUVOffset = bufferSize * bufferSize * 2;
1723             for (size_t i = 0; i < kUVOffset; i += 2)
1724             {
1725                 imageData[i]     = kYFillValue & 0xff;
1726                 imageData[i + 1] = (kYFillValue >> 8) & 0xff;
1727                 if (kUVOffset + i < imageData.size())
1728                 {
1729                     // Interleave U & V samples.
1730                     const unsigned fill          = (i % 4 == 0) ? kUFillValue : kVFillValue;
1731                     imageData[kUVOffset + i]     = fill & 0xff;
1732                     imageData[kUVOffset + i + 1] = (fill >> 8) & 0xff;
1733                 }
1734             }
1735         }
1736 
1737         D3D11_SUBRESOURCE_DATA data = {};
1738         data.pSysMem                = static_cast<const void *>(imageData.data());
1739         data.SysMemPitch            = isNV12 ? bufferSize : bufferSize * 2;
1740 
1741         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, &data, &d3d11Texture)));
1742 
1743         // Create and bind Y plane texture to image.
1744         EGLImage yImage;
1745         GLuint yTexture;
1746 
1747         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
1748         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat,
1749                                     GL_TEXTURE_EXTERNAL_OES, &yImage, &yTexture);
1750 
1751         GLuint rbo;
1752         glGenRenderbuffers(1, &rbo);
1753         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1754         glRenderbufferStorage(GL_RENDERBUFFER, isNV12 ? GL_RGBA8_OES : GL_RGBA16_EXT, bufferSize,
1755                               bufferSize);
1756         ASSERT_GL_NO_ERROR();
1757 
1758         GLuint fbo;
1759         glGenFramebuffers(1, &fbo);
1760         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1761         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1762         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1763                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1764         ASSERT_GL_NO_ERROR();
1765 
1766         // Draw the Y plane using a shader.
1767         glUseProgram(program);
1768         glUniform1i(textureLocation, 0);
1769         ASSERT_GL_NO_ERROR();
1770 
1771         glViewport(0, 0, bufferSize, bufferSize);
1772         drawQuad(program, "position", 1.0f);
1773         ASSERT_GL_NO_ERROR();
1774 
1775         if (isNV12)
1776         {
1777 
1778             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2,
1779                             kYFillValue, 0, 0, 0xff);
1780         }
1781         else
1782         {
1783             EXPECT_PIXEL_16UI(static_cast<GLint>(bufferSize) / 2,
1784                               static_cast<GLint>(bufferSize) / 2, kYFillValue, 0, 0, 0xffff);
1785         }
1786         ASSERT_GL_NO_ERROR();
1787 
1788         // Create and bind UV plane texture to image.
1789         EGLImage uvImage;
1790         GLuint uvTexture;
1791 
1792         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
1793         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat,
1794                                     GL_TEXTURE_EXTERNAL_OES, &uvImage, &uvTexture);
1795 
1796         // Draw the UV plane using a shader.
1797         glUseProgram(program);
1798         glUniform1i(textureLocation, 0);
1799         ASSERT_GL_NO_ERROR();
1800 
1801         // Use only half of the framebuffer to match UV plane dimensions.
1802         glViewport(0, 0, bufferSize / 2, bufferSize / 2);
1803         drawQuad(program, "position", 1.0f);
1804         ASSERT_GL_NO_ERROR();
1805 
1806         if (isNV12)
1807         {
1808 
1809             EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 4, static_cast<GLint>(bufferSize) / 4,
1810                             kUFillValue, kVFillValue, 0, 0xff);
1811         }
1812         else
1813         {
1814             EXPECT_PIXEL_16UI(static_cast<GLint>(bufferSize) / 4,
1815                               static_cast<GLint>(bufferSize) / 4, kUFillValue, kVFillValue, 0,
1816                               0xffff);
1817         }
1818         ASSERT_GL_NO_ERROR();
1819 
1820         glDeleteProgram(program);
1821         glDeleteTextures(1, &yTexture);
1822         glDeleteTextures(1, &uvTexture);
1823         glDeleteFramebuffers(1, &fbo);
1824         glDeleteRenderbuffers(1, &rbo);
1825         eglDestroyImageKHR(display, yImage);
1826         eglDestroyImageKHR(display, uvImage);
1827     }
1828 
RunYUVRenderTest(DXGI_FORMAT format)1829     void RunYUVRenderTest(DXGI_FORMAT format)
1830     {
1831         ASSERT(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1832                format == DXGI_FORMAT_P016);
1833         UINT formatSupport;
1834         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1835                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1836         ASSERT_TRUE(formatSupport &
1837                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET));
1838 
1839         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1840         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1841         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1842         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1843 
1844         constexpr char kVS[] =
1845             R"(precision highp float;
1846             attribute vec4 position;
1847             varying vec2 texcoord;
1848 
1849             void main()
1850             {
1851                 gl_Position = position;
1852                 texcoord = (position.xy * 0.5) + 0.5;
1853                 texcoord.y = 1.0 - texcoord.y;
1854             })";
1855 
1856         constexpr char kFS[] =
1857             R"(precision highp float;
1858             uniform vec4 color;
1859             varying vec2 texcoord;
1860 
1861             void main()
1862             {
1863                 gl_FragColor = color;
1864             })";
1865 
1866         GLuint program = CompileProgram(kVS, kFS);
1867         ASSERT_NE(0u, program) << "shader compilation failed.";
1868 
1869         GLint colorLocation = glGetUniformLocation(program, "color");
1870         ASSERT_NE(-1, colorLocation);
1871 
1872         EGLWindow *window  = getEGLWindow();
1873         EGLDisplay display = window->getDisplay();
1874 
1875         window->makeCurrent();
1876 
1877         const UINT bufferSize = 32;
1878         EXPECT_TRUE(mD3D11Device != nullptr);
1879         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
1880         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
1881                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
1882 
1883         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
1884 
1885         // Create and bind Y plane texture to image.
1886         EGLImage yImage;
1887         GLuint yTexture;
1888 
1889         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
1890         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat, GL_TEXTURE_2D,
1891                                     &yImage, &yTexture);
1892 
1893         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, yImage);
1894         ASSERT_GL_NO_ERROR();
1895 
1896         GLuint fbo;
1897         glGenFramebuffers(1, &fbo);
1898         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1899         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
1900         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1901                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1902         ASSERT_GL_NO_ERROR();
1903 
1904         // Draw the Y plane using a shader.
1905         glUseProgram(program);
1906         glUniform4f(colorLocation, kYFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0, 0);
1907         ASSERT_GL_NO_ERROR();
1908 
1909         drawQuad(program, "position", 1.0f);
1910         ASSERT_GL_NO_ERROR();
1911 
1912         // Create and bind UV plane texture to image.
1913         EGLImage uvImage;
1914         GLuint uvTexture;
1915 
1916         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
1917         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat, GL_TEXTURE_2D,
1918                                     &uvImage, &uvTexture);
1919 
1920         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
1921         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1922                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
1923         ASSERT_GL_NO_ERROR();
1924 
1925         // Draw the UV plane using a shader.
1926         glUseProgram(program);
1927         glUniform4f(colorLocation, kUFillValue * 1.0f / (isNV12 ? 0xff : 0xffff),
1928                     kVFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0);
1929         ASSERT_GL_NO_ERROR();
1930 
1931         drawQuad(program, "position", 1.0f);
1932         ASSERT_GL_NO_ERROR();
1933 
1934         Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
1935         CD3D11_TEXTURE2D_DESC stagingDesc = desc;
1936         stagingDesc.BindFlags             = 0;
1937         stagingDesc.Usage                 = D3D11_USAGE_STAGING;
1938         stagingDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;
1939 
1940         EXPECT_TRUE(
1941             SUCCEEDED(mD3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture)));
1942 
1943         Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
1944         mD3D11Device->GetImmediateContext(&context);
1945 
1946         context->CopyResource(stagingTexture.Get(), d3d11Texture.Get());
1947         ASSERT_GL_NO_ERROR();
1948 
1949         D3D11_MAPPED_SUBRESOURCE mapped = {};
1950         EXPECT_TRUE(SUCCEEDED(context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped)));
1951 
1952         uint8_t *yPlane  = reinterpret_cast<uint8_t *>(mapped.pData);
1953         uint8_t *uvPlane = yPlane + bufferSize * mapped.RowPitch;
1954         if (isNV12)
1955         {
1956             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue);
1957             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue);
1958             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], kVFillValue);
1959         }
1960         else
1961         {
1962             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue & 0xff);
1963             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2 + 1], (kYFillValue >> 8) & 0xff);
1964             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue & 0xff);
1965             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], (kUFillValue >> 8) & 0xff);
1966             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 2], kVFillValue & 0xff);
1967             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 3], (kVFillValue >> 8) & 0xff);
1968         }
1969 
1970         context->Unmap(stagingTexture.Get(), 0);
1971 
1972         glDeleteProgram(program);
1973         glDeleteTextures(1, &yTexture);
1974         glDeleteTextures(1, &uvTexture);
1975         glDeleteFramebuffers(1, &fbo);
1976         eglDestroyImageKHR(display, yImage);
1977         eglDestroyImageKHR(display, uvImage);
1978     }
1979 
RunYUVReadPixelTest(DXGI_FORMAT format)1980     void RunYUVReadPixelTest(DXGI_FORMAT format)
1981     {
1982         ASSERT(format == DXGI_FORMAT_NV12 || format == DXGI_FORMAT_P010 ||
1983                format == DXGI_FORMAT_P016);
1984         UINT formatSupport;
1985         ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11() ||
1986                            FAILED(mD3D11Device->CheckFormatSupport(format, &formatSupport)));
1987         ASSERT_TRUE(formatSupport &
1988                     (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET));
1989 
1990         const bool isNV12          = (format == DXGI_FORMAT_NV12);
1991         const unsigned kYFillValue = isNV12 ? 0x12 : 0x1234;
1992         const unsigned kUFillValue = isNV12 ? 0x23 : 0x2345;
1993         const unsigned kVFillValue = isNV12 ? 0x34 : 0x3456;
1994 
1995         constexpr char kVS[] =
1996             R"(precision highp float;
1997             attribute vec4 position;
1998             varying vec2 texcoord;
1999 
2000             void main()
2001             {
2002                 gl_Position = position;
2003                 texcoord = (position.xy * 0.5) + 0.5;
2004                 texcoord.y = 1.0 - texcoord.y;
2005             })";
2006 
2007         constexpr char kFS[] =
2008             R"(precision highp float;
2009             uniform vec4 color;
2010             varying vec2 texcoord;
2011 
2012             void main()
2013             {
2014                 gl_FragColor = color;
2015             })";
2016 
2017         GLuint program = CompileProgram(kVS, kFS);
2018         ASSERT_NE(0u, program) << "shader compilation failed.";
2019 
2020         GLint colorLocation = glGetUniformLocation(program, "color");
2021         ASSERT_NE(-1, colorLocation);
2022 
2023         EGLWindow *window  = getEGLWindow();
2024         EGLDisplay display = window->getDisplay();
2025 
2026         window->makeCurrent();
2027 
2028         const UINT bufferSize = 32;
2029         EXPECT_TRUE(mD3D11Device != nullptr);
2030         Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11Texture;
2031         CD3D11_TEXTURE2D_DESC desc(format, bufferSize, bufferSize, 1, 1,
2032                                    D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
2033 
2034         EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11Texture)));
2035 
2036         // Create and bind Y plane texture to image.
2037         EGLImage yImage;
2038         GLuint yTexture;
2039 
2040         GLenum internalFormat = format == DXGI_FORMAT_NV12 ? GL_RED_EXT : GL_R16_EXT;
2041         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 0, internalFormat, GL_TEXTURE_2D,
2042                                     &yImage, &yTexture);
2043 
2044         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, yImage);
2045         ASSERT_GL_NO_ERROR();
2046 
2047         GLuint fbo;
2048         glGenFramebuffers(1, &fbo);
2049         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2050         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yTexture, 0);
2051         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2052                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2053         ASSERT_GL_NO_ERROR();
2054 
2055         // Draw the Y plane using a shader.
2056         glUseProgram(program);
2057         glUniform4f(colorLocation, kYFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0, 0);
2058         ASSERT_GL_NO_ERROR();
2059 
2060         drawQuad(program, "position", 1.0f);
2061         ASSERT_GL_NO_ERROR();
2062 
2063         // Read the Y plane pixels.
2064         if (isNV12)
2065         {
2066             GLubyte yPixels[4] = {};
2067             glReadPixels(0, bufferSize / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, yPixels);
2068             EXPECT_EQ(yPixels[0], kYFillValue);
2069         }
2070         else
2071         {
2072             GLushort yPixels[4] = {};
2073             glReadPixels(0, bufferSize / 2, 1, 1, GL_RGBA, GL_UNSIGNED_SHORT, yPixels);
2074             EXPECT_EQ(yPixels[0], kYFillValue);
2075         }
2076 
2077         // Create and bind UV plane texture to image.
2078         EGLImage uvImage;
2079         GLuint uvTexture;
2080 
2081         internalFormat = format == DXGI_FORMAT_NV12 ? GL_RG_EXT : GL_RG16_EXT;
2082         CreateAndBindImageToTexture(display, d3d11Texture.Get(), 1, internalFormat, GL_TEXTURE_2D,
2083                                     &uvImage, &uvTexture);
2084 
2085         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uvTexture, 0);
2086         EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2087                   static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
2088         ASSERT_GL_NO_ERROR();
2089 
2090         // Draw the UV plane using a shader.
2091         glUseProgram(program);
2092         glUniform4f(colorLocation, kUFillValue * 1.0f / (isNV12 ? 0xff : 0xffff),
2093                     kVFillValue * 1.0f / (isNV12 ? 0xff : 0xffff), 0, 0);
2094         ASSERT_GL_NO_ERROR();
2095 
2096         drawQuad(program, "position", 1.0f);
2097         ASSERT_GL_NO_ERROR();
2098 
2099         // Read the UV plane pixels.
2100         if (isNV12)
2101         {
2102             GLubyte uvPixels[4] = {};
2103             glReadPixels(0, bufferSize / 4, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, uvPixels);
2104             EXPECT_EQ(uvPixels[0], kUFillValue);
2105             EXPECT_EQ(uvPixels[1], kVFillValue);
2106         }
2107         else
2108         {
2109             GLushort uvPixels[4] = {};
2110             glReadPixels(0, bufferSize / 4, 1, 1, GL_RGBA, GL_UNSIGNED_SHORT, uvPixels);
2111             EXPECT_EQ(uvPixels[0], kUFillValue);
2112             EXPECT_EQ(uvPixels[1], kVFillValue);
2113         }
2114 
2115         Microsoft::WRL::ComPtr<ID3D11Texture2D> stagingTexture;
2116         CD3D11_TEXTURE2D_DESC stagingDesc = desc;
2117         stagingDesc.BindFlags             = 0;
2118         stagingDesc.Usage                 = D3D11_USAGE_STAGING;
2119         stagingDesc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;
2120 
2121         EXPECT_TRUE(
2122             SUCCEEDED(mD3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture)));
2123 
2124         Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
2125         mD3D11Device->GetImmediateContext(&context);
2126 
2127         context->CopyResource(stagingTexture.Get(), d3d11Texture.Get());
2128         ASSERT_GL_NO_ERROR();
2129 
2130         D3D11_MAPPED_SUBRESOURCE mapped = {};
2131         EXPECT_TRUE(SUCCEEDED(context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mapped)));
2132 
2133         uint8_t *yPlane  = reinterpret_cast<uint8_t *>(mapped.pData);
2134         uint8_t *uvPlane = yPlane + bufferSize * mapped.RowPitch;
2135         if (isNV12)
2136         {
2137             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue);
2138             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue);
2139             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], kVFillValue);
2140         }
2141         else
2142         {
2143             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2], kYFillValue & 0xff);
2144             EXPECT_EQ(yPlane[mapped.RowPitch * bufferSize / 2 + 1], (kYFillValue >> 8) & 0xff);
2145             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4], kUFillValue & 0xff);
2146             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 1], (kUFillValue >> 8) & 0xff);
2147             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 2], kVFillValue & 0xff);
2148             EXPECT_EQ(uvPlane[mapped.RowPitch * bufferSize / 4 + 3], (kVFillValue >> 8) & 0xff);
2149         }
2150 
2151         context->Unmap(stagingTexture.Get(), 0);
2152 
2153         glDeleteProgram(program);
2154         glDeleteTextures(1, &yTexture);
2155         glDeleteTextures(1, &uvTexture);
2156         glDeleteFramebuffers(1, &fbo);
2157         eglDestroyImageKHR(display, yImage);
2158         eglDestroyImageKHR(display, uvImage);
2159     }
2160 };
2161 
2162 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and the resulting GL
2163 // textures can be sampled from.
TEST_P(D3DTextureYUVTest,NV12TextureImageSampler)2164 TEST_P(D3DTextureYUVTest, NV12TextureImageSampler)
2165 {
2166     RunYUVSamplerTest(DXGI_FORMAT_NV12);
2167 }
2168 
2169 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2170 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageSampler)2171 TEST_P(D3DTextureYUVTest, P010TextureImageSampler)
2172 {
2173     RunYUVSamplerTest(DXGI_FORMAT_P010);
2174 }
2175 
2176 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2177 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageSampler)2178 TEST_P(D3DTextureYUVTest, P016TextureImageSampler)
2179 {
2180     RunYUVSamplerTest(DXGI_FORMAT_P016);
2181 }
2182 
2183 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and rendered to as
2184 // framebuffer attachments.
TEST_P(D3DTextureYUVTest,NV12TextureImageRender)2185 TEST_P(D3DTextureYUVTest, NV12TextureImageRender)
2186 {
2187     RunYUVRenderTest(DXGI_FORMAT_NV12);
2188 }
2189 
2190 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2191 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageRender)2192 TEST_P(D3DTextureYUVTest, P010TextureImageRender)
2193 {
2194     RunYUVRenderTest(DXGI_FORMAT_P010);
2195 }
2196 
2197 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2198 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageRender)2199 TEST_P(D3DTextureYUVTest, P016TextureImageRender)
2200 {
2201     RunYUVRenderTest(DXGI_FORMAT_P016);
2202 }
2203 
2204 // Test that an NV12 D3D11 texture can be imported as two R8 and RG8 EGLImages and rendered to as
2205 // framebuffer attachments and then read from as individual planes.
TEST_P(D3DTextureYUVTest,NV12TextureImageReadPixel)2206 TEST_P(D3DTextureYUVTest, NV12TextureImageReadPixel)
2207 {
2208     RunYUVReadPixelTest(DXGI_FORMAT_NV12);
2209 }
2210 
2211 // ANGLE ES2/D3D11 supports GL_EXT_texture_norm16 even though the extension spec says it's ES3 only.
2212 // Test P010 on ES2 since Chromium's Skia context is ES2 and it uses P010 for HDR video playback.
TEST_P(D3DTextureYUVTest,P010TextureImageReadPixel)2213 TEST_P(D3DTextureYUVTest, P010TextureImageReadPixel)
2214 {
2215     RunYUVReadPixelTest(DXGI_FORMAT_P010);
2216 }
2217 
2218 // Same as above, but for P016. P016 doesn't seem to be supported on all GPUs so it might be skipped
2219 // more often than P010 and NV12 e.g. on the NVIDIA GTX 1050 Ti.
TEST_P(D3DTextureYUVTest,P016TextureImageReadPixel)2220 TEST_P(D3DTextureYUVTest, P016TextureImageReadPixel)
2221 {
2222     RunYUVReadPixelTest(DXGI_FORMAT_P016);
2223 }
2224 
2225 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
2226 // tests should be run against.
2227 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureTest);
2228 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureClearTest);
2229 ANGLE_INSTANTIATE_TEST_ES2(D3DTextureYUVTest);
2230 ANGLE_INSTANTIATE_TEST_ES3(D3DTextureTestES3);
2231 // D3D Debug device reports an error. http://anglebug.com/3513
2232 // ANGLE_INSTANTIATE_TEST(D3DTextureTestMS, ES2_D3D11());
2233 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(D3DTextureTestMS);
2234 }  // namespace angle
2235