-
Notifications
You must be signed in to change notification settings - Fork 29.2k
Description
Steps to Reproduce
- build a flutter demo to be run on a Win7 without D3D11
- Debug flutter
Expected results:
flutter failed to initialize D3D11 but succeeded in initializing D3D9
Actual results:
flutter didn't initiliaze d3d9 as expected
Code analysis
Let's start with the function AngleSurfaceManager::Initialize (defined in flutter\engine\shell\platform\windows\angle_surface_manager.cc): const EGLint d3d11_display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
// EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that will
// enable ANGLE to automatically call the IDXGIDevice3::Trim method on
// behalf of the application when it gets suspended.
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
// These are used to request ANGLE's D3D11 renderer, with D3D11 Feature
// Level 9_3.
const EGLint d3d11_fl_9_3_display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
9,
EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE,
3,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
// These attributes request D3D11 WARP (software rendering fallback) in case
// hardware-backed D3D11 is unavailable.
const EGLint d3d11_warp_display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
// These are used to request ANGLE's D3D9 renderer as a fallback if D3D11
// is not available.
const EGLint d3d9_display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
EGL_TRUE,
EGL_NONE,
};
std::vector<const EGLint*> display_attributes_configs = {
d3d11_display_attributes,
d3d11_fl_9_3_display_attributes,
d3d11_warp_display_attributes,
d3d9_display_attributes,
};
PFNEGLGETPLATFORMDISPLAYEXTPROC egl_get_platform_display_EXT =
reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
eglGetProcAddress("eglGetPlatformDisplayEXT"));
if (!egl_get_platform_display_EXT) {
LogEglError("eglGetPlatformDisplayEXT not available");
return false;
}
// Attempt to initialize ANGLE's renderer in order of: D3D11, D3D11 Feature
// Level 9_3, D3D11 WARP and finally D3D9.
for (auto config : display_attributes_configs) {
bool should_log = (config == display_attributes_configs.back());
if (InitializeEGL(egl_get_platform_display_EXT, config, should_log)) {
break;
}
}
As we can see,it attempts to initialize ANGLE's renderer in order of: D3D11, D3D11 Feature
Level 9_3, D3D11 WARP and finally D3D9. So if Initializing D3D11 failed,D3D9 is supposed to
be inintialized.However,it is not the thing.Following the call stack,we can find the arrays(d3d11_display_attributes,d3d11_fl_9_3_display_attributes,d3d11_warp_display_attributes and d3d9_display_attributes) are handled in AttributeMap::CreateFromIntArray(defined in third_party\angle\src\libANGLE\AttributeMap.cpp):
AttributeMap AttributeMap::CreateFromIntArray(const EGLint *attributes)
{
AttributeMap map;
if (attributes)
{
for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
{
map.insert(static_cast<EGLAttrib>(curAttrib[0]), static_cast<EGLAttrib>(curAttrib[1]));
}
}
return map;
}
This func is simple,just convert an array to a map.However,the param is just a pointer,without a length, the terminating condition for this loop is "curAttrib[0] == EGL_NONE".As we come back to the definition of d3d9_display_attributes:
const EGLint d3d9_display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
EGL_TRUE,
EGL_NONE,
};
Obviously,the loop won't end in d3d9_display_attributes because d3d9_display_attributes[2] != EGL_NONE.instead,the loop will
continue run for d3d11_warp_display_attributes(it is next to d3d9_display_attributes on stack),so finally we get a key -value of EGL_PLATFORM_ANGLE_TYPE_ANGLE and EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE which means we are initialzing D3D11 instead of D3D9.
Apparently it's a bug.As a consequence, the fallback of D3D9 is not gonna working.
So would you guys fix this problem?I would like to submit a pull request for it.