UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
drm.cpp File Reference
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include <memory>
#include <vector>
#include <algorithm>
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "pixfmt_conv.h"
#include "utils/color_out.h"
#include "utils/macros.h"
#include "utils/misc.h"
#include "utils/text.h"
#include "utils/string_view_utils.hpp"
#include "video.h"
#include "video_codec.h"
#include "video_display.h"
#include "hwaccel_drm.h"
Include dependency graph for drm.cpp:

Go to the source code of this file.

Classes

struct  drm_display_state
 
struct  Drm_prime_fb
 
struct  Drm_state
 
class  Framebuffer
 

Macros

#define MOD_NAME   "[drm] "
 

Functions

static Framebuffer create_dumb_fb (int dri, int width, int height, uint32_t pix_fmt)
 
static void display_drm_done (void *state)
 
static bool display_drm_get_property (void *state, int property, void *val, size_t *len)
 
static struct video_frame * display_drm_getf (void *state)
 
static void * display_drm_init (struct module *parent, const char *cfg, unsigned int flags)
 
static void display_drm_probe (struct device_info **available_cards, int *count, void(**deleter)(void *))
 
static bool display_drm_putf (void *state, struct video_frame *f, long long flags)
 
static bool display_drm_reconfigure (void *state, struct video_desc desc)
 
static void draw_frame (Framebuffer *dst, video_frame *src, bool center=true)
 
static void draw_splash (drm_display_state *s)
 
static Drm_prime_fb drm_fb_from_frame (drm_display_state *s, frame_uniq frame)
 
static bool drm_format_supported (drm_display_state *s, uint32_t fmt)
 
static bool get_codecs (drm_display_state *s, void *val, size_t *len)
 
static const char * get_connector_status_str (drmModeConnection c)
 
static std::string get_connector_str (int type, uint32_t id)
 
static std::vector< Drm_connector_uniq > get_connectors (drm_display_state *s)
 
static int64_t get_property (int dri, drmModeObjectPropertiesPtr props, std::string_view name)
 
static Framebuffer get_splash_fb (drm_display_state *s, int width, int height)
 
static bool init_drm_state (drm_display_state *s)
 
static Fd_uniq open_dri (drm_display_state *s)
 
static void print_connectors (drm_display_state *s)
 
static void print_drm_driver_info (drm_display_state *s)
 
static bool probe_drm_formats (drm_display_state *s)
 
static void recycle_frame (drm_display_state *s, frame_uniq &frame)
 
static void recycle_prime_frame (drm_display_state *s, Drm_prime_fb &fb)
 
 REGISTER_MODULE (drm, &display_drm_info, LIBRARY_CLASS_VIDEO_DISPLAY, VIDEO_DISPLAY_ABI_VERSION)
 
static bool set_framebuffer (drm_display_state *s, uint32_t fb_id)
 
static bool setup_crtc (drm_display_state *s)
 
static bool swap_buffers (drm_display_state *s)
 

Variables

static const struct video_display_info display_drm_info
 

Detailed Description

Author
Martin Piatka piatk.nosp@m.a@ce.nosp@m.snet..nosp@m.cz

Definition in file drm.cpp.

Macro Definition Documentation

◆ MOD_NAME

Function Documentation

◆ create_dumb_fb()

static Framebuffer create_dumb_fb ( int dri,
int width,
int height,
uint32_t pix_fmt )
static

Definition at line 703 of file drm.cpp.

703 {
704 Framebuffer buf;
705
706 //TODO: Currently pix_fmt is assumed to be single plane and 32 bpp
707
708 int res = 0;
709
710 {
711 Fb_handle handle;
712 drm_mode_create_dumb create_info = {};
713 create_info.width = width;
714 create_info.height = height;
715 create_info.bpp = 32;
716 res = drmIoctl(dri, DRM_IOCTL_MODE_CREATE_DUMB, &create_info);
717 if(res != 0){
718 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to create a dumb framebuffer (%d)\n", res);
719 return {};
720 }
721 handle.handle = create_info.handle;
722 buf.width = width;
723 buf.height = height;
724 buf.pitch = create_info.pitch;
725 buf.size = create_info.size;
726 handle.dri_fd = dri;
727 buf.handle = Fb_handle_uniq(handle);
728 }
729
730 {
731 uint32_t handles[] = {buf.handle.get().handle, 0, 0, 0};
732 uint32_t pitches[] = {buf.pitch, 0, 0, 0};
733 uint32_t offsets[] = {0, 0, 0, 0};
734 Fb_id fb_id;
735 res = drmModeAddFB2(dri, width, height,
736 pix_fmt, handles, pitches, offsets, &fb_id.id, 0);
737
738 if(res != 0){
739 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to add framebuffer (%d)\n", res);
740 return {};
741 }
742
743 fb_id.dri_fd = dri;
744 buf.id = Fb_id_uniq(fb_id);
745 }
746
747 log_msg(LOG_LEVEL_INFO, MOD_NAME "Created dumb buffer: pitch %u, handle: %u\n", buf.pitch, buf.handle.get().handle);
748
749
750 struct drm_mode_map_dumb map_info = {};
751 map_info.handle = buf.handle.get().handle;
752
753 res = drmIoctl(dri, DRM_IOCTL_MODE_MAP_DUMB, &map_info);
754 if(res != 0){
755 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to get map info (%d)\n", res);
756 return {};
757 }
758
759 buf.map = MemoryMapping::create(0, buf.size, PROT_READ | PROT_WRITE, MAP_SHARED, dri, map_info.offset);
760 if(!buf.map.valid()){
761 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to map buffer\n");
762 return {};
763 }
764
765 return buf;
766}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MOD_NAME
Definition drm.cpp:75
uint32_t height
Definition drm.cpp:334
uint32_t pitch
Definition drm.cpp:335
Fb_id_uniq id
Definition drm.cpp:342
size_t size
Definition drm.cpp:336
MemoryMapping map
Definition drm.cpp:343
uint32_t width
Definition drm.cpp:333
Fb_handle_uniq handle
Definition drm.cpp:338

References Framebuffer::handle, Framebuffer::height, Framebuffer::id, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, log_msg(), Framebuffer::map, MOD_NAME, Framebuffer::pitch, Framebuffer::size, and Framebuffer::width.

Referenced by display_drm_reconfigure(), and get_splash_fb().

Here is the call graph for this function:

◆ display_drm_done()

static void display_drm_done ( void * state)
static

Definition at line 905 of file drm.cpp.

906{
907 auto s = std::unique_ptr<drm_display_state>(static_cast<drm_display_state *>(state));
908
909 int res = 0;
910 res = drmModeSetCrtc(s->drm.dri_fd.get(), s->drm.crtc->crtc_id, s->drm.crtc->buffer_id,
911 s->drm.crtc->x , s->drm.crtc->y, &s->drm.connector->connector_id, 1, &s->drm.crtc->mode);
912 if(res < 0){
913 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to restore original crtc (%d)\n", res);
914 }
915}
void ** state

References LOG_LEVEL_ERROR, log_msg(), MOD_NAME, and state.

Here is the call graph for this function:

◆ display_drm_get_property()

static bool display_drm_get_property ( void * state,
int property,
void * val,
size_t * len )
static

Definition at line 1037 of file drm.cpp.

1038{
1039 auto s = static_cast<drm_display_state *>(state);
1040
1041 int rgb_shift[] = {0, 8, 16};
1042 if(!drm_format_supported(s, DRM_FORMAT_XBGR8888)){
1043 std::swap(rgb_shift[0], rgb_shift[2]);
1044 }
1045
1046 switch (property) {
1048 return get_codecs(s, val, len);
1050 if(sizeof(rgb_shift) > *len) {
1051 return false;
1052 }
1053 memcpy(val, rgb_shift, sizeof(rgb_shift));
1054 *len = sizeof(rgb_shift);
1055 break;
1056 default:
1057 return false;
1058 }
1059 return true;
1060}
int void * val
int void size_t * len
int property
static bool drm_format_supported(drm_display_state *s, uint32_t fmt)
Definition drm.cpp:821
static bool get_codecs(drm_display_state *s, void *val, size_t *len)
Definition drm.cpp:1014
@ DISPLAY_PROPERTY_RGB_SHIFT
red,green,blue shift - int[3] (bits)
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]

References DISPLAY_PROPERTY_CODECS, DISPLAY_PROPERTY_RGB_SHIFT, drm_format_supported(), get_codecs(), len, property, state, and val.

Here is the call graph for this function:

◆ display_drm_getf()

static struct video_frame * display_drm_getf ( void * state)
static

Definition at line 917 of file drm.cpp.

918{
919 auto s = static_cast<drm_display_state *>(state);
920
921 while(!s->free_frames.empty()){
922 auto frame = std::move(s->free_frames.back());
923 s->free_frames.pop_back();
924
925 if(video_desc_eq(video_desc_from_frame(frame.get()), s->desc)){
926 return frame.release();
927 }
928 }
929
930 return vf_alloc_desc_data(s->desc);
931}
struct video_frame * frame
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.

References frame, state, vf_alloc_desc_data(), video_desc_eq(), and video_desc_from_frame().

Here is the call graph for this function:

◆ display_drm_init()

static void * display_drm_init ( struct module * parent,
const char * cfg,
unsigned int flags )
static

Definition at line 842 of file drm.cpp.

843{
845
846 auto s = std::make_unique<drm_display_state>();
847
848 if(cfg)
849 s->cfg = cfg;
850
851 bool help_requested = false;
852 std::string_view sv_cfg(s->cfg);
853 while(!sv_cfg.empty()){
854 auto token = tokenize(sv_cfg, ':');
855 auto key = tokenize(token, '=');
856 auto val = tokenize(token, '=');
857
858 if(key == "help"){
859 help_requested = true;
860 } else if(key == "dev"){
861 s->device_path = val;
862 } else if(key == "connector"){
863 s->req_connector = val;
864 } else if(key == "mode"){
865 auto res = tokenize(val, '@');
866 auto rate = tokenize(val, '@');
867
868 auto width = tokenize(res, 'x');
869 auto height = tokenize(res, 'x');
870
871 parse_num(width, s->req_width);
872 parse_num(height, s->req_height);
873 parse_num(rate, s->req_rate);
874 }
875 }
876
877 if(!init_drm_state(s.get())){
878 return nullptr;
879 }
880
881 if(help_requested){
882 color_printf("\n");
883 color_printf("DRM display\n");
884 color_printf(TBOLD(TRED("\t-t drm"))"[:dev=<path>][:connector=<c>][:mode=<w>x<h>[@<rate>]]\n");
885 color_printf("where:\n");
886 color_printf(TBOLD("\tpath") " - Path to the DRI device. If not specified /dev/video[0..32] are tried.\n");
887 color_printf(TBOLD("\tconnector") " - The physical connector the display device is plugged into.\n");
888 color_printf(TBOLD("\tmode") " - Video mode to use. If not specified, the preferred mode is used. \n");
889 color_printf("\n");
890 print_connectors(s.get());
891 return INIT_NOERR;
892 }
893
894 if(!setup_crtc(s.get())){
895 return nullptr;
896 }
897
898 s->splashscreen = get_splash_fb(s.get(), s->drm.mode_info->hdisplay, s->drm.mode_info->vdisplay);
899
900 draw_splash(s.get());
901
902 return s.release();
903}
#define UNUSED(x)
const char unsigned int flags
int color_printf(const char *format,...)
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
static void print_connectors(drm_display_state *s)
Definition drm.cpp:575
static Framebuffer get_splash_fb(drm_display_state *s, int width, int height)
Definition drm.cpp:825
static bool setup_crtc(drm_display_state *s)
Definition drm.cpp:591
static void draw_splash(drm_display_state *s)
Definition drm.cpp:779
static bool init_drm_state(drm_display_state *s)
Definition drm.cpp:528
#define INIT_NOERR
Definition host.h:73
const char * parent
Definition settings.cpp:198
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)
const char * key
Definition cineform.cpp:125

References color_printf(), draw_splash(), flags, get_splash_fb(), init_drm_state(), INIT_NOERR, key, parent, parse_num(), print_connectors(), setup_crtc(), TBOLD, tokenize(), TRED, UNUSED, and val.

Here is the call graph for this function:

◆ display_drm_probe()

static void display_drm_probe ( struct device_info ** available_cards,
int * count,
void(** deleter )(void *) )
static

Definition at line 1119 of file drm.cpp.

1119 {
1120 UNUSED(deleter);
1121 *available_cards = NULL;
1122 *count = 0;
1123}
int void(** deleter)(void *))
int count
Definition hd-rum.c:44

References count, deleter, and UNUSED.

◆ display_drm_putf()

static bool display_drm_putf ( void * state,
struct video_frame * f,
long long flags )
static

Definition at line 981 of file drm.cpp.

982{
983 frame_uniq frame(f);
984
985 if (!frame) {
986 return true;
987 }
988
989 auto s = static_cast<drm_display_state *>(state);
990
991 if(flags == PUTF_DISCARD){
993 return true;
994 }
995
996 if(frame->color_spec == DRM_PRIME){
997 Drm_prime_fb fb = drm_fb_from_frame(s, std::move(frame));
998 if(!set_framebuffer(s, fb.id.get().id)){
999 return false;
1000 }
1001
1002 recycle_prime_frame(s, s->drm_prime_fb);
1003 s->drm_prime_fb = std::move(fb);
1004 return true;
1005 }
1006
1007 draw_frame(&s->back_buffer, frame.get());
1008 recycle_frame(s, frame);
1009 swap_buffers(s);
1010
1011 return true;
1012}
static Drm_prime_fb drm_fb_from_frame(drm_display_state *s, frame_uniq frame)
Definition drm.cpp:938
static void recycle_frame(drm_display_state *s, frame_uniq &frame)
Definition drm.cpp:967
static void recycle_prime_frame(drm_display_state *s, Drm_prime_fb &fb)
Definition drm.cpp:972
static bool set_framebuffer(drm_display_state *s, uint32_t fb_id)
Definition drm.cpp:768
static bool swap_buffers(drm_display_state *s)
Definition drm.cpp:933
static void draw_frame(Framebuffer *dst, video_frame *src, bool center=true)
Definition drm.cpp:788
#define PUTF_DISCARD
Fb_id_uniq id
Definition drm.cpp:349
codec_t color_spec
Definition types.h:306
@ DRM_PRIME
DRM Prime buffer, data contains struct drm_prime_frame.
Definition types.h:107

References video_frame::color_spec, draw_frame(), drm_fb_from_frame(), DRM_PRIME, flags, frame, Drm_prime_fb::id, PUTF_DISCARD, recycle_frame(), recycle_prime_frame(), set_framebuffer(), state, and swap_buffers().

Here is the call graph for this function:

◆ display_drm_reconfigure()

static bool display_drm_reconfigure ( void * state,
struct video_desc desc )
static

Definition at line 1062 of file drm.cpp.

1063{
1064 auto s = static_cast<drm_display_state *>(state);
1065
1066 s->desc = desc;
1067
1068 s->frame.reset(vf_alloc_desc_data(desc));
1069
1070 uint32_t pix_fmt;
1071
1072 switch(desc.color_spec){
1073 case RGBA:
1074 pix_fmt = drm_format_supported(s, DRM_FORMAT_XBGR8888) ? DRM_FORMAT_XBGR8888 : DRM_FORMAT_XRGB8888;
1075 break;
1076 case UYVY:
1077 pix_fmt = DRM_FORMAT_UYVY;
1078 break;
1079 case DRM_PRIME:
1080 /* We don't create dumb buffers in this case, we import framebuffers from video frames instead
1081 */
1082 pix_fmt = 0; //UNUSED
1083 if(!s->drm.mode_info || s->drm.mode_info->hdisplay > desc.width || s->drm.mode_info->vdisplay > desc.height){
1084 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Video mode resolution must be less or equal to DRM_PRIME frames. Trying to find a suitable mode...\n");
1085 s->drm.mode_info = nullptr;
1086 for(int i = 0; i < s->drm.connector->count_modes; i++){
1087 auto mode = &s->drm.connector->modes[i];
1088
1089 if(mode->hdisplay > desc.width)
1090 continue;
1091
1092 if(mode->vdisplay > desc.height)
1093 continue;
1094
1095 s->drm.mode_info = mode;
1096 break;
1097 }
1098 if(!s->drm.mode_info){
1099 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to find suitable mode\n");
1100 return false;
1101 }
1102 }
1103 return true;
1104 default:
1105 return false;
1106 }
1107
1108 if(desc.width > s->drm.mode_info->hdisplay || desc.height > s->drm.mode_info->vdisplay){
1109 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Video resolution is larger than framebuffer. Only part of video frames will be visible\n");
1110 }
1111
1112 s->front_buffer = create_dumb_fb(s->drm.dri_fd.get(), s->drm.mode_info->hdisplay, s->drm.mode_info->vdisplay, pix_fmt);
1113 s->back_buffer = create_dumb_fb(s->drm.dri_fd.get(), s->drm.mode_info->hdisplay, s->drm.mode_info->vdisplay, pix_fmt);
1114
1115
1116 return true;
1117}
struct video_desc desc
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
static Framebuffer create_dumb_fb(int dri, int width, int height, uint32_t pix_fmt)
Definition drm.cpp:703
enum openssl_mode mode
video_desc desc
Definition drm.cpp:369
codec_t color_spec
Definition types.h:182
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70

References video_desc::color_spec, create_dumb_fb(), desc, drm_display_state::desc, drm_format_supported(), DRM_PRIME, video_desc::height, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, mode, RGBA, state, UYVY, vf_alloc_desc_data(), and video_desc::width.

Here is the call graph for this function:

◆ draw_frame()

static void draw_frame ( Framebuffer * dst,
video_frame * src,
bool center = true )
static

Definition at line 788 of file drm.cpp.

788 {
789 auto dst_p = static_cast<char *>(dst->map.get());
790 auto src_p = static_cast<char *>(src->tiles[0].data);
791
792 auto src_w = src->tiles[0].width;
793 auto src_h = src->tiles[0].height;
794
795 unsigned x = 0;
796 unsigned y = 0;
797
798 if(center){
799 if(src_w < dst->width)
800 x = (dst->width - src_w) / 2;
801 if(src_h < dst->height)
802 y = (dst->height - src_h) / 2;
803 }
804
805 int width = std::min(src_w, dst->width - x);
806 int height = std::min(src_h, dst->height - y);
807
808 auto src_pitch = vc_get_linesize(src_w, src->color_spec);
809 auto linesize = vc_get_size(width, src->color_spec);
810
811 dst_p += dst->pitch * y;
812 dst_p += vc_get_size(x, src->color_spec);
813
814 for(int y = 0; y < height; y++){
815 memcpy(dst_p, src_p, linesize);
816 dst_p += dst->pitch;
817 src_p += src_pitch;
818 }
819}
int vc_get_linesize(unsigned int width, codec_t codec)
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int height
Definition types.h:281
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
int vc_get_size(unsigned int width, codec_t codec)

References video_frame::color_spec, tile::data, Framebuffer::height, tile::height, Framebuffer::map, Framebuffer::pitch, video_frame::tiles, vc_get_linesize(), vc_get_size(), Framebuffer::width, and tile::width.

Referenced by display_drm_putf(), and get_splash_fb().

Here is the call graph for this function:

◆ draw_splash()

static void draw_splash ( drm_display_state * s)
static

Definition at line 779 of file drm.cpp.

779 {
780 int res = 0;
781 res = drmModeSetCrtc(s->drm.dri_fd.get(), s->drm.crtc->crtc_id,
782 s->splashscreen.id.get().id, 0, 0, &s->drm.connector->connector_id, 1, s->drm.mode_info);
783 if(res < 0){
784 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to set crtc (%d)\n", res);
785 }
786}
drmModeModeInfoPtr mode_info
Definition drm.cpp:329
Drm_connector_uniq connector
Definition drm.cpp:321
Drm_crtc_uniq crtc
Definition drm.cpp:323
Fd_uniq dri_fd
Definition drm.cpp:316
Drm_state drm
Definition drm.cpp:360
Framebuffer splashscreen
Definition drm.cpp:362

References Drm_state::connector, Drm_state::crtc, Drm_state::dri_fd, drm_display_state::drm, Framebuffer::id, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, Drm_state::mode_info, and drm_display_state::splashscreen.

Referenced by display_drm_init().

Here is the call graph for this function:

◆ drm_fb_from_frame()

static Drm_prime_fb drm_fb_from_frame ( drm_display_state * s,
frame_uniq frame )
static

Definition at line 938 of file drm.cpp.

938 {
939 assert(frame->color_spec == DRM_PRIME);
940
941 Drm_prime_fb fb;
942 fb.frame = std::move(frame);
943 auto drm_frame = (drm_prime_frame *) fb.frame->tiles[0].data;
944
945 for(int i = 0; i < drm_frame->fd_count; i++){
946 fb.gem_objects[i] = s->drm.gem_manager->get_handle(drm_frame->dmabuf_fds[i]);
947 }
948
949 uint32_t handles[4] = {};
950 for(int i = 0; i < drm_frame->planes; i++){
951 handles[i] = fb.gem_objects[drm_frame->fd_indices[i]].get();
952 }
953
954 int res = 0;
955 Fb_id fb_id;
956 res = drmModeAddFB2WithModifiers(s->drm.dri_fd.get(), fb.frame->tiles[0].width, fb.frame->tiles[0].height, drm_frame->drm_format,
957 handles, drm_frame->pitches, drm_frame->offsets, drm_frame->modifiers, &fb_id.id, DRM_MODE_FB_MODIFIERS);
958 if(res != 0){
959 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to add FB\n");
960 }
961 fb_id.dri_fd = s->drm.dri_fd.get();
962 fb.id = Fb_id_uniq(fb_id);
963
964 return fb;
965}
frame_uniq frame
Definition drm.cpp:347
std::unique_ptr< Gem_handle_manager > gem_manager
Definition drm.cpp:318

References video_frame::color_spec, Drm_state::dri_fd, drm_display_state::drm, DRM_PRIME, Drm_prime_fb::frame, frame, Drm_state::gem_manager, Drm_prime_fb::gem_objects, Drm_prime_fb::id, LOG_LEVEL_ERROR, log_msg(), and MOD_NAME.

Referenced by display_drm_putf().

Here is the call graph for this function:

◆ drm_format_supported()

static bool drm_format_supported ( drm_display_state * s,
uint32_t fmt )
static

Definition at line 821 of file drm.cpp.

821 {
822 return s->drm.supported_drm_formats.find(fmt) != s->drm.supported_drm_formats.end();
823}
const char * fmt
std::set< uint32_t > supported_drm_formats
Definition drm.cpp:326

References drm_display_state::drm, fmt, and Drm_state::supported_drm_formats.

Referenced by display_drm_get_property(), display_drm_reconfigure(), and get_splash_fb().

◆ get_codecs()

static bool get_codecs ( drm_display_state * s,
void * val,
size_t * len )
static

Definition at line 1014 of file drm.cpp.

1014 {
1015 std::vector<codec_t> out;
1016
1017 if(s->drm.prime_support)
1018 out.push_back(DRM_PRIME);
1019
1020 if(s->drm.supported_drm_formats.find(DRM_FORMAT_UYVY) != s->drm.supported_drm_formats.end())
1021 out.push_back(UYVY);
1022
1023 out.push_back(RGBA);
1024
1025 size_t length = sizeof(codec_t) * out.size();
1026
1027 if(*len < length) {
1028 return false;
1029 }
1030 *len = length;
1031 memcpy(val, out.data(), *len);
1032
1033 return true;
1034
1035}
bool prime_support
Definition drm.cpp:327
codec_t
Definition types.h:65

References drm_display_state::drm, DRM_PRIME, len, Drm_state::prime_support, RGBA, Drm_state::supported_drm_formats, UYVY, and val.

Referenced by display_drm_get_property().

◆ get_connector_status_str()

static const char * get_connector_status_str ( drmModeConnection c)
static

Definition at line 563 of file drm.cpp.

563 {
564 switch(c){
565 case DRM_MODE_CONNECTED:
566 return " (Connected)";
567 case DRM_MODE_DISCONNECTED:
568 return " (Not connected)";
569 case DRM_MODE_UNKNOWNCONNECTION:
570 default:
571 return "";
572 }
573}

Referenced by print_connectors().

◆ get_connector_str()

static std::string get_connector_str ( int type,
uint32_t id )
static

Definition at line 375 of file drm.cpp.

375 {
376 std::string res;
377 switch(type){
378 case DRM_MODE_CONNECTOR_VGA: res = "VGA"; break;
379 case DRM_MODE_CONNECTOR_HDMIA: res = "HDMI-A"; break;
380 case DRM_MODE_CONNECTOR_HDMIB: res = "HDMI-B"; break;
381 case DRM_MODE_CONNECTOR_DisplayPort: res = "DP"; break;
382 case DRM_MODE_CONNECTOR_eDP: res = "eDP"; break;
383 case DRM_MODE_CONNECTOR_DVII: res = "DVI-I"; break;
384 case DRM_MODE_CONNECTOR_DVID: res = "DVI-D"; break;
385 case DRM_MODE_CONNECTOR_DVIA: res = "DVI-A"; break;
386#ifdef DRM_MODE_CONNECTOR_USB
387 case DRM_MODE_CONNECTOR_USB: res = "USB"; break;
388#endif
389 default:
390 res = std::to_string(type);
391 }
392
393 res += "-";
394 res += std::to_string(id);
395
396 return res;
397}
Option::OptType type
Definition settings.cpp:194

References type.

Referenced by print_connectors(), and setup_crtc().

◆ get_connectors()

static std::vector< Drm_connector_uniq > get_connectors ( drm_display_state * s)
static

Definition at line 514 of file drm.cpp.

514 {
515 std::vector<Drm_connector_uniq> res;
516
517 for(int i = 0; i < s->drm.res->count_connectors; i++){
518 Drm_connector_uniq conn(drmModeGetConnector(s->drm.dri_fd.get(), s->drm.res->connectors[i]));
519 if(!conn)
520 continue;
521
522 res.push_back(std::move(conn));
523 }
524
525 return res;
526}
Drm_res_uniq res
Definition drm.cpp:320

References Drm_state::dri_fd, drm_display_state::drm, and Drm_state::res.

Referenced by print_connectors(), and setup_crtc().

◆ get_property()

static int64_t get_property ( int dri,
drmModeObjectPropertiesPtr props,
std::string_view name )
static

Definition at line 465 of file drm.cpp.

465 {
466 for(unsigned i = 0; i < props->count_props; i++){
467 Drm_property_uniq prop(drmModeGetProperty(dri, props->props[i]));
468 if(!prop)
469 continue;
470
471 if(prop->name == name)
472 return props->prop_values[i];
473 }
474 return -1;
475}
const char * name
Definition settings.cpp:193

References name.

Referenced by probe_drm_formats(), and sdi_register_display_callbacks().

◆ get_splash_fb()

static Framebuffer get_splash_fb ( drm_display_state * s,
int width,
int height )
static

Definition at line 825 of file drm.cpp.

825 {
826 frame_uniq splash_frame(get_splashscreen());
827
828 uint32_t pix_fmt;
829 if(drm_format_supported(s, DRM_FORMAT_XBGR8888)){
830 pix_fmt = DRM_FORMAT_XBGR8888;
831 } else {
832 //XRGB_8888 should be always present
833 //red and blue will be swapped, but for splash it doesn't matter much
834 pix_fmt = DRM_FORMAT_XRGB8888;
835 }
836 auto fb = create_dumb_fb(s->drm.dri_fd.get(), width, height, pix_fmt);
837 draw_frame(&fb, splash_frame.get(), true);
838
839 return fb;
840}
struct video_frame * get_splashscreen()

References create_dumb_fb(), draw_frame(), Drm_state::dri_fd, drm_display_state::drm, drm_format_supported(), and get_splashscreen().

Referenced by display_drm_init().

Here is the call graph for this function:

◆ init_drm_state()

static bool init_drm_state ( drm_display_state * s)
static

Definition at line 528 of file drm.cpp.

528 {
529 s->drm.dri_fd = open_dri(s);
530
531 int dri = s->drm.dri_fd.get();
532 if(dri < 0){
533 return false;
534 }
535
537
538 int res = 0;
539 res = drmSetClientCap(dri, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
540 if(res != 0){
541 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to set universal planes capab\n");
542 return false;
543 }
544
545 s->drm.gem_manager = std::make_unique<Gem_handle_manager>(dri);
546
547 s->drm.res.reset(drmModeGetResources(dri));
548 if(!s->drm.res){
549 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to get DRI resources: %s\n", strerror(errno));
550 return false;
551 }
552
553 uint64_t prime_support = false;
554 res = drmGetCap(dri, DRM_CAP_PRIME, &prime_support);
555 if(res < 0 || !prime_support){
556 log_msg(LOG_LEVEL_WARNING, MOD_NAME "DRM device does not support PRIME buffers\n");
557 }
558 s->drm.prime_support = prime_support;
559
560 return true;
561}
static Fd_uniq open_dri(drm_display_state *s)
Definition drm.cpp:415
static void print_drm_driver_info(drm_display_state *s)
Definition drm.cpp:399

References Drm_state::dri_fd, drm_display_state::drm, Drm_state::gem_manager, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, open_dri(), Drm_state::prime_support, print_drm_driver_info(), and Drm_state::res.

Referenced by display_drm_init().

Here is the call graph for this function:

◆ open_dri()

static Fd_uniq open_dri ( drm_display_state * s)
static

Definition at line 415 of file drm.cpp.

415 {
416
417 auto do_open = [](const char *path) -> Fd_uniq {
418 int fd = open(path, O_RDWR);
419 if(fd < 0){
420 if(errno != ENOENT)
421 log_msg(LOG_LEVEL_INFO, MOD_NAME "Failed to open %s (%s)\n", path, strerror(errno));
422
423 return {};
424 }
425 Fd_uniq ret(fd);
426
427 Drm_res_uniq resources(drmModeGetResources(fd));
428 if(!resources){
429 log_msg(LOG_LEVEL_INFO, MOD_NAME "Failed to get resources on %s (%s)\n", path, strerror(errno));
430 return {};
431 }
432
433 uint64_t dumb_support = false;
434 int res = 0;
435 res = drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &dumb_support);
436 if(res < 0 || !dumb_support){
437 log_msg(LOG_LEVEL_WARNING, MOD_NAME "%s does not support dumb buffers\n", path);
438 return {};
439 }
440
441 log_msg(LOG_LEVEL_INFO, MOD_NAME "Opened %s DRI device\n", path);
442 return ret;
443 };
444
445 if(!s->device_path.empty()){
446 auto ret = do_open(s->device_path.c_str());
447 if(!ret)
448 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to open specified device (%s)\n", s->device_path.c_str());
449
450 return ret;
451 }
452
453 char buf[256] = {};
454 const int max_index = 32;
455 for(int i = 0; i < max_index; i++){
456 snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, i);
457 auto ret = do_open(buf);
458 if(ret)
459 return ret;
460 }
461 log_msg(LOG_LEVEL_ERROR, MOD_NAME "No suitable DRI device found\n");
462 return {};
463}
std::string device_path
Definition drm.cpp:354

References drm_display_state::device_path, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), and MOD_NAME.

Referenced by init_drm_state().

Here is the call graph for this function:

◆ print_connectors()

static void print_connectors ( drm_display_state * s)
static

Definition at line 575 of file drm.cpp.

575 {
576 color_printf("Connectors:\n");
577
578 auto connectors = get_connectors(s);
579 for(auto& connector : connectors){
580 color_printf("\t%s%s:\n", get_connector_str(connector->connector_type, connector->connector_type_id).c_str(),
581 get_connector_status_str(connector->connection));
582
583 for(int i = 0; i < connector->count_modes; i++){
584 auto mode_info = &connector->modes[i];
585 color_printf("\t\t%dx%d@%d (%s)%s\n", mode_info->hdisplay, mode_info->vdisplay, mode_info->vrefresh, mode_info->name,
586 mode_info->type & DRM_MODE_TYPE_PREFERRED ? " preferred" : "");
587 }
588 }
589}
static std::string get_connector_str(int type, uint32_t id)
Definition drm.cpp:375
static std::vector< Drm_connector_uniq > get_connectors(drm_display_state *s)
Definition drm.cpp:514
static const char * get_connector_status_str(drmModeConnection c)
Definition drm.cpp:563

References color_printf(), get_connector_status_str(), get_connector_str(), and get_connectors().

Referenced by display_drm_init().

Here is the call graph for this function:

◆ print_drm_driver_info()

static void print_drm_driver_info ( drm_display_state * s)
static

Definition at line 399 of file drm.cpp.

399 {
400 drmVersionPtr version = drmGetVersion(s->drm.dri_fd.get());
401 if(!version){
402 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Failed to get DRM driver version\n");
403 return;
404 }
405
406 log_msg(LOG_LEVEL_INFO, MOD_NAME "DRM version: %d.%d.%d (%s), Driver: %s\n",
407 version->version_major,
408 version->version_minor,
409 version->version_patchlevel,
410 version->date,
411 version->name);
412 drmFreeVersion(version);
413}

References Drm_state::dri_fd, drm_display_state::drm, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), and MOD_NAME.

Referenced by init_drm_state().

Here is the call graph for this function:

◆ probe_drm_formats()

static bool probe_drm_formats ( drm_display_state * s)
static

Definition at line 477 of file drm.cpp.

477 {
478 int dri = s->drm.dri_fd.get();
479 Drm_plane_res_uniq plane_res(drmModeGetPlaneResources(dri));
480 if(!plane_res){
481 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to get plane resources (%s)\n", strerror(errno));
482 return false;
483 }
484
485 Drm_plane_uniq primary_plane;
486 for(unsigned i = 0; i < plane_res->count_planes; i++){
487 Drm_plane_uniq plane(drmModeGetPlane(dri, plane_res->planes[i]));
488 if(!(plane->possible_crtcs & (1 << s->drm.crtc_index)))
489 continue;
490
491 Drm_object_properties_uniq props(drmModeObjectGetProperties(dri, plane_res->planes[i], DRM_MODE_OBJECT_PLANE));
492 if(!props){
493 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to get plane props (%s)\n", strerror(errno));
494 continue;
495 }
496 if(get_property(dri, props.get(), "type") == DRM_PLANE_TYPE_PRIMARY){
497 primary_plane = std::move(plane);
498 break;
499 }
500 }
501
502 if(!primary_plane){
503 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to find the primary plane\n");
504 return false;
505 }
506
507 for(unsigned i = 0; i < primary_plane->count_formats; i++){
508 s->drm.supported_drm_formats.insert(primary_plane->formats[i]);
509 }
510
511 return true;
512}
static int64_t get_property(int dri, drmModeObjectPropertiesPtr props, std::string_view name)
Definition drm.cpp:465
int crtc_index
Definition drm.cpp:324

References Drm_state::crtc_index, Drm_state::dri_fd, drm_display_state::drm, get_property(), LOG_LEVEL_ERROR, log_msg(), MOD_NAME, and Drm_state::supported_drm_formats.

Referenced by setup_crtc().

Here is the call graph for this function:

◆ recycle_frame()

static void recycle_frame ( drm_display_state * s,
frame_uniq & frame )
static

Definition at line 967 of file drm.cpp.

967 {
968 vf_recycle(frame.get());
969 s->free_frames.push_back(std::move(frame));
970}
std::vector< frame_uniq > free_frames
Definition drm.cpp:372
void vf_recycle(struct video_frame *buf)
This function should be called before returning a frame back to a frame pool. Currently this is used ...

References frame, drm_display_state::free_frames, and vf_recycle().

Referenced by display_drm_putf().

Here is the call graph for this function:

◆ recycle_prime_frame()

static void recycle_prime_frame ( drm_display_state * s,
Drm_prime_fb & fb )
static

Definition at line 972 of file drm.cpp.

972 {
973 frame_uniq frame = std::move(fb.frame);
974 fb = {};
975 if(frame){
976 vf_recycle(frame.get());
977 s->free_frames.push_back(std::move(frame));
978 }
979}

References Drm_prime_fb::frame, frame, drm_display_state::free_frames, and vf_recycle().

Referenced by display_drm_putf().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( drm ,
& display_drm_info,
LIBRARY_CLASS_VIDEO_DISPLAY ,
VIDEO_DISPLAY_ABI_VERSION  )

◆ set_framebuffer()

static bool set_framebuffer ( drm_display_state * s,
uint32_t fb_id )
static

Definition at line 768 of file drm.cpp.

768 {
769 int res = 0;
770 res = drmModeSetCrtc(s->drm.dri_fd.get(), s->drm.crtc->crtc_id,
771 fb_id, 0, 0, &s->drm.connector->connector_id, 1, s->drm.mode_info);
772 if(res < 0){
773 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to set crtc (%d)\n", res);
774 return false;
775 }
776 return true;
777}

References Drm_state::connector, Drm_state::crtc, Drm_state::dri_fd, drm_display_state::drm, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, and Drm_state::mode_info.

Referenced by display_drm_putf(), and swap_buffers().

Here is the call graph for this function:

◆ setup_crtc()

static bool setup_crtc ( drm_display_state * s)
static

Definition at line 591 of file drm.cpp.

591 {
592 auto connectors = get_connectors(s);
593
594 for(auto& connector : connectors){
595 if(!s->req_connector.empty()){
596 if(s->req_connector == get_connector_str(connector->connector_type, connector->connector_type_id)){
597 s->drm.connector = std::move(connector);
598 break;
599 } else {
600 continue;
601 }
602 }
603
604 if(connector->count_modes > 0 && connector->connection == DRM_MODE_CONNECTED){
605 s->drm.connector = std::move(connector);
606 break;
607 }
608 }
609
610 if(!s->drm.connector){
611 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Connector not found\n");
612 return false;
613 }
614
615 bool find_preferred_mode = s->req_width <= 0 && s->req_height <= 0 && s->req_rate <= 0;
616 for(int i = 0; i < s->drm.connector->count_modes; i++){
617 auto mode = &s->drm.connector->modes[i];
618
619 if(s->req_width > 0 && mode->hdisplay != s->req_width)
620 continue;
621
622 if(s->req_height > 0 && mode->vdisplay != s->req_height)
623 continue;
624
625 if(s->req_rate > 0 && mode->vrefresh != s->req_rate)
626 continue;
627
628 if(find_preferred_mode && !(mode->type & DRM_MODE_TYPE_PREFERRED)){
629 continue;
630 }
631
632 s->drm.mode_info = mode;
633 break;
634 }
635
636 if(!s->drm.mode_info){
637 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Mode not found\n");
638 return false;
639 }
640
641 int dri = s->drm.dri_fd.get();
642
643 std::vector<int> encoder_list;
644 if(s->drm.connector->encoder_id){
645 encoder_list.push_back(s->drm.connector->encoder_id);
646 }
647 for(int i = 0; i < s->drm.connector->count_encoders; i++){
648 encoder_list.push_back(s->drm.connector->encoders[i]);
649 }
650
651 for(int encoder_id : encoder_list){
652 s->drm.encoder.reset(drmModeGetEncoder(dri, encoder_id));
653 if(!s->drm.encoder)
654 continue;
655
656 std::vector<unsigned> crtc_list;
657 if(s->drm.encoder->crtc_id){
658 crtc_list.push_back(s->drm.encoder->crtc_id);
659 }
660 for(int i = 0; i < s->drm.res->count_crtcs; i++){
661 if((1 << i) & s->drm.encoder->possible_crtcs){
662 crtc_list.push_back(s->drm.res->crtcs[i]);
663 }
664 }
665
666 for(unsigned crtc_id : crtc_list){
667 s->drm.crtc.reset(drmModeGetCrtc(dri, crtc_id));
668 if(s->drm.crtc){
669 for(int i = 0; i < s->drm.res->count_crtcs; i++){
670 if(s->drm.res->crtcs[i] == crtc_id){
671 s->drm.crtc_index = i;
672 break;
673 }
674 }
675 break;
676 }
677 }
678 if(s->drm.crtc)
679 break;
680 }
681
682
683 if(!s->drm.crtc){
684 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to find encoder crtc pair\n");
685 return false;
686 }
687
688 if(!probe_drm_formats(s)){
689 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Failed to probe DRM supported formats\n");
690 return false;
691 }
692
693 int res = 0;
694 res = drmSetMaster(dri);
695 if(res != 0){
696 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to get DRM master. Is X11 or Wayland running?\n");
697 return false;
698 }
699
700 return true;
701}
static bool probe_drm_formats(drm_display_state *s)
Definition drm.cpp:477
Drm_encoder_uniq encoder
Definition drm.cpp:322
unsigned req_rate
Definition drm.cpp:358
std::string req_connector
Definition drm.cpp:355

References Drm_state::connector, Drm_state::crtc, Drm_state::crtc_index, Drm_state::dri_fd, drm_display_state::drm, Drm_state::encoder, get_connector_str(), get_connectors(), LOG_LEVEL_ERROR, log_msg(), MOD_NAME, mode, Drm_state::mode_info, probe_drm_formats(), drm_display_state::req_connector, drm_display_state::req_height, drm_display_state::req_rate, drm_display_state::req_width, and Drm_state::res.

Referenced by display_drm_init().

Here is the call graph for this function:

◆ swap_buffers()

static bool swap_buffers ( drm_display_state * s)
static

Definition at line 933 of file drm.cpp.

933 {
934 std::swap(s->front_buffer, s->back_buffer);
935 return set_framebuffer(s, s->front_buffer.id.get().id);
936}
Framebuffer back_buffer
Definition drm.cpp:364
Framebuffer front_buffer
Definition drm.cpp:365

References drm_display_state::back_buffer, drm_display_state::front_buffer, Framebuffer::id, and set_framebuffer().

Referenced by display_drm_putf().

Here is the call graph for this function:

Variable Documentation

◆ display_drm_info

const struct video_display_info display_drm_info
static
Initial value:
= {
NULL,
NULL,
NULL,
}
static void * display_drm_init(struct module *parent, const char *cfg, unsigned int flags)
Definition drm.cpp:842
static bool display_drm_reconfigure(void *state, struct video_desc desc)
Definition drm.cpp:1062
static void display_drm_done(void *state)
Definition drm.cpp:905
static struct video_frame * display_drm_getf(void *state)
Definition drm.cpp:917
static bool display_drm_get_property(void *state, int property, void *val, size_t *len)
Definition drm.cpp:1037
static bool display_drm_putf(void *state, struct video_frame *f, long long flags)
Definition drm.cpp:981
static void display_drm_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
Definition drm.cpp:1119

Definition at line 1125 of file drm.cpp.

1125 {
1128 NULL, // _run
1134 NULL, // _put_audio_frame
1135 NULL, // _reconfigure_audio
1136 MOD_NAME,
1137};