目前看到最好的libdrm tutorial

來源:互聯網
上載者:User

http://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api

http://dvdhrm.wordpress.com/2012/12/21/advanced-drm-mode-setting-api

 

The Direct Rendering Manager (DRM) is a subsystem of the linux kernel that manages access to graphics cards (GPUs). It is the main video API used by X.org‘s xserver and the xf86-video-*video drivers. However, it can also be used by independent programs to program video output without using the xserver or wayland. In the past most other projects used the much olderfbdev API, however, with more and more drivers being added to the DRM subsystem, there is really no reason to avoid DRM on modern computers, anymore. Unfortunately, there hasn’t been any documentation of the DRM API, yet.

DRM-Modesetting HowTo

I have written a short introduction into the DRM mode-setting API, which can be found on github. It is a full C-file with detailed comments on what is needed to perform simple mode-setting with the DRM-API. I embedded the documentation directly into the source file as this makes reading a lot more convenient:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset.c

This document does not describe the whole DRM API. There are parts like the OpenGL-rendering-pipeline, which are driver-dependent and which should almost never be accessed outside of the mesa-3D implementation. Instead, this document describes the API which is needed to write simple applications performing software-rendering similar to fbdev but with the DRM API.

Furthermore, this document is not free of errors. So please contact me if something is wrong, if essential parts are missing or if you intend to extend this documentation.

More tutorials will follow, including “DRM double/triple-buffering”, “DRM vsync’ed pageflips”, “DRM hardware-accelerated rendering”, “DRM planes/overlays/sprites” and more.

I hope you enjoy this short introduction. 

 

=========================================

 

I recently wrote a short How-To that introduces the linux DRM Mode-Setting API. It didn’t use any advanced techniques but I got several responses that it is a great introduction if you want to get started with linux DRM Mode-Setting. So I decided to go further and extend the examples to usedouble-buffering and vsync’ed page-flips.

The first extension that I wrote can be found here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-double-buffered.c

It extends the old example to use two buffers so we no longer render into the front-buffer. It reduces a lot of tearing that you get when using the single-buffered example. However, it is still not perfect as you might swap the front and back buffer during a scanout-period and the display-controller will use the new buffer in the middle of the screen. So I extended this further to do the page-flip during a vertical-blank period using drmModePageFlip(). You can find this example here:

https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c

This example also shows how to wait for page-flip events and integrate it into any select()poll() orepoll based event-loop. Everything regarding page-flip-timing beyond that point depends on the use-cases and can get very hard to get right. I recommend reading Owen Taylor’s posts #1 and #2 on frame-timing for compositors.

There are still many more things like “DRM hardware-accelerated rendering”, “DRM planes/overlays/sprites”, “DRM flink/dmabuf buffer-passing” that I want to write How-Tos for. But time is short around Christmas so that’ll have to wait until next year.

Feedback is always welcome and you can find my email address in all the examples. Happy reading! 

 

代碼在這裡: http://files.cnblogs.com/super119/libdrm-tutorial.zip

原文中有一些feedback,也值得一看。 

 

在modeset-double-buffer-vsync.c中,有一個bug,就是在cleanup之前,沒有wait上一次的page flip結束,這樣就有可能導致雖然我們執行了cleanup,恢複了saved crtc,但是後續的page flip又重新繪製了一螢幕的顏色,最終導致回不去程式執行之前的介面了。所以,在main函數的modeset_cleanup之前,需要添加這樣一段代碼(變數vbl的類型是drmVBlank):

/* Wait VBlank before cleanup. This avoids set crtc in the
           middle of a page flip. */
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 1;
ret = drmWaitVBlank(fd, &vbl);
if (ret != 0) {
    fprintf(stderr, "drmWaitVBlank (relative) failed ret: %i\n",
                        ret);
    /* Anyway, goto cleanup. */

 

理論上來說,kernel的drmModeSetCrtc應該去負責cancel pending的page flip,這樣就不需要userspace來考慮這些問題了。而事實上,set crtc這個工作每個driver的做法是不一樣的。根據原文作者的描述,i915 driver是沒有上述問題的。而我在我的ASUS筆記本上(ATI顯卡,radeon開源驅動)就有這個問題。

所以,理論上來說,我們不需要WaitVBlank這個邏輯,但是目前看來,我們需要(相當於一個workaround)。

 

不過,wait vblank的方式不是一個好的解決方案,理由是:

1. wait vblank無法指定哪個CRTC

2. 要wait多少個vblank才算OK?

所以,和作者David討論了之後,還是採用wait page flip complete的方法較好。也就是像代碼中一樣,使用select來得知page flip complete. 

 

此外,我還發現作者代碼中,find crtc那個函數,目前是通過encoder的possible_crtcs來選定一個crtc。這樣做可以,但是有可能在最終set crtc的時候會觸發fullmode modeset。因為我們可能改變了encoder, crtc原來的配對。其實我們需要改變要顯示的framebuffer而已。為此,我的建議是,首先check encoder的crtc_id是不是有效,如果有效直接使用。如果無效表示該encoder還沒有crtc配對,那麼就使用possible_crtcs來匹配一個。 

 

最後,find crtc函數中還有一個bug,判斷crtc >= 0,事實上,crtc是unsigned int,這個if永遠成立。所以,可以將crtc = -1改成crtc = 0(因為0也是illegal value),然後判斷crtc是否是0就可以。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.