Exemple #1
0
bool Display::initialize()
{
    if (isInitialized())
    {
        return true;
    }

    mD3d9Module = LoadLibrary(TEXT("d3d9.dll"));
    if (mD3d9Module == NULL)
    {
        terminate();
        return false;
    }

    typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT);
    Direct3DCreate9Func Direct3DCreate9Ptr = reinterpret_cast<Direct3DCreate9Func>(GetProcAddress(mD3d9Module, "Direct3DCreate9"));

    if (Direct3DCreate9Ptr == NULL)
    {
        terminate();
        return false;
    }

    typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
    Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));

    // Use Direct3D9Ex if available. Among other things, this version is less
    // inclined to report a lost context, for example when the user switches
    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
    if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9ex)))
    {
        ASSERT(mD3d9ex);
        mD3d9ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
        ASSERT(mD3d9);
    }
    else
    {
        mD3d9 = Direct3DCreate9Ptr(D3D_SDK_VERSION);
    }

    if (mD3d9)
    {
        if (mDc != NULL)
        {
            //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
        }

        HRESULT result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);

        if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
        {
            return error(EGL_BAD_ALLOC, false);
        }

        if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
        {
            terminate();
            return error(EGL_NOT_INITIALIZED, false);
        }

        mMinSwapInterval = 4;
        mMaxSwapInterval = 0;

        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {
            mMinSwapInterval = std::min(mMinSwapInterval, 0);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)       {
            mMinSwapInterval = std::min(mMinSwapInterval, 1);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)       {
            mMinSwapInterval = std::min(mMinSwapInterval, 2);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)     {
            mMinSwapInterval = std::min(mMinSwapInterval, 3);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)      {
            mMinSwapInterval = std::min(mMinSwapInterval, 4);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
        }

        const D3DFORMAT renderTargetFormats[] =
        {
            D3DFMT_A1R5G5B5,
            //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
            D3DFMT_A8R8G8B8,
            D3DFMT_R5G6B5,
            D3DFMT_X1R5G5B5,
            D3DFMT_X8R8G8B8
        };

        const D3DFORMAT depthStencilFormats[] =
        {
            //  D3DFMT_D16_LOCKABLE,
            D3DFMT_D32,
            //  D3DFMT_D15S1,
            D3DFMT_D24S8,
            D3DFMT_D24X8,
            //  D3DFMT_D24X4S4,
            D3DFMT_D16,
            //  D3DFMT_D32F_LOCKABLE,
            //  D3DFMT_D24FS8
        };

        D3DDISPLAYMODE currentDisplayMode;
        mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);

        ConfigSet configSet;

        for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
        {
            D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];

            HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);

            if (SUCCEEDED(result))
            {
                for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
                {
                    D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
                    HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);

                    if (SUCCEEDED(result))
                    {
                        HRESULT result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);

                        if (SUCCEEDED(result))
                        {
                            // FIXME: enumerate multi-sampling

                            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0);
                        }
                    }
                }
            }
        }

        // Give the sorted configs a unique ID and store them internally
        EGLint index = 1;
        for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
        {
            Config configuration = *config;
            configuration.mConfigID = index;
            index++;

            mConfigSet.mSet.insert(configuration);
        }

        if (!createDevice())
        {
            terminate();

            return false;
        }
    }

    if (!isInitialized())
    {
        terminate();

        return false;
    }

    return true;
}
Exemple #2
0
bool Display::initialize()
{
    if (isInitialized())
    {
        return true;
    }

    if (mSoftwareDevice)
    {
        mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
    }
    else
    {
        mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
    }
    if (mD3d9Module == NULL)
    {
        terminate();
        return false;
    }

    typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
    Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));

#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
    // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
    static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;

    for (int i = 0; i < sizeof(d3dCompilerNames) / sizeof(*d3dCompilerNames); ++i)
    {
        if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule))
        {
            break;
        }
    }
#else
    // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
    mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL);
#endif  // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES

    if (!mD3dCompilerModule)
    {
        terminate();
        return false;
    }

    mD3DCompileFunc = reinterpret_cast<D3DCompileFunc>(GetProcAddress(mD3dCompilerModule, "D3DCompile"));
    ASSERT(mD3DCompileFunc);

    // Use Direct3D9Ex if available. Among other things, this version is less
    // inclined to report a lost context, for example when the user switches
    // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
    if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
    {
        ASSERT(mD3d9Ex);
        mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
        ASSERT(mD3d9);
    }
    else
    {
        mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    }

    if (mD3d9)
    {
        if (mDc != NULL)
        {
            //  UNIMPLEMENTED();   // FIXME: Determine which adapter index the device context corresponds to
        }

        HRESULT result;

        // Give up on getting device caps after about one second.
        for (int i = 0; i < 10; ++i)
        {
            result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);

            if (SUCCEEDED(result))
            {
                break;
            }
            else if (result == D3DERR_NOTAVAILABLE)
            {
                Sleep(100);   // Give the driver some time to initialize/recover
            }
            else if (FAILED(result))   // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
            {
                terminate();
                return error(EGL_BAD_ALLOC, false);
            }
        }

        if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
        {
            terminate();
            return error(EGL_NOT_INITIALIZED, false);
        }

        // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
        // This is required by Texture2D::convertToRenderTarget.
        if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
        {
            terminate();
            return error(EGL_NOT_INITIALIZED, false);
        }

        mMinSwapInterval = 4;
        mMaxSwapInterval = 0;

        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {
            mMinSwapInterval = std::min(mMinSwapInterval, 0);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)       {
            mMinSwapInterval = std::min(mMinSwapInterval, 1);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)       {
            mMinSwapInterval = std::min(mMinSwapInterval, 2);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)     {
            mMinSwapInterval = std::min(mMinSwapInterval, 3);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
        }
        if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)      {
            mMinSwapInterval = std::min(mMinSwapInterval, 4);
            mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
        }

        mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);

        // ATI cards on XP have problems with non-power-of-two textures.
        mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
                                     !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
                                     !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
                                     !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);

        const D3DFORMAT renderTargetFormats[] =
        {
            D3DFMT_A1R5G5B5,
            //  D3DFMT_A2R10G10B10,   // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
            D3DFMT_A8R8G8B8,
            D3DFMT_R5G6B5,
            //  D3DFMT_X1R5G5B5,      // Has no compatible OpenGL ES renderbuffer format
            D3DFMT_X8R8G8B8
        };

        const D3DFORMAT depthStencilFormats[] =
        {
            D3DFMT_UNKNOWN,
            //  D3DFMT_D16_LOCKABLE,
            D3DFMT_D32,
            //  D3DFMT_D15S1,
            D3DFMT_D24S8,
            D3DFMT_D24X8,
            //  D3DFMT_D24X4S4,
            D3DFMT_D16,
            //  D3DFMT_D32F_LOCKABLE,
            //  D3DFMT_D24FS8
        };

        D3DDISPLAYMODE currentDisplayMode;
        mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);

        ConfigSet configSet;

        for (unsigned int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++)
        {
            D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex];

            HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);

            if (SUCCEEDED(result))
            {
                for (unsigned int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++)
                {
                    D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex];
                    HRESULT result = D3D_OK;

                    if(depthStencilFormat != D3DFMT_UNKNOWN)
                    {
                        result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
                    }

                    if (SUCCEEDED(result))
                    {
                        if(depthStencilFormat != D3DFMT_UNKNOWN)
                        {
                            result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
                        }

                        if (SUCCEEDED(result))
                        {
                            // FIXME: enumerate multi-sampling

                            configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0,
                                          mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight);
                        }
                    }
                }
            }
        }

        // Give the sorted configs a unique ID and store them internally
        EGLint index = 1;
        for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
        {
            Config configuration = *config;
            configuration.mConfigID = index;
            index++;

            mConfigSet.mSet.insert(configuration);
        }
    }

    if (!isInitialized())
    {
        terminate();

        return false;
    }

    initExtensionString();

    static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
    static const TCHAR className[] = TEXT("STATIC");

    mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);

    if (!createDevice())
    {
        terminate();
        return false;
    }

    mVertexShaderCache.initialize(mDevice);
    mPixelShaderCache.initialize(mDevice);

    return true;
}