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