Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New RGB/YUV pcb + screencap fix + scaling improvements #115

Merged
merged 16 commits into from
Dec 8, 2019

Conversation

IanSB
Copy link
Collaborator

@IanSB IanSB commented Dec 8, 2019

Final issue 2 pcb layout for universal RGB/YUV board
Fix screen cap issues in 4bpp mode
Fix scaling issues with screen caps
Add automatic small overscan to Pi's frame buffer when scaling fraction is not an exact multiple of the screen resolution
e.g. ORIC 1 scales 3x horizontal so buffer is 533 pixels. On a 1600x1200 monitor this is 1599 pixels so 1 pixel overscan is added to ensure all pixels are 3x. (Without this 1 pixel ends up wider)
Add new mode 7 horizontal integer scaling option: Mode7 Scaling: 4:3 (Uneven)/Even
This only affects integer scaling. The default is 4:3 (Uneven) which scales mode 7 to a 4:3 ratio but pixels are actually uneven as every 4th pixel is wider so the image can look a little ragged without interpolation (although it's a regular unevennes so not too noticeable). This was previously the only option. The new option "Even" allows even Integer scaling in mode 7 so all pixels are equal.
In 1600x1200 and 1080p monitors this results in a slightly wider image but results may vary in other resolutions.

@hoglet67 hoglet67 merged commit 54f4b28 into hoglet67:dev Dec 8, 2019
@hoglet67
Copy link
Owner

hoglet67 commented Dec 8, 2019

Ian,

I've merged that, but I'm seeing slightly wierd results with the new Mode 7 Even scaling mode.

My monitor resolution is 1600x1200 and Scaling is set to Integer/Sharp.

If I select Mode7 Scaling: 4:3 (Uneven), and then cycle through the different overscan values, then everything behaves as I would expect, i.e. Minimum gives the smallest display, Maximum the largest display, Half-way is inbetween, and Auto looks the same as maxiumum, and everything is centred.

If I then select Mode 7 Scaling: Even, and again cycle through the different overscan values, then I get gives some very wierd results, and auto in particular results in a slightly cropped / offset screen:
capture5

Also, you frequently see menu re-draw artifacts, with bits of menu not being erased.

I don't see this at 1920x1080, so I expected something is possibly going negative when the resolution is 1600x1200.

Stepping back, there are now a large number of parameters that seem to interact (to me anyway) in unexpected ways. We have:

  • Resolution
  • Scaling (Integer / Fill 4:3 / Fill All)
  • Mode 7 Scaling (4:3 Uneven / Even)
  • Overscan (Min / Halfway / Max / Auto)
  • Geometry Min Width / Height
  • Geomerty Max Width / Heigth
  • FB Size (Normal / Double Width / Double Height / Double Width + Height)

If I had to expain to someone why we now have all of these, I would fail miserably. In fact, I actually started to try to document this today, and after a couple of hours gave up!

(I'm especially confused as to why the implementation now needs to make use of the Pi Overscan property. This is something I have stayed away from in the past, because it's badly documented and completely counter intuitive in how it works. It also works differently with different firmware versions. I'm sure there's a good reason for using it.)

One thing that would help me tremendously would be an accurate writeup of how the scaling now works. This also needs to be part of the documentation for anyone trying to add a new machine.

Dave

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

If I then select Mode 7 Scaling: Even, and again cycle through the different overscan values, then I get gives some very wierd results, and auto in particular results in a slightly cropped / offset screen

I think the offset was fixed with a profile tweak - did you update your profiles?
However, there is something wrong with the overscan setting and I can fix that but it may be better to eliminate the overscan option altogether for integer scaling as it isn't very intuitive or useful.
In integer scaling mode, the overscan option doesn't change the size of the image, it changes the size of the capture area (The menu is written to the capture area so you can see the menu move when you change the setting)
The option was useful for setting up max and min sizes but they now have their own special setup modes to assist with that.
The overscan setting is useful in Fill4:3 and Fill All modes as it changes the size of the image on screen because the capture area is zoomed to fill the whole screen.
Pehaps a better option would be to change the setting to "Fill Overscan" with options of Maximum, Half Way and Minimum and ignore the setting altogether in Integer mode (i.e. always equivalent to Auto).

What do you think?

I'm especially confused as to why the implementation now needs to make use of the Pi Overscan property.

This was to fix an integer scaling bug which I only just noticed.
As mentioned if the integer scale factor doesn't exactly divide into the screen area then you get some pixels at odd sizes.
e.g. The beeb uses 2x or 4x scale factors which divide into 1920x1080 or 1600x1200 with no remainder. The oric uses a 3x horizontal scale factor which divides into 1920 OK (=640) but doesn't divide into 1600 (=533 with remainder of 1) when the pi scales 533 to 1600 with no interpolation, one of the Oric pixels is represented by 4 lcd pixels instead of 3 to make up the full 1600 size.
Setting the Pi overscan to 1 pixel in this case so the screen area is 1599x1200 makes up the difference and ensures all Oric pixels are 3x lcd pixels. The Pi overscan settings will normally be 0 and only be a few pixels in either direction in rare circumstances to "soak up" any remainder in integer scaling.

This is something I have stayed away from in the past, because it's badly documented and completely counter intuitive in how it works.

Not heard of that, can you elaborate. You were using the overscan setting in the config file in the original software to get the scaling correct in exactly the same way.

One thing that would help me tremendously would be an accurate writeup of how the scaling now works. This also needs to be part of the documentation for anyone trying to add a new machine.

I'll try to get something written up soon.
BTW how do you upload images to the Wiki

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

I think the offset was fixed with a profile tweak - did you update your profiles?

Yes, I did a release build, then:

cp -a releases/RGBtoHDMI_20191208_54f4b28/* /media/dmb/RGBTOHDMI/

I'm still able to replicate that now, on a 1600x1200 monitor.

Pehaps a better option would be to change the setting to "Fill Overscan" with options of Maximum, Half Way and Minimum and ignore the setting altogether in Integer mode (i.e. always equivalent to Auto).

What do you think?

From a UI design perspective, it's consider bad form to give the user choices that don't have an effect. So generally I would try to avoid settings that have no effects in certain modes. If we need to do this, I wonder if we should find a way to "grey out" a setting, then it's much clearer that it's not applicable.

I've just done a bit more testing, of a Beeb at both 1920x1080 and 1600x1200, in both Mode 7 and Mode 0, with a red border colour set.

Fill All @ 1600x1200: working as expected
Fill 4:3 @ 1600x1200: working as expected
Fill All @ 1920x1080: working as expected

  • The capture area exactly fills the screen, i.e. you never see the red border
  • Overscan min/halfway/max progressively increases the size of the capture area
  • Overscan = Auto is the same as Overscan = Max
  • M7 Scaling is ignored

Fill 4:3 @ 1920x1080: working almost as expected:

  • The capture area fills the centre 4:3 section of the screen, i.e. you just have left/right red borders
  • but the width of the red borders changes very slightly as you vary overscan (why?)

Integer @ 1600x1200: working almost as expected:

  • The capture area is always centrered
  • Overscan min/halfway/max progressively increases the size of the capture area, so you progressively see more black captured border, and less red border. The actual captured content stays in a fixed place.
  • Overscan = Auto is the same as Overscan = Max
  • M7 Scaling is ignored in Mode 0, and widens the image in Mode 7
  • the only anomoly is the menu repaint bug when M7 Scaling = Even and you change the overscan

Integer @ 1920x1080: this is where I'm seeing unintuitive results:

Min:
capture12
Half way:
capture13
Max:
capture14
Auto:
capture15

I think what I wasn't expecting here is that in some cases the aspect ratio is severly distorted, because different H and V scale factors are allowed:

  • min: 2x horizontal, 2x vertical
  • half way: 2x horizontal, 1x vertical
  • max: 2x horizontal, 1x vertical

I thought we were trying to preserve the aspect ratio in Integer scaling mode?

So returning to your original point:

Pehaps a better option would be to change the setting to "Fill Overscan" with options of Maximum, Half Way and Minimum and ignore the setting altogether in Integer mode (i.e. always equivalent to Auto).

What do you think?

My worry then is there may be some cases where the capture border is then lost. For example:

  • an Atom with a min capture area of 256x192
  • displayed on a monitor that is 1024x768

By only having the Auto option, I think the system would then eliminate the capture borders completely. Or am I wrong in that?

It seems how much of the original border is captured is a choice we should give the user in all scaling modes, then we just have to do our best to work with that. That's especially true in systems where software could set the border colour, or where it contains "content" like tape loading information.

This was to fix an integer scaling bug which I only just noticed.

OK, I understand now. I had missed the fact that it was:

  • only ever a few pixels
  • only ever used in integer scaling mode

Not heard of that, can you elaborate. You were using the overscan setting in the config file in the original software to get the scaling correct in exactly the same way.

See the comments here:

# Currently the RGBtoHDMI frame buffer is 672x540

The values seem to be applied relative to a default, which is 32 or 48 depending on the mode.

Our config file has disable_overscan=1, so it's possible you setting are being ignored. Or it's possible this just applies to the interpretation of the properties.

I don't know if the same is true when setting the overscan through the API, but is suspect it may be.

See what I mean about it being confusing?

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

Ian,

OK, so refreshing my memory a bit more regarding this property:

disable_overscan=1

This has the effect of removing the default overscan value (32 or 48) so that system uses the absolute values that are specified (which musg be positive).

However, see also this recent firmware change:
raspberrypi/linux#3059 (comment)

Which I think means that overcan is never applied in DMT modes, only in CEA modes. Ouch!

Dave

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

Integer @ 1920x1080: this is where I'm seeing unintuitive results:
I thought we were trying to preserve the aspect ratio in Integer scaling mode?

It isn't always obvious what is 4:3 as NTSC derived sources like CGA have a pixel size of 640x200 which should be scaled to 4:3 (Hx2, Vx5) while PAL sources that are also ~640x200 (i.e. everything except BBC) should be letterboxed to resemble their original screen (Hx2, Vx4). The Oric is even worse as it's 12Mhz pixel clock means very non square pixels (like mode 7) so maintaining a consistent scaling relationship is problematic and I found it very difficult to enforce a consistent aspect ratio for all possible permutations of geometry and screen size in integer scaling so the integer scaling acts independently on X and Y and the choice of geometry settings is used to provide an aspect ratio hint. The unintuitive results mentioned above are currently the expected behaviour as you are overriding the auto settings which try to match the geometry sample area to the screen size.

Our config file has disable_overscan=1, so it's possible you setting are being ignored. Or it's possible this just applies to the interpretation of the properties.

The setting definitely has an effect:

Here is the Oric output with no Pi overscan. Note the bottom pixel of the rightmost /
before

And after with the overscan property adding 1 pixel of horizontal overscan:
after

(Can't use screengrabs as this is a scaling issue so source framebuffer is the same in both cases)

I wonder if we should find a way to "grey out" a setting, then it's much clearer that it's not applicable.

Hiding or greying out options would be useful.
Also I think we will need a sub-menu in the sampling menu as the new analog board will have 8 settings for DACs and that's going to overflow the screen.

I'll fix the current issue with mode 7 even overscan settings and look into the other anomalies mentioned above

EDIT:

Note in the above Half Way and Max screen grabs, the only other option for integer scaling would be to go from 2x to 1x horizontal scaling so the images would be very narrow.
i.e. there is no good looking integer scaling solution for those Max or Half Way source resolutions.

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

It isn't always obvious what is 4:3 as NTSC derived sources like CGA have a pixel size of 640x200 which should be scaled to 4:3 (Hx2, Vx5) while PAL sources that are also ~640x200 (i.e. everything except BBC) should be letterboxed to resemble their orginal screen (Hx2, Vx4).

Yes, I can see how doing this automatically in all cases is impossible.

I have a couple of related questions:

  1. I wonder if the profile should allow the source pixel aspect ratio to be specified? That would help with the cases you give above.

  2. We currently assume the display pixel aspect ratio is always 1:1. While this is generally true, I think there are some examples of displays with non-square pixels. For example, I believe you can can 800x480 displays that are 16:9 (so the pixels are 15:16). I think I have also seem 1024x768 screens that are 16:9.

Technically, I think the Beeb pixel aspect ratio is actually 14.75/16, see:
https://stardot.org.uk/forums/viewtopic.php?p=124361#p124361

See also the end of this post, which also ends up at 14.75/16
https://stardot.org.uk/forums/viewtopic.php?p=166089#p166089

Also, thinking off the cuff here, is there case for a fill mode that perserves the aspect original ratio? Both the fill modes we have at the moment will can distort the image.

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

Technically, I think the Beeb pixel aspect ratio is actually 14.75/16

Yes that's correct, square pixels as used on the Prisma 2/3 require a 14.769231 Mhz pixel clock:
Square pixels in 4:3 means a resolution of 768*576 (2 x 288) which means 768 clock cycles in the active line period of 52uS.
The beeb's 16 Mhz clock means it outputs 832 clock cycles in 52uS so a full overscan screen would be 832x288 but I've limited the capture to 768 as we are distorting to true square pixels.

Interestingly those computers that use an NTSC crystal related pixel clock (i.e. 14.31818 etc) are much closer to producing square pixels on a PAL screen than the beebs 16Mhz clock.

I wonder if the profile should allow the source pixel aspect ratio to be specified?

It already is albeit in a non-obvious way:
In the fill modes the max setting is stretched to 4:3 so by changing the Max values you change the aspect ratio.

Also, thinking off the cuff here, is there case for a fill mode that perserves the aspect original ratio? Both the fill modes we have at the moment will can distort the image.

Using the above info, if you change the max values on a BBC profile to 832x288 instead of 768x288, you will get exactly the correct BBC aspect ratio in the Fill modes.

For example, I believe you can can 800x480 displays that are 16:9 (so the pixels are 15:16).

Not heard of that before, all the panels I've seen in that past have had square pixels. I can imagine that would cause a lot of problems with systems that assume square pixels.

However, see also this recent firmware change:
Which I think means that overcan is never applied in DMT modes, only in CEA modes. Ouch!

Is there a build of that firmware available to see if it breaks my above Oric scaling fix?

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

Is there a build of that firmware available to see if it breaks my above Oric scaling fix?

I would try the latest from here:
https://github.com/raspberrypi/firmware/tree/master/boot

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

I would try the latest from here:

The overscan property setting still works with this version.

Actually I found that the fix above wasn't quite right in that there were 2 oversized pixels and the fix removed just one. Increasing the Pi overscan by 1 so 2 pixels (L=1, R=1) got rid of the second oversized pixel so I guess there is some rounding issue in the scaler hardware.
I'm not sure if that means the general rule is the value should be +1 or rounded up to an even number or possibly doubled (For now it rounds up to an even number).

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

It's possible the recent firmware change people were talking about was this one:
raspberrypi/firmware#1173

In which case we are fine.

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

I did some further tests with the overscan value using different sized buffers and it seems that the correct value is always the calculated value +1 (if non-zero), not rounded up to an even number.

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

Integer @ 1920x1080: this is where I'm seeing unintuitive results:

Here is a more detailed explanation of why the Min/Halfway/Max/Auto are the way they are in your screen grabs above:

Geometry min is 640x256
Geometry max is 768x288
A 1080p monitor normally has 4:3 resolution of 1440x1080 but I have increased the usable width to 1600x1080 so it can better handle the full overscan Amstrad modes.

Min:
This selects the minimum size which is 640x256 as the capture area.
this can be scaled Hx2 Vx4 for 1280x1024 to fit in the above 1600x1080 area so you get a good aspect ratio but with no additional capture area around it to cope with slight misalignment

In Half way, the capture area is 704x272 the H will still scale 2x to 1408 but the V won't scale 4x as that would be 1088 so it has to choose 3x which is 816 so it looks a bit letterboxed. There is no good solution to integer scale that capture area to a 1080p monitor

In Max, the capture area is 768x288. H will scale 2x to 1536 and V will scale 3x to 864 so again no good solution for a 4:3 aspect ratio.

In Auto the software looks at the min and max values and picks the an intermediate value with the highest x and y scale factors that exactly fits into the monitor's resolution which in this case is 768x270 which scales Hx2 and Vx4 to 1536x1080 so you get a good 4:3 solution.

Note the halfway and max values will scale properly to 1600x1200 which is why it looks better on that monitor.

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

A 1080p monitor normally has 4:3 resolution of 1440x1080 but I have increased the usable width to 1600x1080 so it can better handle the full overscan Amstrad modes.

Where in the code is that expansion to 1600x1080 done?

In Max, the capture area is 768x288. H will scale 2x to 1536 and V will scale 3x to 864 so again no good solution for a 4:3 aspect ratio.

This (perhaps not surprisingly) is very like the manual calculations I would do in the early versions of RGBtoHDMI. The key difference being that I would never scale H and V differently. i.e. I would prioritise maintaining the aspect ratio over reducing the bars.

I think that's mostly what I'm reacting too here, as I find aspect ratio distortion far more objectionable than black bars.

Another area of confusion for me in the above calculation is at what point double height comes in to play. i.e. the capture area is 768x288, but the FB Size is double height. Isn't that the same as saying the capture area is 768x576, in which case I'm not sure what happens to the vertical scale factor. Does it end up as 1.5, and this is still integer (2 pixels -> 3 pixels, but those 2 pixels are identical)?

Dave

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

Where in the code is that expansion to 1600x1080 done?

This line in geometry.c -
h_size43 = (h_size43 * 800) / 720; //adjust 4:3 ratio on widescreen resolutions to account for up to 800 pixel wide integer sample capture

I would prioritise maintaining the aspect ratio over reducing the bars.

You would end up with a postage stamp image with scaling Hx1 and Vx2

I would never scale H and V differently

H and V are almost always scaled differently though e.g. beeb Hx2 and Vx4, CGA Hx2 and Vx5. Currently the scaler doesn't inherently "know" that those values are equal so maybe some helper info is needed in the geometry settings.

what point double height comes in to play

Double height is mostly ignored during scaler calculations. This actually results in more flexible scaling.
In the case of the beeb with double height on, it still comes out with Hx2 and Vx4 although the buffer is now double size. This can result in alternate vertical or horizontal pixels being scaled differently for some resolutions. In the beeb case Vx4 would still result in Vx2 for alternate vertical pixels so no difference but in the case of CGA x5 scaling results in x2 and x3 for alternate lines but as they are both the same pixel value it isn't noticeable at all unless you enable scanlines which blanks alternate lines.

@hoglet67
Copy link
Owner

hoglet67 commented Dec 9, 2019

Thanks for the info Ian. I appreciate there is no right answer here.

It will be interesting to see what happens when we put out a public beta.

I know at least one user of the Atom interface (Ken Lowe) has some pretty unusual monitor resolutions:

  • Philips Brilliance 200W - 1680 x 1050 (16 x 10)
  • Dell 2009Wt - 1680 x 1050 (16 x 10)
  • Dell 1908WFPf - 1440 x 900 (16 x 10)
  • Dell 2007FP - 1600 x 1200 (4 x 3)

https://stardot.org.uk/forums/viewtopic.php?f=3&t=14430&p=208720

So, taking 1680 x 1050, the usable area is 1400x1050 (I don't think your expansion rule applies to max_width of 320).

The Atom's capture area is defined as 272x208 => 320x240

So that should allow 5x in X and Y, with auto ending up using something like 280x210, so quite close to min.

I might try this one out myself, as I think I have a suitable monitor in the loft.

Dave

@IanSB
Copy link
Collaborator Author

IanSB commented Dec 9, 2019

Thinking about it, the geometry helper info required is not the screen aspect ratio but the pixel aspect ratio which would be 1:2 for a beeb, 2:5 for cga 1:1 for atom etc.
With that info I could always adjust the X and Y scaling to meet that ratio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants