diff --git a/common/hw-gfx-gma-pipe_setup.adb b/common/hw-gfx-gma-pipe_setup.adb index 321271c558..e2d2567d07 100644 --- a/common/hw-gfx-gma-pipe_setup.adb +++ b/common/hw-gfx-gma-pipe_setup.adb @@ -172,19 +172,16 @@ package body HW.GFX.GMA.Pipe_Setup is if Config.Has_Plane_Control then declare - Stride, Offset, GTT_Addr : Word32; + Stride, Offset : Word32; Width : constant Pos16 := Rotated_Width (FB); Height : constant Pos16 := Rotated_Height (FB); begin if Rotation_90 (FB) then Stride := Word32 (FB_Pitch (FB.V_Stride, FB)); Offset := Word32 (FB.V_Stride - FB.Height); - GTT_Addr := - FB.Offset + Word32 (GTT_Rotation_Offset) * GTT_Page_Size; else Stride := Word32 (FB_Pitch (FB.Stride, FB)); Offset := 0; - GTT_Addr := FB.Offset; end if; Registers.Write (Register => Controller.PLANE_CTL, @@ -197,7 +194,7 @@ package body HW.GFX.GMA.Pipe_Setup is Registers.Write (Controller.PLANE_SIZE, Encode (Width, Height)); Registers.Write (Controller.PLANE_STRIDE, Stride); Registers.Write (Controller.PLANE_POS, 16#0000_0000#); - Registers.Write (Controller.PLANE_SURF, GTT_Addr and 16#ffff_f000#); + Registers.Write (Controller.PLANE_SURF, FB.Offset and 16#ffff_f000#); end; else if Config.Disable_Trickle_Feed then diff --git a/common/hw-gfx-gma.adb b/common/hw-gfx-gma.adb index d6aa7cbdcc..6f4594b13c 100644 --- a/common/hw-gfx-gma.adb +++ b/common/hw-gfx-gma.adb @@ -473,22 +473,29 @@ is ---------------------------------------------------------------------------- function FB_First_Page (FB : Framebuffer_Type) return Natural is - (Natural (FB.Offset / GTT_Page_Size)); + (Natural (Phys_Offset (FB) / GTT_Page_Size)); function FB_Pages (FB : Framebuffer_Type) return Natural is (Natural (Div_Round_Up (FB_Size (FB), GTT_Page_Size))); function FB_Last_Page (FB : Framebuffer_Type) return Natural is (FB_First_Page (FB) + FB_Pages (FB) - 1); - -- Check basics and that it fits in GTT + -- Check basics and that it fits in GTT. For 90 degree rotations, + -- the Offset should be above GTT_Rotation_Offset. The latter will + -- be subtracted for the aperture mapping. function Valid_FB (FB : Framebuffer_Type) return Boolean is - (Valid_Stride (FB) and FB_Last_Page (FB) < GTT_Rotation_Offset); + (Valid_Stride (FB) and + FB_First_Page (FB) in GTT_Range and + FB_Last_Page (FB) in GTT_Range and + (not Rotation_90 (FB) or + (FB_Last_Page (FB) + GTT_Rotation_Offset in GTT_Range and + FB.Offset >= Word32 (GTT_Rotation_Offset) * GTT_Page_Size))); -- Also check that we don't overflow the GTT's 39-bit space -- (always true with a 32-bit base) function Valid_Phys_FB (FB : Framebuffer_Type; Phys_Base : Word32) return Boolean is (Valid_FB (FB) and - Int64 (Phys_Base) + Int64 (FB.Offset) + Int64 (FB_Size (FB)) <= + Int64 (Phys_Base) + Int64 (Phys_Offset (FB)) + Int64 (FB_Size (FB)) <= Int64 (GTT_Address_Type'Last)) with Ghost; @@ -507,7 +514,7 @@ is Pre => Is_Initialized and Valid_Phys_FB (FB, Phys_Base) is Phys_Addr : GTT_Address_Type := - GTT_Address_Type (Phys_Base) + GTT_Address_Type (FB.Offset); + GTT_Address_Type (Phys_Base) + GTT_Address_Type (Phys_Offset (FB)); begin for Idx in FB_First_Page (FB) .. FB_Last_Page (FB) loop Registers.Write_GTT @@ -524,7 +531,7 @@ is GTT_Address_Type (Pixel_To_Bytes (32 * FB.Stride, FB)); begin Phys_Addr := GTT_Address_Type (Phys_Base) + - GTT_Address_Type (FB.Offset) + + GTT_Address_Type (Phys_Offset (FB)) + GTT_Address_Type (FB_Size (FB)); for Page in FB_First_Page (FB) .. FB_Last_Page (FB) loop Phys_Addr := Phys_Addr - Bytes_Per_Row; @@ -629,7 +636,7 @@ is FB_Last_Page (FB) < GTT_Size / Config.GTT_PTE_Size and FB_Last_Page (FB) < Natural (Stolen_Size / GTT_Page_Size) and FB_Last_Page (FB) < Aperture_Size / GTT_Page_Size; - pragma Debug (not Valid, Debug.Put + pragma Debug (not Valid, Debug.Put_Line ("Stolen memory too small to hold framebuffer.")); end if; end Validate_FB; @@ -701,7 +708,7 @@ is if Linear_FB_Base /= 0 then Validate_FB (FB, Valid); if Valid then - Linear_FB := Linear_FB_Base + Word64 (FB.Offset); + Linear_FB := Linear_FB_Base + Word64 (Phys_Offset (FB)); end if; end if; end Map_Linear_FB; diff --git a/common/hw-gfx-gma.ads b/common/hw-gfx-gma.ads index fadf437ec6..77def8ea1c 100644 --- a/common/hw-gfx-gma.ads +++ b/common/hw-gfx-gma.ads @@ -102,6 +102,15 @@ is Device_Address : GTT_Address_Type; Valid : Boolean); + -- For the default framebuffer setup (see below) with 90 degree rotations, + -- we expect the offset which is used for the final scanout to be above + -- `GTT_Rotation_Offset`. So we can use `Offset - GTT_Rotation_Offset` for + -- the physical memory location and aperture mapping. + function Phys_Offset (FB : Framebuffer_Type) return Word32 is + (if Rotation_90 (FB) + then FB.Offset - Word32 (GTT_Rotation_Offset) * GTT_Page_Size + else FB.Offset); + procedure Setup_Default_FB (FB : in Framebuffer_Type; Clear : in Boolean := True; diff --git a/gfxtest/hw-gfx-gma-gfx_test.adb b/gfxtest/hw-gfx-gma-gfx_test.adb index 514e60fa87..cb09c63017 100644 --- a/gfxtest/hw-gfx-gma-gfx_test.adb +++ b/gfxtest/hw-gfx-gma-gfx_test.adb @@ -78,13 +78,16 @@ is 0 .. 3 * (Max_W * Max_H + FB_Align / 4) - 1; type Screen_Type is array (Screen_Index) of Word32; + function Screen_Offset (FB : Framebuffer_Type) return Natural is + (Natural (Phys_Offset (FB) / 4)); + package Screen is new MMIO_Range (0, Word32, Screen_Index, Screen_Type); Screen_Backup : Screen_Type; procedure Backup_Screen (FB : Framebuffer_Type) is - First : constant Screen_Index := Natural (FB.Offset) / 4; + First : constant Screen_Index := Screen_Offset (FB); Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1; begin for Idx in Screen_Index range First .. Last loop @@ -94,7 +97,7 @@ is procedure Restore_Screen (FB : Framebuffer_Type) is - First : constant Screen_Index := Natural (FB.Offset) / 4; + First : constant Screen_Index := Screen_Offset (FB); Last : constant Screen_Index := First + Natural (FB_Size (FB)) / 4 - 1; begin for Idx in Screen_Index range First .. Last loop @@ -158,7 +161,7 @@ is is P : Pixel_Type; -- We have pixel offset wheras the framebuffer has a byte offset - Offset_Y : Natural := Natural (Framebuffer.Offset / 4); + Offset_Y : Natural := Screen_Offset (Framebuffer); Offset : Natural; function Top_Test (X, Y : Natural) return Boolean @@ -214,7 +217,7 @@ is V_Stride => Div_Round_Up (Pos32 (Mode.H_Visible), 32) * 32, Tiling => Y_Tiled, Rotation => Rotation, - Offset => Offset); + Offset => Offset + Word32 (GTT_Rotation_Offset) * GTT_Page_Size); else FB := (Width => Width_Type (Mode.H_Visible),