falahati / NvAPIWrapper

NvAPIWrapper is a .Net wrapper for NVIDIA public API, capable of managing all aspects of a display setup using NVIDIA GPUs
GNU Lesser General Public License v3.0
313 stars 55 forks source link

Setting rotation for any display doesn't work #33

Closed ogulzarinlighten closed 4 years ago

ogulzarinlighten commented 4 years ago

Hi,

I have been using this API to write a small application to set the position, resolution and rotation of displays. It works perfectly fine when setting the position and resolution, BUT setting the rotation has no effect, all displays revert back to zero degrees as soon as the configuration is applied.

falahati commented 4 years ago

Can you share your code so I can take a look at it?

ogulzarinlighten commented 4 years ago

This is a console app, it read the display config, changes the rotation of each display to 90 degrees and then sets the config in the end, It works on one of the NVidia cards with two displays, but not on any other of my setups, although they have same version of driver and windows

` using System; using NvAPIWrapper; using NvAPIWrapper.Display;

namespace NVidiaApp { class Program { static void Main(string[] args) { NVIDIA.Initialize();

        PathInfo[] pathInfoArr = PathInfo.GetDisplaysConfig();

        foreach (PathInfo info in pathInfoArr)
        {
            Console.WriteLine($"{info.Position}");
            Console.WriteLine($"{info.Resolution}");
            Console.WriteLine($"{info.IsGDIPrimary}");

            foreach(PathTargetInfo target in info.TargetsInfo)
            {
                Console.WriteLine($"{target.Rotation}");
                target.Rotation = NvAPIWrapper.Native.Display.Rotate.Degree90;
            }

            Console.WriteLine("");
        }

        Console.WriteLine("-----------------------------------");

        foreach (PathInfo info in pathInfoArr)
        {
            Console.WriteLine($"{info.Position}");
            Console.WriteLine($"{info.Resolution}");
            Console.WriteLine($"{info.IsGDIPrimary}");

            foreach (PathTargetInfo target in info.TargetsInfo)
            {
                Console.WriteLine($"{target.Rotation}");
            }

            Console.WriteLine("");
        }

        PathInfo.SetDisplaysConfig(pathInfoArr, NvAPIWrapper.Native.Display.DisplayConfigFlags.None);

        Console.ReadLine();
    }
}

}`

ogulzarinlighten commented 4 years ago

One more thing, when i tried the same thing using c++ API, it works on all my setups

falahati commented 4 years ago

I will take a look at this. but in the meanwhile, why not using a more general-purpose library?

My WindowsDisplayAPI library should be able to do this easily and with all GPU vendors since its only dependency is Windows's APIs themselves.

The code would be similar, but for better results; use the display config API instead of legacy at the root of the library.

falahati commented 4 years ago

If you decided to go with WindowsDisplayAPI, the following is an example that I just wrote for someone who wants to do the same thing: https://github.com/falahati/WindowsDisplayAPI/issues/15

falahati commented 4 years ago

The same thing using this library is possible with the following code:

NVIDIA.Initialize();

var paths = NvAPIWrapper.Display.PathInfo.GetDisplaysConfig();
var originalPaths = paths.ToArray();

for (int i = 0; i < paths.Length; i++)
{
    var path = paths[i];

    if (path.IsGDIPrimary)
    {
        continue;
    }

    paths[i] = new PathInfo(
        path.Resolution,
        path.ColorFormat,
        path.TargetsInfo.Select(
            (t) => new PathTargetInfo(t.DisplayDevice) {Rotation = Rotate.Degree180}
        ).ToArray()
    );
}

NvAPIWrapper.Display.PathInfo.SetDisplaysConfig(paths, DisplayConfigFlags.DriverReloadAllowed);
Console.WriteLine("Press 'Enter' to revert back.");
Console.ReadLine();
NvAPIWrapper.Display.PathInfo.SetDisplaysConfig(originalPaths, DisplayConfigFlags.DriverReloadAllowed);
NVIDIA.Unload();

As you can see, the code is almost identical.