Hardware graphics acceleration port idea

Many people says that introducing hardware graphics acceleration (OpenGL etc.) is difficult, but actually implementing basic support may be not so.

Hardware accelerated rendering can be done on offscreen GPU surface and then copied to CPU memory and displayed by BView::DrawBitmap. No major changes in Interface Kit / app_server is required. Compositing is also not required. This solution should work faster than software rendering.

Things need to be done:

  1. Port kernel mode DRM (direct rendering manager) as Haiku kernel module. Existing attempts: https://github.com/hamishm/haiku-drm, https://review.haiku-os.org/c/haiku/+/435, https://www.haiku-os.org/blog/vivek/.
  2. Adjust mode setting/accelerant.
  3. Port user mode library for interfacing to kernel module libdrm (https://gitlab.freedesktop.org/mesa/drm).
  4. Enable build of DRM in Mesa port.
  5. Adjust HGL to allocate GPU surfaces and copy it to BBitmap.

I am not familiar with internals of videocard hardware or kernel mode video drivers, but can do userland (Interface Kit/Mesa HGL) things.

8 Likes

I have a long-standing offer to tackle the kernel/drivers side of things, if someone else will take care of the app_server & Mesa side of things, but nobody has taken me up on it yet. So if you’re game… :slight_smile:

The “accelerants” model already has support for hardware framebuffers-as-windows (BDirectWindow), and it is rather flexible (although, the accelerants could use a refactor anyway; they are very much designed around 90s-style video cards, and I think they even get instantiated into apps and not only app_server…)

Refactoring the accelerants, and then app_server to get multi-monitor support would be a good first step here, as the Intel and Radeon drivers already support multi-monitor, but only “mirror” mode as app_server does not support multiple displays.

The existing attempts are extremely basic and don’t get very far.

For my own research, I think there are 3 major possible approaches to porting the KMS-DRM components:

  1. Port the ones from DragonFlyBSD. These mostly keep up with upstream, and use the BSD-style PCI/DMA/etc. APIs that we already have implemented for WiFi support. (Probably the least amount of time required of the 3.)
  2. Port the ones from Linux directly (what the ones you have linked to started doing) via a new compatibility layer. This will probably be more robust in the long run than #1, but will also take more time and trial’n’error to get right.
  3. Port the ones from Linux … as user-space drivers. This may be the “best” solution, actually, though it will require some kind of wrapper in kernel-space for interrupts (PCI mappings may already be workable via /dev/mem.) There really is no good reason for a lot of this code to be in the kernel, Linux only put it there because they don’t ship userspace components with the kernel.

Probably #1 is the approach worth taking, though #3 may be worth consideration at least, or maybe worth revisiting later.

4 Likes

Yes, BWindowScreen allows apps to directly call the accelerant hooks and do scrolling, etc. This could be useful for games to have precise synchronization with the graphics card in the 2D world (but not so much in 3D).

The old radeon driver does support multiple displays. The Screen preferences allows you to set different resolutions for each display and set their relative positions (but I don’t remember if our version still does this or if the Radeon driver used to come with a patched RadeonScreen). This even works in BeOS. The remaining problem is that the driver then tells app_server that this is just one single large display, and it’s not really possible to use BScreen to target a specific display. But it’s a start, and there is already a patch on Gerrit adding the screen_id to all accelerant hooks to solve this (at the cost of losing BeOS compatibility, but we may be able to fix that by putting the parameter at the end and abusing our knowledge of x86 calling conventions, knowing it woudl safely be ignored by old drivers).

4 Likes

Hi this sounds very interesting. I could maybe give some spare time to help out a bit. But someone would need to direct me a bit. So maybe we can get some people together to get it done.

2 Likes

There is also OpenCL support to consider that may not impede getting graphics working too much. Also I think a long time ago it was mentioned that perhaps one of the video acceleration APIs could be hooked up on Haiku. But yeah one thing at a time I guess… I thinking OpenCL could actually occur before graphics acceleration though since there is less going on there.

If either of you needs hardware let me know.

Some time ago I tried to get multiple displays working with a supported Radeon card. I couldn’t get it to work. It may require some extra work.

It worked last time I booted Haiku on my 2003 machine. You need one of the old Radeons (7000/VE or 9250) from 20 years ago. The new radeon_hd driver does not support multiple displays (yet).

1 Like

Is it possible to make at least experimental accelerant API to enumerate displays and getting front buffer of specific display? I can try to integrate it to app_server and Interface Kit.

Related tickets: https://dev.haiku-os.org/ticket/10486, https://dev.haiku-os.org/ticket/8612.

1 Like

The starting point is https://review.haiku-os.org/c/haiku/+/329 there are open questions in the comments.

And also the hacks from the old Radeon driver with RADEON_MODE_MULTIMON_REQUEST/REPLY (https://git.haiku-os.org/haiku/tree/headers/private/graphics/radeon/accelerant_ext.h) which was done this way because the driver was also used on BeOS and changing the hooks there wasn’t possible.

4 Likes

Love it… another if I can help with any hardware.

I have a variation of the Radeon 9800 in my Tyan Thunder 2 ATX these days… I should give it a go also.

1 Like

If hardware testing for anything is needed I have a massive collection of graphics cards from the mid 90s up of about every company that was worth mentioning, and even some that are rather fringe. I have some strange obsession with collecting interesting and old graphics cards, so far I have about 4 large boxes full :neutral_face:

5 Likes

Hi,

Please remember that the nVidia driver I wrote, and also the Matrox driver do support dualhead modes: these use Mark Watson’s preference app, but for the nVidia driver I also added partial support for Thomas his method (Thomas and I had long night-time conversations at BeGeistert back in the day :wink: )

The nVidia driver supports TNT1 upto/including GeForce 7900 or so… And of course I have a lot of them still a few meters away from where I am sitting writing this message :slight_smile:
Bye!

Oh, PS:
http://www.rudolfs-place.nl/BeOS/BeOS.html

6 Likes

Think it ran pretty well on BeOS/ZETA back then :slight_smile:

6 Likes

I found @kallisti5 DRM port attempt: https://gitlab.com/kallisti5/haikugpu. I tried to compile but it failed for both x86 and x86_64:

> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Install directory: "/Haiku/data/packages/linux-5.5.2/include/asm-generic" as "target-x86_64/include/asm-generic"
Install directory: "/Haiku/data/packages/linux-5.5.2/include/video" as "target-x86_64/include/video"
gcc -o /Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.os -c -fPIC -Isrc -Iinclude -I/Haiku/data/packages/linux-5.5.2/arch/x86/include -I/Haiku/data/packages/linux-5.5.2/arch/x86/include/uapi -Itarget-x86_64/include -Isrc/include /Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.c
In file included from /Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/vga.h:11,
                 from target-x86_64/include/video/vga.h:22,
                 from /Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.c:24:
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:50:31: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_array_uc(struct page **pages, int addrinarray);
                               ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:51:31: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_array_wc(struct page **pages, int addrinarray);
                               ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:52:31: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_array_wt(struct page **pages, int addrinarray);
                               ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:53:31: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_array_wb(struct page **pages, int addrinarray);
                               ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:75:25: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_uc(struct page *page, int numpages);
                         ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:76:25: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_wb(struct page *page, int numpages);
                         ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:77:25: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_ro(struct page *page, int numpages);
                         ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:78:25: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_pages_rw(struct page *page, int numpages);
                         ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:80:43: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_direct_map_invalid_noflush(struct page *page);
                                           ^~~~
/Haiku/data/packages/linux-5.5.2/arch/x86/include/asm/set_memory.h:81:43: warning: 'struct page' declared inside parameter list will not be visible outside of this definition or declaration
 int set_direct_map_default_noflush(struct page *page);
                                           ^~~~
In file included from /Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.c:24:
target-x86_64/include/video/vga.h:183:15: error: expected ':', ',', ';', '}' or '__attribute__' before ' token
  void __iomem *vgabase; /* mmio base, if supported      */
               ^
target-x86_64/include/video/vga.h: In function 'vga_io_r':
target-x86_64/include/video/vga.h:204:9: warning: implicit declaration of function 'inb_p' [-Wimplicit-function-declaration]
  return inb_p(port);
         ^~~~~
target-x86_64/include/video/vga.h: In function 'vga_io_w':
target-x86_64/include/video/vga.h:209:2: warning: implicit declaration of function 'outb_p' [-Wimplicit-function-declaration]
  outb_p(val, port);
  ^~~~~~
target-x86_64/include/video/vga.h: In function 'vga_io_w_fast':
target-x86_64/include/video/vga.h:215:2: warning: implicit declaration of function 'outw' [-Wimplicit-function-declaration]
  outw(VGA_OUT16VAL (val, reg), port);
  ^~~~
target-x86_64/include/video/vga.h: At top level:
target-x86_64/include/video/vga.h:218:52: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_mm_r (void __iomem *regbase, unsigned short port)
                                                    ^
target-x86_64/include/video/vga.h:223:43: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_w (void __iomem *regbase, unsigned short port, unsigned char val)
                                           ^
target-x86_64/include/video/vga.h:228:48: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_w_fast (void __iomem *regbase, unsigned short port,
                                                ^
target-x86_64/include/video/vga.h:234:49: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_r (void __iomem *regbase, unsigned short port)
                                                 ^
target-x86_64/include/video/vga.h:242:40: error: expected ';', ',' or ')' before '*' token
 static inline void vga_w (void __iomem *regbase, unsigned short port, unsigned char val)
                                        ^
target-x86_64/include/video/vga.h:251:45: error: expected ';', ',' or ')' before '*' token
 static inline void vga_w_fast (void __iomem *regbase, unsigned short port,
                                             ^
target-x86_64/include/video/vga.h:265:52: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg)
                                                    ^
target-x86_64/include/video/vga.h:271:43: error: expected ';', ',' or ')' before '*' token
 static inline void vga_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
                                           ^
target-x86_64/include/video/vga.h:297:55: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_mm_rcrt (void __iomem *regbase, unsigned char reg)
                                                       ^
target-x86_64/include/video/vga.h:303:46: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
                                              ^
target-x86_64/include/video/vga.h:318:52: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg)
                                                    ^
target-x86_64/include/video/vga.h:324:43: error: expected ';', ',' or ')' before '*' token
 static inline void vga_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
                                           ^
target-x86_64/include/video/vga.h:350:55: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_mm_rseq (void __iomem *regbase, unsigned char reg)
                                                       ^
target-x86_64/include/video/vga.h:356:46: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
                                              ^
target-x86_64/include/video/vga.h:370:52: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg)
                                                    ^
target-x86_64/include/video/vga.h:376:43: error: expected ';', ',' or ')' before '*' token
 static inline void vga_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
                                           ^
target-x86_64/include/video/vga.h:402:55: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_mm_rgfx (void __iomem *regbase, unsigned char reg)
                                                       ^
target-x86_64/include/video/vga.h:408:46: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
                                              ^
target-x86_64/include/video/vga.h:423:53: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg)
                                                     ^
target-x86_64/include/video/vga.h:429:44: error: expected ';', ',' or ')' before '*' token
 static inline void vga_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
                                            ^
target-x86_64/include/video/vga.h:447:56: error: expected ';', ',' or ')' before '*' token
 static inline unsigned char vga_mm_rattr (void __iomem *regbase, unsigned char reg)
                                                        ^
target-x86_64/include/video/vga.h:453:47: error: expected ';', ',' or ')' before '*' token
 static inline void vga_mm_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
                                               ^
/Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.c:26:10: fatal error: drm/drm_atomic_helper.h: No such file or directory
 #include <drm/drm_atomic_helper.h>
          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
scons: *** [/Haiku/data/packages/linux-5.5.2/drivers/gpu/drm/cirrus/cirrus.os] Error 1
scons: building terminated because of errors.

What Linux version and target architecture (x86 or x86_64) was used?

1 Like

Yes, it doesn’t compile, it’s a hack of a first attempt with virtually nothing implemented and I think he since abandoned it; we were discussing this together as he was working on it.