How to set framebuffer properties flags

Anything and everything about programming graphics with Ultibo
Poi
Posts: 29
Joined: Mon Jan 07, 2019 11:57 pm

How to set framebuffer properties flags

Postby Poi » Tue Feb 19, 2019 11:57 pm

How do you set the FramebufferProperties.Flags property?

I know it has something to do with bitwise xor and those constants defined in framebuffer.pas, but I was never too comfortable with bitwise operations :P

I have been doing some digging around and found out in the comments that those values are ignored if you are using FramebufferDeviceAllocate or FramebufferDeviceSetProperties to set up your framebuffer device, so that is adding a little bit to the confussion.

The flag I am interested in is FRAMEBUFFER_FLAG_SWAP. I want to toggle it off.

I want to do that because I have been doing some fancy rectangle drawings, but I can't get the colors quite right. The device is reporting an order
of FRAMEBUFFER_ORDER_RGB and a color format of COLOR_FORMAT_RGB16 (which the comments suggest is RGB565)

Knowing that, I try to build a color and draw the rectangle, like so.

Code: Select all

color := ((31 shl 11) or (0 shl 5) or 0)

FramebufferDeviceFillRect(FramebufferDevice, 10, 10, 20 ,20 , color, FRAMEBUFFER_TRANSFER_DMA);


I expected that to draw a red rectangle, but instead it ends up being blue.

The insteresting thing is that If I add a SwapEndian, the rectangle is red, like I expect it to be.

Code: Select all

color := SwapEndian((31 shl 11) or (0 shl 5) or 0)

FramebufferDeviceFillRect(FramebufferDevice, 10, 10, 20 ,20 , color, FRAMEBUFFER_TRANSFER_DMA);


Bellow is the full program

Code: Select all

program test;

{$mode delphi}{$H+}

uses
   RaspberryPi,
   GlobalConfig,
   GlobalConst,
   GlobalTypes,
   Platform,
   Threads,
   SysUtils,
   Classes,
   Ultibo,
   Devices,
   Framebuffer,
   Console,

   FileSystem,
   FATFS,
   MMC,
   BCM2708,

   PiTFT35;

var
   FramebufferDevice:PFramebufferDevice;
   FramebufferProperties:TFramebufferProperties;

begin
   FramebufferDevice:=FramebufferDeviceFindByDescription('Adafruit PiTFT 3.5" LCD');

   FramebufferDeviceGetProperties(FramebufferDevice, @FramebufferProperties);

   FramebufferDeviceRelease(FramebufferDevice);

   Sleep(1000);

   FramebufferProperties.Depth := FRAMEBUFFER_DEPTH_16;
   FramebufferProperties.Rotation := FRAMEBUFFER_ROTATION_270;
   FramebufferProperties.Order := FRAMEBUFFER_ORDER_RGB;
   FramebufferProperties.VirtualWidth := FramebufferProperties.PhysicalWidth;
   FramebufferProperties.VirtualHeight := FramebufferProperties.PhysicalHeight;

   FramebufferDeviceAllocate(FramebufferDevice, @FramebufferProperties);

   Sleep(1000);
   
   // should be red but is blue
   FramebufferDeviceFillRect(FramebufferDevice, 10, 10, 20 ,20 , Word ((31 shl 11) or (0 shl 5) or 0), FRAMEBUFFER_TRANSFER_DMA);
   // should be green but is red
   FramebufferDeviceFillRect(FramebufferDevice, 20, 20, 20 ,20 , Word ((0 shl 11) or (63 shl 5) or 0), FRAMEBUFFER_TRANSFER_DMA);
   // should be blue, but is green
   FramebufferDeviceFillRect(FramebufferDevice, 30, 30, 20 ,20 , Word ((0 shl 11) or (0 shl 5) or 31), FRAMEBUFFER_TRANSFER_DMA); // green

   ThreadHalt(0);
end.



I am thinking that the FRAMEBUFFER_FLAG_SWAP flag is turned on by default, but I am not quite sure if I am reading the FramebufferProperties.Flags value correctly, because again, I am not super confortable with bitwise operation and I might be doing the reading wrong.

I am trying this on a Pi Zero.

Hope somebody can help.
pik33
Posts: 857
Joined: Fri Sep 30, 2016 6:30 pm
Location: Poland
Contact:

Re: How to set framebuffer properties flags

Postby pik33 » Wed Feb 20, 2019 4:55 am

I tried to enable alpha channel in Ultibo fb and nothing worked until I added proper lines to config.txt.

viewtopic.php?f=10&t=1248
User avatar
Ultibo
Site Admin
Posts: 2208
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: How to set framebuffer properties flags

Postby Ultibo » Wed Feb 20, 2019 9:41 am

Poi wrote:How do you set the FramebufferProperties.Flags property

The Flags property in the FramebufferProperties tells you what features and options the framebuffer device supports, it isn't intended to be changed by software because the driver for the specific device sets the flags when it loads to report what it is capable of.

Poi wrote:The flag I am interested in is FRAMEBUFFER_FLAG_SWAP. I want to toggle it off.

The FRAMEBUFFER_FLAG_SWAP value says that the hardware behind the framebuffer needs the bytes to be in the opposite order to what would be normal for the platform.

In the case of the Adafruit PiTFT 3.5" LCD which uses the HX8357D TFT LCD driver chip the device expects the data sent to its memory to be in big endian order, because the ARM is a little endian processor then the bytes need to be reversed when written to the framebuffer memory so that the SPI transfer will send them correctly.

Poi wrote:I am thinking that the FRAMEBUFFER_FLAG_SWAP flag is turned on by default, but I am not quite sure if I am reading the FramebufferProperties.Flags value correctly, because again, I am not super confortable with bitwise operation and I might be doing the reading wrong.

If you look at the HX8357DFramebufferCreate() function in the hx8357d unit you will see it sets the FRAMEBUFFER_FLAG_SWAP flag by default unless the CPU target is big endian (nothing that is currently supported by Ultibo) but without ever thinking about where the flag is set you can rely on the Flags value of the framebuffer properties to tell you what the device expects.

You can test for the FRAMEBUFFER_FLAG_SWAP flag like this:

Code: Select all

var
  IsSwap: Boolean;
 
 begin
    IsSwap := (FramebufferProperties.Flags and FRAMEBUFFER_FLAG_SWAP) <> 0;
 

There are a few ways you can deal with this in your own code, if you are using the framebuffer raw and not relying on most of the console support you could simply check for the FRAMEBUFFER_FLAG_SWAP flag before allocating your framebuffer and if it is set then specify FRAMEBUFFER_ORDER_BGR instead.

Alternatively you can see how the framebuffer and console API deal with it by looking at those units in Ultibo, for example the FramebufferDeviceSetCursor() function checks it when converting the passed image into the format required for the framebuffer.

You will also see that we have a number of functions in the GlobalConfig unit such as PixelsDefaultToFormat, ColorDefaultToFormat etc which know how to convert between all the different formats, you can probably take information from them on how to pack and unpack the pixels for your output.

Hope that makes sense.
Ultibo.org | Make something amazing
https://ultibo.org
Poi
Posts: 29
Joined: Mon Jan 07, 2019 11:57 pm

Re: How to set framebuffer properties flags

Postby Poi » Wed Feb 20, 2019 10:11 am

Oooohhhhhh, so you don't set the flags, you can only get them. Got it! :)

Yeah, everything makes sense, I am just trying to find the most elegant path to set a color. Converting everything on my side using SwapEndian, while effective, seemed wrong.

Thanks for the clarification.
User avatar
Ultibo
Site Admin
Posts: 2208
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: How to set framebuffer properties flags

Postby Ultibo » Wed Feb 20, 2019 11:13 pm

Poi wrote:Converting everything on my side using SwapEndian, while effective, seemed wrong.

It's one of those tricky things with designing an API, where possible it should be high level enough to handle the details internally but some APIs have to be low level enough to accommodate all of the possible variations of hardware available.

Where you are creating your own drawing routines and utilizing the framebuffer directly then you also have to make sure you deal with these sorts of details, in comparison something like the console or graphics console API handles all the details of color format, order, caching, DMA support etc etc and doesn't require the caller to think about any of that.
Ultibo.org | Make something amazing
https://ultibo.org
Poi
Posts: 29
Joined: Mon Jan 07, 2019 11:57 pm

Re: How to set framebuffer properties flags

Postby Poi » Thu Feb 21, 2019 1:17 pm

I though that building the color value as a big endian straight away would be easy and save me the call to SwapEndian. Then I took a look at how the bits look after applying the SwapEndian function on a little endian number... I back tracked immediately and decided to just use SwapEndian.

The red and blue channels are not so bad at least they are contiguos, the green channel though... it ends up in this weird position where half the value is at the front and the other half at the back. Not having any of that :lol:

Return to “Graphics”

Who is online

Users browsing this forum: No registered users and 1 guest