© Jan Newmarch 2017

Jan Newmarch, Raspberry Pi GPU Audio Video Programming , 10.1007/978-1-4842-2472-4_4

4. Dispmanx on the Raspberry Pi

Jan Newmarch

(1)Oakleigh, Victoria, Australia

Dispmanx is the lowest level of programming for the RPi’s GPU. I don’t go very deeply into it in this chapter, but you’ll learn enough to get a native window for use by other toolkits.

Building Programs

The following is a Makefile to build the program in this chapter:

DMX_INC =  -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/ -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux

INCLUDES = $(DMX_INC)

CFLAGS = $(INCLUDES)
CPPFLAGS = -march=armv7-a -mtune=cortex-a7


DMX_LIBS =  -L/opt/vc/lib/ -lbcm_host -lvcos -lvchiq_arm -lpthread
LDFLAGS =  $(DMX_LIBS)


all: info

You can use it by running make in the same directory as the Makefile and source file info.c.

Accessing the GPU

The lowest level of accessing the GPU seems to be by an API called Dispmanx. Now, people don’t write their graphics applications using Dispmanx. Instead, they use Dispmanx to get a window that is then used by a framework such as EGL and from there by OpenGLES.

Just to give you a total lack of encouragement from using Dispmanx, there are hardly any examples and no serious documentation. However, that hasn’t stopped AndrewFromMelbourne from developing a set of programs that can draw Mandelbrot figures, animate triangles, and so on. I’m not going to delve deeply into his programs; you can download them from raspidmx ( https://github.com/AndrewFromMelbourne/raspidmx ) if you want.

You just use Dispmanx to get some information about the display size and then to create a window that takes up the full screen. You won’t do anything else in this chapter; this is just a building block on the way to using the Dispmanx window within a higher-level API. Again, if you want, explore AndrewFromMelbourne’s examples.

The following are the relevant Dispmanx calls to build a window :

    DISPMANX_ELEMENT_HANDLE_T dispman_element;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;


   success = graphics_get_display_size(0 /* LCD */,
             &screen_width, &screen_height);
    assert( success >= 0 );


    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = screen_width;
    dst_rect.height = screen_height;


    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = screen_width << 16;
    src_rect.height = screen_height << 16;        


    dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );
    dispman_element =
        vc_dispmanx_element_add(dispman_update, dispman_display,
                                0/*layer*/, &dst_rect, 0/*src*/,
                                &src_rect, DISPMANX_PROTECTION_NONE,
                                0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

At the end of this, you have a window stored in dispman_element that can be used as a native window object later.

The complete program is info.c and just prints the size of the screen, as shown here:

 /*
 * code stolen from openGL-RPi-tutorial-master/encode_OGL/
 */


#include <stdio.h>
#include <assert.h>


#include <bcm_host.h>

typedef struct
{
    uint32_t screen_width;
    uint32_t screen_height;
    DISPMANX_DISPLAY_HANDLE_T dispman_display;
} DISPMANX_STATE_T;


DISPMANX_STATE_T state, *p_state = &state;

void init_dispmanx(DISPMANX_STATE_T *state) {
    int32_t success = 0;


    bcm_host_init();

    DISPMANX_ELEMENT_HANDLE_T dispman_element;

    DISPMANX_UPDATE_HANDLE_T dispman_update;
    VC_RECT_T dst_rect;
    VC_RECT_T src_rect;


    success = graphics_get_display_size(0 /* LCD */,
                                        &state->screen_width,
                                        &state->screen_height);
    assert( success >= 0 );


    printf("Screen height %d, width %d ",
           state->screen_height, state->screen_width) ;


    dst_rect.x = 0;
    dst_rect.y = 0;
    dst_rect.width = state->screen_width;
    dst_rect.height = state->screen_height;


    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = state->screen_width << 16;
    src_rect.height = state->screen_height << 16;        


    state->dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
    dispman_update = vc_dispmanx_update_start( 0 );


    dispman_element =
        vc_dispmanx_element_add(dispman_update, state->dispman_display,
                                0/*layer*/, &dst_rect, 0/*src*/,
                                &src_rect, DISPMANX_PROTECTION_NONE,
                                0 /*alpha*/, 0/*clamp*/, 0/*transform*/);


    /* Now we have created a native Dispmanx window
     * Toolkits such as OpenGL ES will use this for
     * their own 'native window' type, with code like this:


    static EGL_DISPMANX_WINDOW_T nativewindow;

    nativewindow.element = dispman_element;
    nativewindow.width = state->screen_width;
    nativewindow.height = state->screen_height;
    vc_dispmanx_update_submit_sync( dispman_update );
    assert(vc_dispmanx_element_remove(dispman_update, dispman_element) == 0);
    */
}


int
main(int argc, char *argv[])
{
    init_dispmanx(p_state);


    assert( vc_dispmanx_display_close(p_state->dispman_display) == 0);

    return 0;
}

It can then be run easily by the following:

./info

The output on my RPi is as follows:

    Screen height 1080, width 1920

Garbage Collection

C does not have automatic garbage collection like Java or other languages have. You need to do it yourself. This program does little else apart from opening a display. This can be closed by vc_dispmanx_display_close(p_state->dispman_display). It doesn’t actually seem to make a difference but is tidier.

Showing the free memory in RAM used by the CPU is common; tools such as top give a good idea of this, with ps drilling down deeper. Showing the memory used by the GPU is trickier, and there is a Broadcom tool vcdbg to show that. Even if nothing has been run, it shows some memory usage (with 512 MB of RAM devoted to the GPU).

$/opt/vc/lib /opt/vc/bin/vcdbg reloc

Relocatable heap version 4 found at 0x1f000000
total space allocated is 492M, with 492M relocatable, 0 legacy and 0 offline
0 legacy blocks of size 2359296


free list at 0x3d886520
489M free memory in 1 free block(s)
largest free block is 489M bytes


0x1f000000: free 489M
[   4] 0x3d886540: used  576 (refcount 1 lock count 0, size      512, align    4, data 0x3d886560, d0rual) 'ILCS VC buffer pool'
[   3] 0x3d886780: used 3.5M (refcount 1 lock count 8, size  3618816, align 4096, data 0x3d887000, d1rual) 'ARM FB'
[   2] 0x3dbfafa0: used  16K (refcount 1 lock count 0, size    16384, align   32, data 0x3dbfafc0, d0ruAl) 'audioplus_tmp_buf'
[   1] 0x3dbfefe0: used 4.0K (refcount 1 lock count 0, size        0, align 4096, data 0x3dbff000, d1rual) 'camera fast alloc arena'
small allocs not requested

This program is useful for showing what is going on when you haven’t been doing garbage collection!

Screen Captur e

AndrewFromMelbourne has written a program using Dispmanx called raspi2png to capture the RPi screen and save it as a PNG file. The source code demonstrates additional Dispmanx calls.

Conclusion

Dispmanx is the layer between EGL and the Broadcom GPU. You just looked at enough to supply that bridge.

Resources

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset