blob: e7fb80c0f2779c62bfd3491d955a5be130c282e1 [file] [log] [blame]
Nico Huber1d0abe42017-03-05 14:14:09 +01001with System.Storage_Elements;
2with Ada.Command_Line;
3with Interfaces.C;
4
5with HW.File;
6with HW.Debug;
7with HW.GFX.GMA;
8with HW.GFX.GMA.Display_Probing;
9
10use HW;
11use HW.GFX;
12
13package body GFX_Test is
14
15 MMIO_Size : constant := 2 * 1024 * 1024;
16 subtype MMIO_Range is Natural range 0 .. MMIO_Size - 1;
17 subtype MMIO_Buffer is Buffer (MMIO_Range);
18 MMIO_Dummy : MMIO_Buffer
19 with
20 Alignment => 16#1000#,
21 Volatile;
22
23 type Pixel_Type is record
24 Red : Byte;
25 Green : Byte;
26 Blue : Byte;
27 Alpha : Byte;
28 end record;
29
30 for Pixel_Type use record
31 Blue at 0 range 0 .. 7;
32 Green at 1 range 0 .. 7;
33 Red at 2 range 0 .. 7;
34 Alpha at 3 range 0 .. 7;
35 end record;
36
37 Max_W : constant := 4096;
38 Max_H : constant := 2160;
39 FB_Align : constant := 16#0004_0000#;
40 type Screen_Type is
41 array (0 .. 3 * (Max_W * Max_H + FB_Align / 4) - 1) of Pixel_Type;
42
43 Screen : Screen_Type
44 with
45 Alignment => 16#1000#,
46 Volatile;
47
48 Pipes : GMA.Pipe_Configs;
49
50 function Fill
51 (X, Y : Natural;
52 Framebuffer : Framebuffer_Type;
53 Pipe : GMA.Pipe_Index)
54 return Pixel_Type
55 is
56 use type HW.Byte;
57
58 Xp : constant Natural := X * 256 / Natural (Framebuffer.Width);
59 Yp : constant Natural := Y * 256 / Natural (Framebuffer.Height);
60 Xn : constant Natural := 255 - Xp;
61 Yn : constant Natural := 255 - Yp;
62
63 function Map (X, Y : Natural) return Byte is
64 begin
65 return Byte (X * Y / 255);
66 end Map;
67 begin
68 return
69 (case Pipe is
70 when GMA.Primary => (Map (Xn, Yn), Map (Xp, Yn), Map (Xp, Yp), 255),
71 when GMA.Secondary => (Map (Xn, Yp), Map (Xn, Yn), Map (Xp, Yn), 255),
72 when GMA.Tertiary => (Map (Xp, Yp), Map (Xn, Yp), Map (Xn, Yn), 255));
73 end Fill;
74
75 procedure Test_Screen
76 (Framebuffer : Framebuffer_Type;
77 Pipe : GMA.Pipe_Index)
78 is
79 use type HW.Word32;
80 P : Pixel_Type;
81 -- We have pixel offset wheras the framebuffer has a byte offset
82 Offset_Y : Natural := Natural (Framebuffer.Offset / 4);
83 Offset : Natural;
84 begin
85 for Y in 0 .. Natural (Framebuffer.Height) - 1 loop
86 Offset := Offset_Y;
87 for X in 0 .. Natural (Framebuffer.Width) - 1 loop
88 if Y mod 16 = 0 or X mod 16 = 0 then
89 P := (0, 0, 0, 0);
90 else
91 P := Fill (X, Y, Framebuffer, Pipe);
92 end if;
93 Screen (Offset) := P;
94 Offset := Offset + 1;
95 end loop;
96 Offset_Y := Offset_Y + Natural (Framebuffer.Stride);
97 end loop;
98 end Test_Screen;
99
100 procedure Calc_Framebuffer
101 (FB : out Framebuffer_Type;
102 Mode : in Mode_Type;
103 Offset : in out Word32)
104 is
105 use type HW.Int32;
106 use type HW.Word32;
107 begin
108 Offset := (Offset + FB_Align - 1) and not (FB_Align - 1);
109 FB :=
110 (Width => Width_Type (Mode.H_Visible),
111 Height => Height_Type (Mode.V_Visible),
112 BPC => 8,
113 Stride => Width_Type ((Word32 (Mode.H_Visible) + 15) and not 15),
114 Offset => Offset);
115 Offset := Offset + Word32 (FB.Stride * FB.Height * 4);
116 end Calc_Framebuffer;
117
118 procedure Prepare_Configs
119 is
120 use type HW.GFX.GMA.Port_Type;
121
122 Offset : HW.Word32 := 0;
123 begin
124 GMA.Display_Probing.Scan_Ports (Pipes);
125
126 for Pipe in GMA.Pipe_Index loop
127 if Pipes (Pipe).Port /= GMA.Disabled then
128 Calc_Framebuffer
129 (FB => Pipes (Pipe).Framebuffer,
130 Mode => Pipes (Pipe).Mode,
131 Offset => Offset);
132 end if;
133 end loop;
134
135 GMA.Dump_Configs (Pipes);
136 end Prepare_Configs;
137
138 procedure Print_Usage is
139 begin
140 Debug.Put_Line
141 ("Usage: " & Ada.Command_Line.Command_Name & " <sysfs-pci-path>");
142 Debug.New_Line;
143 end Print_Usage;
144
145 procedure Main
146 is
147 use System.Storage_Elements;
148
149 use type HW.GFX.GMA.Port_Type;
150 use type Interfaces.C.int;
151
152 MMIO_Mapped,
153 Screen_Mapped,
154 Initialized : Boolean;
155
156 function iopl (level : Interfaces.C.int) return Interfaces.C.int;
157 pragma Import (C, iopl, "iopl");
158 begin
159 if Ada.Command_Line.Argument_Count /= 1 then
160 Print_Usage;
161 return;
162 end if;
163
164 if iopl (3) /= 0 then
165 Debug.Put_Line ("Failed to change i/o privilege level.");
166 return;
167 end if;
168
169 File.Map
170 (Path => Ada.Command_Line.Argument (1) & "/resource0",
171 Addr => Word64 (To_Integer (MMIO_Dummy'Address)),
172 Len => MMIO_Dummy'Size / 8,
173 Readable => True,
174 Writable => True,
175 Success => MMIO_Mapped);
176 if not MMIO_Mapped then
177 Debug.Put_Line
178 ("Failed to map '" & Ada.Command_Line.Argument (1) & "/resource0'.");
179 return;
180 end if;
181
182 File.Map
183 (Path => Ada.Command_Line.Argument (1) & "/resource2",
184 Addr => Word64 (To_Integer (Screen'Address)),
185 Len => Screen'Size / 8,
186 Readable => True,
187 Writable => True,
188 Success => Screen_Mapped);
189 if not Screen_Mapped then
190 Debug.Put_Line
191 ("Failed to map '" & Ada.Command_Line.Argument (1) & "/resource2'.");
192 return;
193 end if;
194
195 GMA.Initialize
196 (MMIO_Base => Word64 (To_Integer (MMIO_Dummy'Address)),
197 Clean_State => True,
198 Success => Initialized);
199
200 if Initialized then
201 Prepare_Configs;
202
203 GMA.Update_Outputs (Pipes);
204
205 for Pipe in GMA.Pipe_Index loop
206 if Pipes (Pipe).Port /= GMA.Disabled then
207 Test_Screen
208 (Framebuffer => Pipes (Pipe).Framebuffer,
209 Pipe => Pipe);
210 end if;
211 end loop;
212 end if;
213 end Main;
214
215end GFX_Test;