Skip to content

Commit

Permalink
Merge pull request #14097 from lrusak/drm-modifiers
Browse files Browse the repository at this point in the history
[linux] windowing/gbm: add drm modifiers
  • Loading branch information
lrusak committed Aug 3, 2018
2 parents ca8e010 + b894d4b commit 1012f78
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 12 deletions.
11 changes: 11 additions & 0 deletions cmake/modules/FindGBM.cmake
Expand Up @@ -39,13 +39,24 @@ check_c_source_compiles("#include <gbm.h>
}
" GBM_HAS_BO_MAP)

check_c_source_compiles("#include <gbm.h>
int main()
{
gbm_surface_create_with_modifiers(NULL, 0, 0, 0, NULL, 0);
}
" GBM_HAS_MODIFIERS)

if(GBM_FOUND)
set(GBM_LIBRARIES ${GBM_LIBRARY})
set(GBM_INCLUDE_DIRS ${GBM_INCLUDE_DIR})
set(GBM_DEFINITIONS -DHAVE_GBM=1)
if(GBM_HAS_BO_MAP)
list(APPEND GBM_DEFINITIONS -DHAS_GBM_BO_MAP=1)
endif()
if(GBM_HAS_MODIFIERS)
list(APPEND GBM_DEFINITIONS -DHAS_GBM_MODIFIERS=1)
endif()
if(NOT TARGET GBM::GBM)
add_library(GBM::GBM UNKNOWN IMPORTED)
set_target_properties(GBM::GBM PROPERTIES
Expand Down
4 changes: 4 additions & 0 deletions xbmc/utils/GBMBufferObject.cpp
Expand Up @@ -80,5 +80,9 @@ int CGBMBufferObject::GetStride()

uint64_t CGBMBufferObject::GetModifier()
{
#if defined(HAS_GBM_MODIFIERS)
return gbm_bo_get_modifier(m_bo);
#else
return 0;
#endif
}
85 changes: 76 additions & 9 deletions xbmc/windowing/gbm/DRMUtils.cpp
Expand Up @@ -93,22 +93,40 @@ drm_fb * CDRMUtils::DrmFbGetFromBo(struct gbm_bo *bo)
strides[4] = {0},
offsets[4] = {0};

uint64_t modifiers[4] = {0};

width = gbm_bo_get_width(bo);
height = gbm_bo_get_height(bo);

#if defined(HAS_GBM_MODIFIERS)
for (int i = 0; i < gbm_bo_get_plane_count(bo); i++)
{
handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
offsets[i] = gbm_bo_get_offset(bo, i);
modifiers[i] = gbm_bo_get_modifier(bo);
}
#else
handles[0] = gbm_bo_get_handle(bo).u32;
strides[0] = gbm_bo_get_stride(bo);
memset(offsets, 0, 16);
#endif

if (modifiers[0] == DRM_FORMAT_MOD_INVALID)
modifiers[0] = DRM_FORMAT_MOD_LINEAR;

auto ret = drmModeAddFB2(m_fd,
width,
height,
fb->format,
handles,
strides,
offsets,
&fb->fb_id,
0);
CLog::Log(LOGDEBUG, "CDRMUtils::%s - using modifier: %lli", __FUNCTION__, modifiers[0]);

auto ret = drmModeAddFB2WithModifiers(m_fd,
width,
height,
fb->format,
handles,
strides,
offsets,
modifiers,
&fb->fb_id,
(modifiers[0] > 0) ? DRM_MODE_FB_MODIFIERS : 0);

if(ret)
{
Expand Down Expand Up @@ -402,6 +420,11 @@ bool CDRMUtils::FindPlanes()
CLog::Log(LOGERROR, "CDRMUtils::%s - could not get primary plane %u properties: %s", __FUNCTION__, m_primary_plane->plane->plane_id, strerror(errno));
return false;
}

if (!FindModifiersForPlane(m_primary_plane))
{
CLog::Log(LOGDEBUG, "CDRMUtils::%s - no drm modifiers present for the primary plane", __FUNCTION__);
}
}

// overlay plane should always be available
Expand All @@ -411,6 +434,50 @@ bool CDRMUtils::FindPlanes()
return false;
}

if (!FindModifiersForPlane(m_overlay_plane))
{
CLog::Log(LOGDEBUG, "CDRMUtils::%s - no drm modifiers present for the overlay plane", __FUNCTION__);
}

return true;
}

bool CDRMUtils::FindModifiersForPlane(struct plane *object)
{
uint64_t blob_id = 0;

for (uint32_t i = 0; i < object->props->count_props; i++)
{
if (strcmp(object->props_info[i]->name, "IN_FORMATS") == 0)
blob_id = object->props->prop_values[i];
}

if (blob_id == 0)
return false;

drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(m_fd, blob_id);
if (!blob)
return false;

drm_format_modifier_blob *header = static_cast<drm_format_modifier_blob*>(blob->data);
uint32_t *formats = reinterpret_cast<uint32_t*>(reinterpret_cast<char*>(header) + header->formats_offset);
drm_format_modifier *mod = reinterpret_cast<drm_format_modifier*>(reinterpret_cast<char*>(header) + header->modifiers_offset);

for (uint32_t i = 0; i < header->count_formats; i++)
{
std::vector<uint64_t> modifiers;
for (uint32_t j = 0; j < header->count_modifiers; j++)
{
if (mod[j].formats & 1ULL << i)
modifiers.emplace_back(mod[j].modifier);
}

object->modifiers_map.emplace(formats[i], modifiers);
}

if (blob)
drmModeFreePropertyBlob(blob);

return true;
}

Expand Down
5 changes: 5 additions & 0 deletions xbmc/windowing/gbm/DRMUtils.h
Expand Up @@ -12,6 +12,7 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <gbm.h>
#include <map>
#include <vector>

#include "windowing/Resolution.h"
Expand All @@ -35,6 +36,7 @@ struct plane : drm_object
{
drmModePlanePtr plane = nullptr;
uint32_t format = DRM_FORMAT_XRGB8888;
std::map<uint32_t, std::vector<uint64_t>> modifiers_map;
};

struct connector : drm_object
Expand Down Expand Up @@ -75,6 +77,8 @@ class CDRMUtils
int GetFileDescriptor() const { return m_fd; }
struct plane* GetPrimaryPlane() const { return m_primary_plane; }
struct plane* GetOverlayPlane() const { return m_overlay_plane; }
std::vector<uint64_t> *GetPrimaryPlaneModifiersForFormat(uint32_t format) { return &m_primary_plane->modifiers_map[format]; }
std::vector<uint64_t> *GetOverlayPlaneModifiersForFormat(uint32_t format) { return &m_overlay_plane->modifiers_map[format]; }
struct crtc* GetCrtc() const { return m_crtc; }

virtual RESOLUTION_INFO GetCurrentMode();
Expand Down Expand Up @@ -112,6 +116,7 @@ class CDRMUtils
bool FindEncoder();
bool FindCrtc();
bool FindPlanes();
bool FindModifiersForPlane(struct plane *object);
bool FindPreferredMode();
bool RestoreOriginalMode();
static void DrmFbDestroyCallback(struct gbm_bo *bo, void *data);
Expand Down
11 changes: 10 additions & 1 deletion xbmc/windowing/gbm/GBMUtils.cpp
Expand Up @@ -36,16 +36,25 @@ void CGBMUtils::DestroyDevice()
}
}

bool CGBMUtils::CreateSurface(int width, int height)
bool CGBMUtils::CreateSurface(int width, int height, const uint64_t *modifiers, const int modifiers_count)
{
if (m_surface)
CLog::Log(LOGWARNING, "CGBMUtils::%s - surface already created", __FUNCTION__);

#if defined(HAS_GBM_MODIFIERS)
m_surface = gbm_surface_create_with_modifiers(m_device,
width,
height,
GBM_FORMAT_ARGB8888,
modifiers,
modifiers_count);
#else
m_surface = gbm_surface_create(m_device,
width,
height,
GBM_FORMAT_ARGB8888,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
#endif

if (!m_surface)
{
Expand Down
2 changes: 1 addition & 1 deletion xbmc/windowing/gbm/GBMUtils.h
Expand Up @@ -17,7 +17,7 @@ class CGBMUtils
~CGBMUtils() = default;
bool CreateDevice(int fd);
void DestroyDevice();
bool CreateSurface(int width, int height);
bool CreateSurface(int width, int height, const uint64_t *modifiers, const int modifiers_count);
void DestroySurface();
struct gbm_bo *LockFrontBuffer();
void ReleaseBuffer();
Expand Down
4 changes: 3 additions & 1 deletion xbmc/windowing/gbm/WinSystemGbm.cpp
Expand Up @@ -127,7 +127,9 @@ bool CWinSystemGbm::CreateNewWindow(const std::string& name,
return false;
}

if(!m_GBM->CreateSurface(res.iWidth, res.iHeight))
std::vector<uint64_t> *modifiers = m_DRM->GetOverlayPlaneModifiersForFormat(m_DRM->GetOverlayPlane()->format);

if (!m_GBM->CreateSurface(res.iWidth, res.iHeight, modifiers->data(), modifiers->size()))
{
CLog::Log(LOGERROR, "CWinSystemGbm::%s - failed to initialize GBM", __FUNCTION__);
return false;
Expand Down

1 comment on commit 1012f78

@mrfixit2001
Copy link

@mrfixit2001 mrfixit2001 commented on 1012f78 Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't appear all GPU drivers support the drm modifiers yet. For example, the latest available Mali drivers from ARM do not include "gbm_bo_get_offset" and "gbm_surface_create_with_modifiers". So compiling on those systems will fail with this commit unless they use MESA.

Reviewing the source, looks like maybe adding these conf options will bypass?
-DGBM_HAS_MODIFIERS=0
-DGBM_HAS_BO_MAP=0

Please sign in to comment.