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