Commit 49ae88ba by John Bauman

Implement EGL_ANGLE_direct_composition extension

On D3D11, if dcomp.dll can be loaded then EGL_ANGLE_direct_composition is exposed. Setting EGL_DIRECT_COMPOSITION_ANGLE as an attrib on a surface will force it to use DirectComposition to draw to the screen, possibly saving power. BUG=524838 Change-Id: I3ea175a97bbca1a3388ffe52fdd1587a2f0c2ce7 Reviewed-on: https://chromium-review.googlesource.com/319214Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJohn Bauman <jbauman@chromium.org>
parent 44492266
......@@ -468,6 +468,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
#ifndef EGL_ANGLE_direct_composition
#define EGL_ANGLE_direct_composition 1
#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
#endif /* EGL_ANGLE_direct_composition */
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
......
......@@ -621,7 +621,8 @@ DisplayExtensions::DisplayExtensions()
glTexture3DImage(false),
glRenderbufferImage(false),
getAllProcAddresses(false),
flexibleSurfaceCompatibility(false)
flexibleSurfaceCompatibility(false),
directComposition(false)
{
}
......@@ -638,6 +639,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
......
......@@ -465,6 +465,9 @@ struct DisplayExtensions
// EGL_ANGLE_flexible_surface_compatibility
bool flexibleSurfaceCompatibility;
// EGL_ANGLE_direct_composition
bool directComposition;
};
struct DeviceExtensions
......
......@@ -49,6 +49,8 @@ Surface::Surface(rx::SurfaceImpl *impl,
mFlexibleSurfaceCompatibilityRequested =
(attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
if (mFixedSize)
{
......
......@@ -84,6 +84,8 @@ class Surface final : public gl::FramebufferAttachmentObject
}
EGLint getOrientation() const { return mOrientation; }
bool directComposition() const { return mDirectComposition; }
private:
virtual ~Surface();
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; }
......@@ -110,6 +112,8 @@ class Surface final : public gl::FramebufferAttachmentObject
size_t mFixedWidth;
size_t mFixedHeight;
bool mDirectComposition;
EGLenum mTextureFormat;
EGLenum mTextureTarget;
......
......@@ -173,6 +173,7 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration,
EGLint height = attribs.get(EGL_HEIGHT, 0);
EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE);
EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
EGLint directComposition = attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE);
if (!fixedSize)
{
......@@ -181,7 +182,7 @@ SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration,
}
return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize,
width, height, orientation);
directComposition, width, height, orientation);
}
SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration,
......
......@@ -24,7 +24,8 @@ namespace rx
SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle,
EGLint width, EGLint height)
{
return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, shareHandle, NULL);
return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, EGL_FALSE,
shareHandle, NULL);
}
SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer,
......@@ -32,12 +33,13 @@ SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer,
const egl::Config *config,
EGLNativeWindowType window,
EGLint fixedSize,
EGLint directComposition,
EGLint width,
EGLint height,
EGLint orientation)
{
return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation,
static_cast<EGLClientBuffer>(0), window);
directComposition, static_cast<EGLClientBuffer>(0), window);
}
SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
......@@ -47,6 +49,7 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
EGLint height,
EGLint fixedSize,
EGLint orientation,
EGLint directComposition,
EGLClientBuffer shareHandle,
EGLNativeWindowType window)
: SurfaceImpl(),
......@@ -58,7 +61,7 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
mDepthStencilFormat(config->depthStencilFormat),
mSwapChain(nullptr),
mSwapIntervalDirty(true),
mNativeWindow(window, config),
mNativeWindow(window, config, directComposition),
mWidth(width),
mHeight(height),
mSwapInterval(1),
......
......@@ -30,6 +30,7 @@ class SurfaceD3D : public SurfaceImpl
const egl::Config *config,
EGLNativeWindowType window,
EGLint fixedSize,
EGLint directComposition,
EGLint width,
EGLint height,
EGLint orientation);
......@@ -73,6 +74,7 @@ class SurfaceD3D : public SurfaceImpl
EGLint height,
EGLint fixedSize,
EGLint orientation,
EGLint directComposition,
EGLClientBuffer shareHandle,
EGLNativeWindowType window);
......
......@@ -44,14 +44,21 @@ typedef IDXGISwapChain DXGISwapChain;
typedef IDXGIFactory DXGIFactory;
#endif
typedef interface IDCompositionDevice IDCompositionDevice;
typedef interface IDCompositionTarget IDCompositionTarget;
typedef interface IDCompositionVisual IDCompositionVisual;
namespace rx
{
class NativeWindow
{
public:
explicit NativeWindow(EGLNativeWindowType window, const egl::Config *config);
explicit NativeWindow(EGLNativeWindowType window,
const egl::Config *config,
bool directComposition);
~NativeWindow();
bool initialize();
bool getClientRect(LPRECT rect);
bool isIconic();
......@@ -63,11 +70,17 @@ class NativeWindow
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
void commitChange();
private:
EGLNativeWindowType mWindow;
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
bool mDirectComposition;
IDCompositionDevice *mDevice;
IDCompositionTarget *mCompositionTarget;
IDCompositionVisual *mVisual;
const egl::Config *mConfig;
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
std::shared_ptr<InspectableNativeWindow> mImpl;
#endif
......
......@@ -499,6 +499,7 @@ Renderer11::Renderer11(egl::Display *display)
mD3d11Module = NULL;
mDxgiModule = NULL;
mDCompModule = NULL;
mCreatedWithDeviceEXT = false;
mEGLDevice = nullptr;
......@@ -765,6 +766,7 @@ egl::Error Renderer11::initializeD3DDevice()
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
if (mD3d11Module == nullptr || mDxgiModule == nullptr)
{
......@@ -1089,6 +1091,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->glRenderbufferImage = true;
outExtensions->flexibleSurfaceCompatibility = true;
outExtensions->directComposition = !!mDCompModule;
}
gl::Error Renderer11::flush()
......@@ -2604,6 +2607,12 @@ void Renderer11::release()
mDxgiModule = NULL;
}
if (mDCompModule)
{
FreeLibrary(mDCompModule);
mDCompModule = NULL;
}
mCompiler.release();
}
......
......@@ -327,6 +327,7 @@ class Renderer11 : public RendererD3D
HMODULE mD3d11Module;
HMODULE mDxgiModule;
HMODULE mDCompModule;
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
D3D_DRIVER_TYPE mDriverType;
bool mCreatedWithDeviceEXT;
......
......@@ -821,6 +821,8 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
ERR("Present failed with error code 0x%08X", result);
}
mNativeWindow.commitChange();
return EGL_SUCCESS;
}
......
......@@ -11,14 +11,31 @@
#include "common/debug.h"
#include <initguid.h>
#include <dcomp.h>
namespace rx
{
NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *)
: mWindow(window)
NativeWindow::NativeWindow(EGLNativeWindowType window,
const egl::Config *config,
bool directComposition)
: mWindow(window),
mDirectComposition(directComposition),
mCompositionTarget(nullptr),
mDevice(nullptr),
mVisual(nullptr),
mConfig(config)
{
}
NativeWindow::~NativeWindow()
{
SafeRelease(mCompositionTarget);
SafeRelease(mDevice);
SafeRelease(mVisual);
}
bool NativeWindow::initialize()
{
return true;
......@@ -48,6 +65,83 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
return E_INVALIDARG;
}
if (mDirectComposition)
{
HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
if (!dcomp)
{
return E_INVALIDARG;
}
typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
GetProcAddress(dcomp, "DCompositionCreateDevice"));
if (!createDComp)
{
return E_INVALIDARG;
}
if (!mDevice)
{
IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
reinterpret_cast<void **>(&mDevice));
SafeRelease(dxgiDevice);
if (FAILED(result))
{
return result;
}
}
if (!mCompositionTarget)
{
HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget);
if (FAILED(result))
{
return result;
}
}
if (!mVisual)
{
HRESULT result = mDevice->CreateVisual(&mVisual);
if (FAILED(result))
{
return result;
}
}
IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 2;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.AlphaMode =
mConfig->alphaSize == 0 ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
swapChainDesc.Flags = 0;
IDXGISwapChain1 *swapChain1 = nullptr;
HRESULT result =
factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
if (SUCCEEDED(result))
{
*swapChain = static_cast<DXGISwapChain *>(swapChain1);
}
mVisual->SetContent(swapChain1);
mCompositionTarget->SetRoot(mVisual);
SafeRelease(factory2);
return result;
}
// Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
if (factory2 != nullptr)
......@@ -96,4 +190,12 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
}
void NativeWindow::commitChange()
{
if (mDevice)
{
mDevice->Commit();
}
}
}
......@@ -11,12 +11,22 @@
namespace rx
{
NativeWindow::NativeWindow(EGLNativeWindowType window, const egl::Config *config)
NativeWindow::NativeWindow(EGLNativeWindowType window,
const egl::Config *config,
bool directComposition)
{
mWindow = window;
mConfig = config;
}
NativeWindow::~NativeWindow()
{
}
void NativeWindow::commitChange()
{
}
bool NativeWindow::initialize()
{
// If the native window type is a IPropertySet, extract the
......
......@@ -385,6 +385,13 @@ Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWin
case EGL_VG_ALPHA_FORMAT:
return Error(EGL_BAD_MATCH);
case EGL_DIRECT_COMPOSITION_ANGLE:
if (!displayExtensions.directComposition)
{
return Error(EGL_BAD_ATTRIBUTE);
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE);
}
......
......@@ -447,6 +447,16 @@ EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint a
}
*value = eglSurface->getOrientation();
break;
case EGL_DIRECT_COMPOSITION_ANGLE:
if (!display->getExtensions().directComposition)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
"EGL_DIRECT_COMPOSITION_ANGLE cannot be used without "
"EGL_ANGLE_direct_composition support."));
return EGL_FALSE;
}
*value = eglSurface->directComposition();
break;
default:
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment