Skip to content

flutter didn't initiliaze d3d9 as expected on Windows 7 #92650

@PerserveranceX

Description

@PerserveranceX

Steps to Reproduce

  1. build a flutter demo to be run on a Win7 without D3D11
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: desktopRunning on desktope: OS-version specificAffects only some versions of the relevant operating systemengineflutter/engine related. See also e: labels.platform-windowsBuilding on or for Windows specificallyr: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions