Recent

Author Topic: Graph unit - how to find all possible graphics resolutions (see edit #1)  (Read 491 times)

dculp

  • Jr. Member
  • **
  • Posts: 86
For a given display and graphics card, I want to determine all possible resolutions. I can do this with something like the following --

for gd:= D4bit to D16bit do
   begin
   getModeRange(gd,gm_lowest,gm_highest); { Get the available mode numbers for this driver }
   for gm:= gm_lowest to gm_highest do
      begin
      initgraph(gd,gm,'');
      XRes:= getmaxx; // requires initgraph
      YRes:= getmaxy; // requires initgraph
         {Then save these values somewhere before next loop}
      closegraph;
      end;
   end;

The problem is that each call to initgraph opens a graph window. This is unsightly.

Is there another way to find possible graphics resolutions without having to call initgraph or, alternately, is there a way to prevent these graphic windows from showing?

---------------------------
Edit #1. Ultimate purpose. After the application finds all of the available resolutions on the user's computer then it will choose the best one. For example, using the above (undesirable) method, one laptop shows resolutions of 640x480, 800x600, 1350x730, and 1366x664. However, the last two have significant horizontal distortion so that circles show up as ellipses. That would not be acceptable for this engineering application. Note that popular 1024x768 is missing, even though the laptop supports this resolution. Thus, on this laptop the best resolution would be 800x600. (A desktop computer shows that 1024x768 is available so that resolution would be best for that computer.)

Since the above method stores each of the found resolutions, it only needs to be used when the application starts. However, initgraph..closegraph must be called repeatedly in order to find each available resolution. This results in a series of flashing windows when the application starts. If there were a way to hide these windows or actually prevent them from displaying then that would also be an acceptable solution.
---------------------------

(Yes, I know that the graph unit is rather obsolete. However, I have thousands of lines of code that rely on the graph unit and upgrading these could easily turn into a swamp, especially just to implement this single change.)

Lazarus version 1.6.4
FPC version 3.0.2
For Windows 7+ only

Thanks,
Don C.

« Last Edit: December 07, 2018, 09:02:12 am by dculp »

lucamar

  • Sr. Member
  • ****
  • Posts: 496
Re: Graph unit - how to find all possible graphics resolutions
« Reply #1 on: December 06, 2018, 10:28:38 pm »
You could try extracting the info from the result of GetModeName()

Otherwise, if  your OS is plain DOS (or Windows 9x/Me) or similar and  your graphics card is VESA compliant (most are actually) you can try calling the VESA functions directly. Look into FPC Source/3.0.4/packages/graph/src to see what's available but undocumented.

Graph is quite obsolete by now; for a (relatively) pain-free alternative look for PTCGraph (look into FPC source/3.0.4/packages/ptc)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 1.8.4/FPC 3.0.4 on:
(K)Ubuntu 11..16, Windows XP SP3 (Home/Prof.) and various DOS incarnations.

dculp

  • Jr. Member
  • **
  • Posts: 86
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #2 on: December 07, 2018, 09:01:15 am »
Lucamar --

GetModeName doesn't address the basic problem of discovering the available graphic modes; it only returns a string for a selected standard mode. Also, it must be called after initgraph which opens a window and which I'm trying to avoid. (See my updated edit of my original post.)

Thanks for suggesting PTCgraph which I wasn't aware of. However, since the graph unit currently works well I wouldn't attempt an upgrade unless the graph unit fails in a future Windows OS.

Any additional suggestions would be appreciated.
« Last Edit: December 07, 2018, 09:07:32 am by dculp »

sash

  • Full Member
  • ***
  • Posts: 158
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #3 on: December 07, 2018, 10:44:44 am »
since the graph unit currently works well ...
Yet you have a problem.
Why?
Because graph unit (which I believe is being kept only for legacy means) and its approaches were deprecated decades ago.
Nowadays no one is setting screen resolution. It is done by the OS or user (at worst case). Applications are written to be capable to adapt to given environment (they scale or scroll output according to resolution, viewport size and dpi).

Any additional suggestions would be appreciated.
In addition to querying VESA, you could ask user to pick desired resolution (like it was back in old 80-90s) and introduce scale factor.
This could be done (semi)automatically (knowing physical screen/pixel geometry) or as a table of aspect ratios for each videomode.

Lazarus 1.8.4 Unversioned directory FPC 3.0.4 x86_64-linux-gtk2 -- Ubuntu 18.04 XFCE

Mr.Madguy

  • Sr. Member
  • ****
  • Posts: 390
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #4 on: December 07, 2018, 12:35:02 pm »
Don't use graph. It doesn't even support the most important feature, needed for animation - WaitForVSync.

See some crazy DOS stuff in attachment. That was my dream at some point - to make universal DOS/Windows program. Another thing - it was made on Win Mobile 5.0 smartphone via DOS emulator. Almost entirely. Only Windows driver was made via DosBox, cuz it was way too complex.

P.S. Picture.bmp is removed, as archive's size shouldn't exceed 250Kb.
« Last Edit: December 07, 2018, 12:47:40 pm by Mr.Madguy »
DynamicData 2.0 Released! Many optimizations: 15% smaller sources, 10% smaller code! Improved scalability!
Developing version 2.1.
Crazy unit testing

dculp

  • Jr. Member
  • **
  • Posts: 86
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #5 on: December 07, 2018, 12:52:06 pm »
For those who have kindly suggested that I abandon the graph unit, I have ~13000 lines of code devoted to the graph unit. Regardless of the long-term advantages of upgrading, I simply don't have the time or fortitude to do so (other projects take priority). If graph eventually becomes unuseable then I will make the effort. In the meantime I have to improvise as needed (hopefully with the much-appreciated help from this forum).

jamie

  • Hero Member
  • *****
  • Posts: 973
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #6 on: December 07, 2018, 11:31:20 pm »
You can use the "EnumDIsplaySettings"

As far as I know, it only works with windows.

But I am going to give you far warning, if you change the "DisplaySettings" for your graphic mode you
better be in full screen.

 if you are simply looking to obtain the current graphics resolution and depth then use "GetDeviceCaps" using the
DC handle.

Something for you to look at ;)

Mr.Madguy

  • Sr. Member
  • ****
  • Posts: 390
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #7 on: December 08, 2018, 08:55:10 am »
In short, if something isn't supported by library, then there is no magic solution of a problem, except:
1) Give up and migrate to another library
2) Add support of needed feature yourself
DynamicData 2.0 Released! Many optimizations: 15% smaller sources, 10% smaller code! Improved scalability!
Developing version 2.1.
Crazy unit testing

jamie

  • Hero Member
  • *****
  • Posts: 973
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #8 on: December 08, 2018, 04:49:12 pm »
The graph unit has a call "Graph.QueryAdapterInfo"

---
Var
 P :Graph.PModeInfo;
Begin
 P := Graph.QueryAdapterInfo;

 P^. …. contains all parameters of the first mode. this also includes the MaxX, MaxY etc..

 To move to the next one..
 P := p^.NextPModeInfo;

 and repeat until NIL pointer I guess.

This gives back info without initiating the adapter.
Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Classes, graph
  10.   { you can add units after this };
  11. Var
  12.   P:Graph.PModeInfo;
  13. begin
  14.   P  := Graph.queryadapterinfo;
  15.   While P <> Nil Do
  16.   Begin
  17.     WritelN(P^.ModeNumber,',', P^.ModeName,',', P^.MaxX,',', P^.MaxY);
  18.     P := P^.next;
  19.   end;
  20.  ReadLn;
  21. end.                                    
  22.  

Is this what you are looking for ?
« Last Edit: December 08, 2018, 04:57:46 pm by jamie »

dculp

  • Jr. Member
  • **
  • Posts: 86
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #9 on: December 10, 2018, 11:59:08 am »
Jamie --

This would seem to be what I need. The following is the output from my laptop (I added MaxColor) --

ModeNumber,   ModeName,   MaxX,   MaxY,   MaxColor
==> 2 , 640 x 480 x 16 Win , 639 , 479 , 16
0 , 640 x 200 x 16 Win , 639 , 199 , 16
1 , 640 x 350 x 16 Win , 639 , 349 , 16
256 , 640 x 400 x 256 Wi , 639 , 399 , 256
257 , 640 x 480 x 256 Wi , 639 , 479 , 256
==> 258 , 800 x 600 x 16 Win , 799 , 599 , 16
259 , 800 x 600 x 256 Wi , 799 , 599 , 256
240 , Largest Window x 1 , 1349 , 729 , 16
241 , Largest Window x 2 , 1349 , 729 , 256
245 , Maximized Window x , 1365 , 663 , 16
246 , Maximized Window x , 1365 , 663 , 256

To evaluate this I called initgraph(D4bit,2,'') which opens the expected (640 , 480) graph window.

However, if I call initgraph(D4bit,258,''), which should open the (800, 600) graph window, then  graphresult = -10 ("Invalid graphics mode for selected device'). (D4bit = driver 13 = 16 colors; graphh.inc)

For the 200 series modes above, I can't find any reference to these in graphh.inc. Is there a translation of these that initgraph will accept?

Note - I looked at P^.internModeNumber but this always returned 0.

Thanks.

dculp

  • Jr. Member
  • **
  • Posts: 86
Re: Graph unit - how to find all possible graphics resolutions (see edit #1)
« Reply #10 on: December 10, 2018, 03:04:58 pm »
I have found the problem. I was trying to use the predefined driver numbers from graphh.inc. However, you have to use the driver number that is extracted from Graph.queryadapterinfo for each ModeNumber (i.e., P^.DriverNumber & P^.ModeNumber). Then the results on my laptop are --

DriverNumber,   ModeNumber,   ModeName,   MaxX,   MaxY,   MaxColor
      9      2  640 x 480 x 16 Win    639    479     16
      9      0  640 x 200 x 16 Win    639    199     16
      9      1  640 x 350 x 16 Win    639    349     16
     10    256  640 x 400 x 256 Wi    639    399    256
     10    257  640 x 480 x 256 Wi    639    479    256
     10    258  800 x 600 x 16 Win    799    599     16 <==
     10    259  800 x 600 x 256 Wi    799    599    256
     10    240  Largest Window x 1   1349    729     16
     10    241  Largest Window x 2   1349    729    256 <==
     10    245  Maximized Window x   1365    663     16
     10    246  Maximized Window x   1365    663    256

For example, use initgraph(10,258,''); for 800 x 600 x 16 colors or initgraph(10,241,''); for 1350 x 730 x 256 colors.