summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp')
-rw-r--r--gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp326
1 files changed, 326 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp b/gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp
new file mode 100644
index 000000000..028b24a81
--- /dev/null
+++ b/gfx/angle/src/tests/gl_tests/D3DTextureTest.cpp
@@ -0,0 +1,326 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// D3DTextureTest:
+// Tests of the EGL_ANGLE_d3d_texture_client_buffer extension
+
+#include "test_utils/ANGLETest.h"
+
+#include <d3d11.h>
+#include <windows.h>
+
+#include "com_utils.h"
+
+namespace angle
+{
+
+class D3DTextureTest : public ANGLETest
+{
+ protected:
+ D3DTextureTest()
+ {
+ setWindowWidth(128);
+ setWindowHeight(128);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ }
+
+ void SetUp() override
+ {
+ ANGLETest::SetUp();
+
+ // clang-format off
+ const std::string vsSource = SHADER_SOURCE
+ (
+ precision highp float;
+ attribute vec4 position;
+ varying vec2 texcoord;
+
+ void main()
+ {
+ gl_Position = position;
+ texcoord = (position.xy * 0.5) + 0.5;
+ texcoord.y = 1.0 - texcoord.y;
+ }
+ );
+
+ const std::string textureFSSource = SHADER_SOURCE
+ (
+ precision highp float;
+ uniform sampler2D tex;
+ varying vec2 texcoord;
+
+ void main()
+ {
+ gl_FragColor = texture2D(tex, texcoord);
+ }
+ );
+ // clang-format on
+
+ mTextureProgram = CompileProgram(vsSource, textureFSSource);
+ ASSERT_NE(0u, mTextureProgram) << "shader compilation failed.";
+
+ mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+ ASSERT_NE(-1, mTextureUniformLocation);
+
+ mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
+ ASSERT_NE(nullptr, mD3D11Module);
+
+ PFN_D3D11_CREATE_DEVICE createDeviceFunc = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
+
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+ if (eglDisplayExtensionEnabled(display, "EGL_EXT_device_query"))
+ {
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
+ reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
+ eglGetProcAddress("eglQueryDisplayAttribEXT"));
+ PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT =
+ reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
+ eglGetProcAddress("eglQueryDeviceAttribEXT"));
+
+ EGLDeviceEXT device = 0;
+ {
+ EGLAttrib result = 0;
+ EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
+ device = reinterpret_cast<EGLDeviceEXT>(result);
+ }
+
+ if (eglDeviceExtensionEnabled(device, "EGL_ANGLE_device_d3d"))
+ {
+ EGLAttrib result = 0;
+ if (eglQueryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &result))
+ {
+ mD3D11Device = reinterpret_cast<ID3D11Device *>(result);
+ mD3D11Device->AddRef();
+ }
+ else if (eglQueryDeviceAttribEXT(device, EGL_D3D9_DEVICE_ANGLE, &result))
+ {
+ mD3D9Device = reinterpret_cast<IDirect3DDevice9 *>(result);
+ mD3D9Device->AddRef();
+ }
+ }
+ }
+ else
+ {
+ ASSERT_TRUE(
+ SUCCEEDED(createDeviceFunc(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
+ 0, D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr)));
+ }
+ }
+
+ void TearDown() override
+ {
+ glDeleteProgram(mTextureProgram);
+
+ if (mD3D11Device)
+ {
+ mD3D11Device->Release();
+ mD3D11Device = nullptr;
+ }
+
+ FreeLibrary(mD3D11Module);
+ mD3D11Module = nullptr;
+
+ if (mD3D9Device)
+ {
+ mD3D9Device->Release();
+ mD3D9Device = nullptr;
+ }
+
+ ANGLETest::TearDown();
+ }
+
+ EGLSurface createPBuffer(size_t width,
+ size_t height,
+ EGLint eglTextureFormat,
+ EGLint eglTextureTarget)
+ {
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+ EGLConfig config = window->getConfig();
+
+ EGLint attribs[] = {
+ EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
+ eglTextureTarget, EGL_NONE, EGL_NONE,
+ };
+
+ if (mD3D11Device)
+ {
+ ID3D11Texture2D *texture = nullptr;
+ CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, static_cast<UINT>(width),
+ static_cast<UINT>(height), 1, 1,
+ D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
+ EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
+ texture, config, attribs);
+
+ texture->Release();
+
+ return pbuffer;
+ }
+ else if (mD3D9Device)
+ {
+ IDirect3DTexture9 *texture = nullptr;
+ EXPECT_TRUE(SUCCEEDED(mD3D9Device->CreateTexture(
+ static_cast<UINT>(width), static_cast<UINT>(height), 1, D3DUSAGE_RENDERTARGET,
+ D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr)));
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
+ texture, config, attribs);
+
+ texture->Release();
+
+ return pbuffer;
+ }
+ else
+ {
+ return EGL_NO_SURFACE;
+ }
+ }
+
+ bool valid() const
+ {
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+ if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_d3d_texture_client_buffer"))
+ {
+ std::cout << "Test skipped due to missing EGL_ANGLE_d3d_texture_client_buffer"
+ << std::endl;
+ return false;
+ }
+
+ if (!mD3D11Device && !mD3D9Device)
+ {
+ std::cout << "Test skipped due to no D3D devices being available." << std::endl;
+ return false;
+ }
+
+ if (IsWindows() && IsAMD() && IsOpenGL())
+ {
+ std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
+ return false;
+ }
+
+ if (IsWindows() && IsIntel() && IsOpenGL())
+ {
+ std::cout << "Test skipped on Windows Intel OpenGL." << std::endl;
+ return false;
+ }
+ return true;
+ }
+
+ GLuint mTextureProgram;
+ GLint mTextureUniformLocation;
+
+ HMODULE mD3D11Module = nullptr;
+ ID3D11Device *mD3D11Device = nullptr;
+
+ IDirect3DDevice9 *mD3D9Device = nullptr;
+};
+
+// Test creating a pbuffer from a d3d surface and clearing it
+TEST_P(D3DTextureTest, Clear)
+{
+ if (!valid())
+ {
+ return;
+ }
+
+ EGLWindow *window = getEGLWindow();
+ EGLDisplay display = window->getDisplay();
+
+ const size_t bufferSize = 32;
+
+ EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE);
+ ASSERT_EGL_SUCCESS();
+ ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+ // Apply the Pbuffer and clear it to purple and verify
+ eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
+ ASSERT_EGL_SUCCESS();
+
+ glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+ glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
+ 255, 255);
+
+ eglDestroySurface(display, pbuffer);
+}
+
+// Test creating a pbuffer from a d3d surface and binding it to a texture
+TEST_P(D3DTextureTest, BindTexImage)
+{
+ if (!valid())
+ {
+ return;
+ }
+
+ EGLWindow *window = getEGLWindow();
+
+ const size_t bufferSize = 32;
+
+ EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D);
+ ASSERT_EGL_SUCCESS();
+ ASSERT_NE(pbuffer, EGL_NO_SURFACE);
+
+ // Apply the Pbuffer and clear it to purple
+ eglMakeCurrent(window->getDisplay(), pbuffer, pbuffer, window->getContext());
+ ASSERT_EGL_SUCCESS();
+
+ glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
+ glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+
+ EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
+ 255, 255);
+
+ // Apply the window surface
+ eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(),
+ window->getContext());
+
+ // Create a texture and bind the Pbuffer to it
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ EXPECT_GL_NO_ERROR();
+
+ eglBindTexImage(window->getDisplay(), pbuffer, EGL_BACK_BUFFER);
+ glViewport(0, 0, getWindowWidth(), getWindowHeight());
+ ASSERT_EGL_SUCCESS();
+
+ // Draw a quad and verify that it is purple
+ glUseProgram(mTextureProgram);
+ glUniform1i(mTextureUniformLocation, 0);
+
+ drawQuad(mTextureProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+
+ // Unbind the texture
+ eglReleaseTexImage(window->getDisplay(), pbuffer, EGL_BACK_BUFFER);
+ ASSERT_EGL_SUCCESS();
+
+ // Verify that purple was drawn
+ EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
+
+ glDeleteTextures(1, &texture);
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(D3DTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
+
+} // namespace