DisplaySettingsEvent

Demonstrates how to handle notifications about changes in display settings when programming with ADLX.

Sample Path

/Samples/C/Display/DisplaySettingsEvent

Code

Copied!

//
// Copyright (c) 2021 - 2023 Advanced Micro Devices, Inc. All rights reserved.
//
//-------------------------------------------------------------------------------------------------


#include "SDK/ADLXHelper/Windows/C/ADLXHelper.h"
#include "SDK/Include/ISystem.h"
#include "SDK/Include/IDisplays.h"
#include "SDK/Include/IDisplaySettings.h"

HANDLE hDisplaySettingsChangeEvt = NULL;

// Get the display unique name
void DisplayUniqueName(IADLXDisplay* display, char* uniqueName);

// Call back to handle changed events
static adlx_bool ADLX_STD_CALL OnDisplaySettingsChanged (IADLXDisplaySettingsChangedListener* pThis, IADLXDisplaySettingsChangedEvent* pDisplaySettingChangedEvent)
{
    if (pDisplaySettingChangedEvent == NULL)
        return false;

    printf ("OnDisplaySettingsChanged(): Display settings change event received.\n");

    IADLXDisplay* pDisplay = NULL;
    ADLX_RESULT  res = pDisplaySettingChangedEvent->pVtbl->GetDisplay (pDisplaySettingChangedEvent, &pDisplay);
    char displayName[128] = "Unknown";
    DisplayUniqueName(pDisplay, displayName);
    printf ("Display: %s\n", displayName);
    // Release display interface
    if (pDisplay != NULL)
    {
        pDisplay->pVtbl->Release (pDisplay);
    }

    adlx_bool VSRChanged = pDisplaySettingChangedEvent->pVtbl->IsVSRChanged (pDisplaySettingChangedEvent);
    printf ("OnDisplaySettingsChanged, IsVSRChanged:%s\n", VSRChanged ? "true" : "false");

    SetEvent (hDisplaySettingsChangeEvt);

    return true;
}

static IADLXDisplaySettingsChangedListenerVtbl vt = { &OnDisplaySettingsChanged };
static IADLXDisplaySettingsChangedListener DisplaySetingsEventListener = { &vt };

ADLX_RESULT  GetDisplayServices (IADLXDisplayServices** ppDisplayServices)
{
    IADLXSystem* pSys = ADLXHelper_GetSystemServices ();
    if (pSys == NULL)
        return ADLX_FAIL ;
    return pSys->pVtbl->GetDisplaysServices (pSys, ppDisplayServices);
}

ADLX_RESULT  AddDisplaySettingsListener ()
{
    ADLX_RESULT  res = ADLX_FAIL ;

    IADLXDisplayServices* pDisplayServices = NULL;
    res = GetDisplayServices (&pDisplayServices);
    if (ADLX_SUCCEEDED  (res) && pDisplayServices != NULL)
    {
        IADLXDisplayChangedHandling* pDisplayChangedHandler = NULL;
        res = pDisplayServices->pVtbl->GetDisplayChangedHandling (pDisplayServices, &pDisplayChangedHandler);
        if (ADLX_SUCCEEDED  (res) && pDisplayChangedHandler)
        {
            res = pDisplayChangedHandler->pVtbl->AddDisplaySettingsEventListener (pDisplayChangedHandler, &DisplaySetingsEventListener);
            pDisplayChangedHandler->pVtbl->Release (pDisplayChangedHandler);
            pDisplayChangedHandler = NULL;
        }
        pDisplayServices->pVtbl->Release (pDisplayServices);
        pDisplayServices = NULL;
    }

    return res;
}

ADLX_RESULT  RemoveDisplaySettingsListener ()
{
    ADLX_RESULT  res = ADLX_FAIL ;

    IADLXDisplayServices* pDisplayServices = NULL;
    res = GetDisplayServices (&pDisplayServices);
    if (ADLX_SUCCEEDED  (res) && pDisplayServices != NULL)
    {
        IADLXDisplayChangedHandling* pDisplayChangedHandler = NULL;
        res = pDisplayServices->pVtbl->GetDisplayChangedHandling (pDisplayServices, &pDisplayChangedHandler);
        if (ADLX_SUCCEEDED  (res) && pDisplayChangedHandler)
        {
            res = pDisplayChangedHandler->pVtbl->RemoveDisplaySettingsEventListener (pDisplayChangedHandler, &DisplaySetingsEventListener);
            pDisplayChangedHandler->pVtbl->Release (pDisplayChangedHandler);
            pDisplayChangedHandler = NULL;
        }
        pDisplayServices->pVtbl->Release (pDisplayServices);
        pDisplayServices = NULL;
    }

    return res;
}

// VSR helper
ADLX_RESULT  IsVSRSupported (IADLXDisplay* pDisplay, adlx_bool* supported)
{
    ADLX_RESULT  res = ADLX_FAIL ;
    if (pDisplay == NULL || supported == NULL)
        return res;

    IADLXDisplayServices* pDisplayServices = NULL;
    res = GetDisplayServices (&pDisplayServices);
    if (ADLX_SUCCEEDED  (res) && pDisplayServices != NULL)
    {
        IADLXDisplayVSR* pVSR = NULL;
        pDisplayServices->pVtbl->GetVirtualSuperResolution (pDisplayServices, pDisplay, &pVSR);

        res = pVSR->pVtbl->IsSupported (pVSR, supported);
        pVSR->pVtbl->Release (pVSR);
        pDisplayServices->pVtbl->Release (pDisplayServices);
    }

    return res;
}

ADLX_RESULT  GetVSREnabled (IADLXDisplay* pDisplay, adlx_bool* enabled)
{
    ADLX_RESULT  res = ADLX_FAIL ;
    if (pDisplay == NULL || enabled == NULL)
        return res;

    IADLXDisplayServices* pDisplayServices = NULL;
    res = GetDisplayServices (&pDisplayServices);
    if (ADLX_SUCCEEDED  (res) && pDisplayServices != NULL)
    {
        IADLXDisplayVSR* pVSR = NULL;
        pDisplayServices->pVtbl->GetVirtualSuperResolution (pDisplayServices, pDisplay, &pVSR);

        res = pVSR->pVtbl->IsEnabled (pVSR, enabled);
        pVSR->pVtbl->Release (pVSR);
        pDisplayServices->pVtbl->Release (pDisplayServices);
    }

    return res;
}

ADLX_RESULT  SetVSREnabled (IADLXDisplay* pDisplay, adlx_bool enabled)
{
    ADLX_RESULT  res = ADLX_FAIL ;
    if (pDisplay == NULL)
        return res;

    IADLXDisplayServices* pDisplayServices = NULL;
    res = GetDisplayServices (&pDisplayServices);
    if (ADLX_SUCCEEDED  (res) && pDisplayServices != NULL)
    {
        IADLXDisplayVSR* pVSR = NULL;
        pDisplayServices->pVtbl->GetVirtualSuperResolution (pDisplayServices, pDisplay, &pVSR);

        res = pVSR->pVtbl->SetEnabled (pVSR, enabled);
        pVSR->pVtbl->Release (pVSR);
        pDisplayServices->pVtbl->Release (pDisplayServices);
    }

    return res;
}

int main ()
{
    ADLX_RESULT  res = ADLXHelper_Initialize ();
    if (ADLX_SUCCEEDED  (res))
    {
        hDisplaySettingsChangeEvt = CreateEvent (NULL, TRUE, FALSE, NULL);

        IADLXDisplayServices* pDisplayService = NULL;
        IADLXDisplayList* pDisplayList = NULL;
        IADLXDisplay* pDisplay = NULL;

        res = GetDisplayServices (&pDisplayService);
        if (ADLX_SUCCEEDED  (res) && pDisplayService != NULL)
        {
            res = pDisplayService->pVtbl->GetDisplays (pDisplayService, &pDisplayList);
            if (ADLX_SUCCEEDED  (res))
            {
                if (pDisplayList && !pDisplayList->pVtbl->Empty (pDisplayList))
                {
                    IADLXDisplay* pDisplay = NULL;
                    res = pDisplayList->pVtbl->At_DisplayList (pDisplayList, 0, &pDisplay);
                    if (ADLX_SUCCEEDED  (res) && pDisplay != NULL)
                    {
                        adlx_bool supported = false;
                        res = IsVSRSupported (pDisplay, &supported);
                        if (ADLX_SUCCEEDED  (res) && supported)
                        {
                            adlx_bool enabled = false;
                            res = GetVSREnabled (pDisplay, &enabled);
                            if (ADLX_FAILED  (res))
                                goto END;

                            res = AddDisplaySettingsListener ();
                            if (ADLX_FAILED  (res))
                                goto END;

                            ResetEvent (hDisplaySettingsChangeEvt);

                            res = SetVSREnabled (pDisplay, !enabled);
                            if (ADLX_FAILED  (res))
                                goto END;

                            DWORD r = WaitForSingleObject (hDisplaySettingsChangeEvt, 1000);
                            if (ADLX_FAILED  (res))
                                goto END;

                            res = RemoveDisplaySettingsListener ();
                            if (ADLX_FAILED  (res))
                                goto END;

                            res = SetVSREnabled (pDisplay, enabled);
                            if (ADLX_FAILED  (res))
                                goto END;

                        }
                    END:
                        pDisplay->pVtbl->Release (pDisplay);
                    }
                    pDisplayList->pVtbl->Release (pDisplayList);
                }
            }
            pDisplayService->pVtbl->Release (pDisplayService);
        }
    }
    else
    {
        printf ("ADLX initialization failed\n");
        return 0;
    }

    res = ADLXHelper_Terminate ();
    printf ("Destroy ADLX result: %d\n", res);

    if (hDisplaySettingsChangeEvt)
        CloseHandle(hDisplaySettingsChangeEvt);

    system ("pause");

    return 0;
}

void DisplayUniqueName(IADLXDisplay* display, char* uniqueName)
{
    if (NULL != display && NULL != uniqueName)
    {
        const char* gpuName = NULL;
        ADLX_RESULT  res = display->pVtbl->Name(display, &gpuName);
        if (ADLX_SUCCEEDED (res))
            sprintf_s(uniqueName, 128, "name:%s", gpuName);
        adlx_size id;
        res = display->pVtbl->UniqueId(display, &id);
        if (ADLX_SUCCEEDED (res))
            sprintf_s(uniqueName, 128, "id:%zu", id);
    }
}