Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drm: add support for generic color pipeline API #1309

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 125 additions & 1 deletion src/drm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ namespace gamescope

static std::optional<CDRMAtomicProperty> Instantiate( const char *pszName, CDRMAtomicObject *pObject, const DRMObjectRawProperties& rawProperties );

uint32_t GetPropertyId() const { return m_uPropertyId; }
uint64_t GetPendingValue() const { return m_ulPendingValue; }
uint64_t GetCurrentValue() const { return m_ulCurrentValue; }
uint64_t GetInitialValue() const { return m_ulInitialValue; }
Expand Down Expand Up @@ -212,6 +213,7 @@ namespace gamescope
std::optional<CDRMAtomicProperty> AMD_PLANE_LUT3D;
std::optional<CDRMAtomicProperty> AMD_PLANE_BLEND_TF;
std::optional<CDRMAtomicProperty> AMD_PLANE_BLEND_LUT;
std::optional<CDRMAtomicProperty> COLOR_PIPELINE;
std::optional<CDRMAtomicProperty> DUMMY_END;
};
PlaneProperties &GetProperties() { return m_Props; }
Expand Down Expand Up @@ -398,14 +400,46 @@ namespace gamescope
ConnectorProperties m_Props;
};

class CDRMColorOp final : public CDRMAtomicTypedObject<DRM_MODE_OBJECT_COLOROP>
{
public:
CDRMColorOp( uint32_t uColorOpId );

void RefreshState();

struct ColorOpProperties
{
std::optional<CDRMAtomicProperty> TYPE; // Immutable
std::optional<CDRMAtomicProperty> NEXT; // Immutable
std::optional<CDRMAtomicProperty> BYPASS; // Immutable

std::optional<CDRMAtomicProperty> DATA;
std::optional<CDRMAtomicProperty> MULTIPLIER;
};
ColorOpProperties &GetProperties() { return m_Props; }
const ColorOpProperties &GetProperties() const { return m_Props; }
private:
ColorOpProperties m_Props;
};

struct CDRMColorPipeline
{
std::unique_ptr<gamescope::CDRMColorOp> degamma;
std::unique_ptr<gamescope::CDRMColorOp> CTM;
std::unique_ptr<gamescope::CDRMColorOp> HDRMult;
std::unique_ptr<gamescope::CDRMColorOp> shaper;
std::unique_ptr<gamescope::CDRMColorOp> lut3D;
std::unique_ptr<gamescope::CDRMColorOp> blend;
};

class CDRMFb final : public CBaseBackendFb
{
public:
CDRMFb( uint32_t uFbId, wlr_buffer *pClientBuffer );
~CDRMFb();

uint32_t GetFbId() const { return m_uFbId; }

private:
uint32_t m_uFbId = 0;
};
Expand Down Expand Up @@ -799,6 +833,66 @@ static bool refresh_state( drm_t *drm )
return true;
}

static std::optional<gamescope::CDRMColorPipeline> get_color_pipeline( struct drm_t *drm, uint32_t uHeadId )
{
std::vector<std::unique_ptr<gamescope::CDRMColorOp>> pipeline;

uint32_t uColorOpId = uHeadId;
while ( uColorOpId != 0 )
{
auto pColorOp = std::make_unique<gamescope::CDRMColorOp>( uHeadId );
pColorOp->RefreshState();
uColorOpId = pColorOp->GetProperties().NEXT.value().GetInitialValue();
pipeline.emplace_back( std::move(pColorOp) );
}

// Check if the pipeline has what we need
if ( pipeline.size() != 6 )
return {};
if ( pipeline[0]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_1D_CURVE )
return {};
if ( pipeline[1]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_CTM_3X4 )
return {};
if ( pipeline[2]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_MULTIPLIER )
return {};
if ( pipeline[3]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_1D_CURVE )
return {};
if ( pipeline[4]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_3D_LUT )
return {};
if ( pipeline[5]->GetProperties().TYPE.value().GetInitialValue() != DRM_COLOROP_1D_CURVE )
return {};

gamescope::CDRMColorPipeline p {
.degamma = std::move(pipeline[0]),
.CTM = std::move(pipeline[1]),
.HDRMult = std::move(pipeline[2]),
.shaper = std::move(pipeline[3]),
.lut3D = std::move(pipeline[4]),
.blend = std::move(pipeline[5]),
};
return p;
}

static bool get_plane_color_pipelines( struct drm_t *drm, std::unique_ptr< gamescope::CDRMPlane > &pPlane )
{
auto pColorPipelineProp = pPlane->GetProperties().COLOR_PIPELINE;
if ( !pColorPipelineProp )
return true;

drmModePropertyRes *pProperty = drmModeGetProperty( g_DRM.fd, pColorPipelineProp->GetPropertyId() );
if ( !pProperty )
return false;
defer( drmModeFreeProperty( pProperty ) );

for ( int i = 0; i < pProperty->count_enums; i++ )
{
auto entry = pProperty->enums[ i ];
get_color_pipeline( drm, entry.value );
}

return true;
}

static bool get_resources(struct drm_t *drm)
{
{
Expand Down Expand Up @@ -835,6 +929,12 @@ static bool get_resources(struct drm_t *drm)
}
}

for ( std::unique_ptr< gamescope::CDRMPlane > &pPlane : drm->planes )
{
if ( !get_plane_color_pipelines( drm, pPlane ) )
return false;
}

return refresh_state( drm );
}

Expand Down Expand Up @@ -1123,6 +1223,8 @@ bool init_drm(struct drm_t *drm, int width, int height, int refresh)
return false;
}

drmSetClientCap(drm->fd, DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE, 1);

if (drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &drm->cursor_width) != 0) {
drm->cursor_width = 64;
}
Expand Down Expand Up @@ -1890,6 +1992,7 @@ namespace gamescope
m_Props.AMD_PLANE_LUT3D = CDRMAtomicProperty::Instantiate( "AMD_PLANE_LUT3D", this, *rawProperties );
m_Props.AMD_PLANE_BLEND_TF = CDRMAtomicProperty::Instantiate( "AMD_PLANE_BLEND_TF", this, *rawProperties );
m_Props.AMD_PLANE_BLEND_LUT = CDRMAtomicProperty::Instantiate( "AMD_PLANE_BLEND_LUT", this, *rawProperties );
m_Props.COLOR_PIPELINE = CDRMAtomicProperty::Instantiate( "COLOR PIPELINE", this, *rawProperties );
}
}

Expand Down Expand Up @@ -2296,6 +2399,27 @@ namespace gamescope
return std::nullopt;
}

/////////////////////////
// CDRMConnector
/////////////////////////
CDRMColorOp::CDRMColorOp( uint32_t uColorOpId )
: CDRMAtomicTypedObject<DRM_MODE_OBJECT_COLOROP>( uColorOpId )
{
}

void CDRMColorOp::RefreshState()
{
auto rawProperties = GetRawProperties();
if ( rawProperties )
{
m_Props.TYPE = CDRMAtomicProperty::Instantiate( "TYPE", this, *rawProperties );
m_Props.NEXT = CDRMAtomicProperty::Instantiate( "NEXT", this, *rawProperties );
m_Props.BYPASS = CDRMAtomicProperty::Instantiate( "BYPASS", this, *rawProperties );
m_Props.DATA = CDRMAtomicProperty::Instantiate( "DATA", this, *rawProperties );
m_Props.MULTIPLIER = CDRMAtomicProperty::Instantiate( "MULTIPLIER", this, *rawProperties );
}
}

/////////////////////////
// CDRMFb
/////////////////////////
Expand Down
22 changes: 22 additions & 0 deletions src/drm_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,25 @@ enum drm_colorspace {
#define DRM_MODE_CONTENT_TYPE_PHOTO 2
#define DRM_MODE_CONTENT_TYPE_CINEMA 3
#define DRM_MODE_CONTENT_TYPE_GAME 4

#define DRM_MODE_OBJECT_COLOROP 0xfafafafa

#define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE 7

enum drm_colorop_type {
DRM_COLOROP_1D_CURVE,
DRM_COLOROP_1D_LUT,
DRM_COLOROP_CTM_3X4,
DRM_COLOROP_MULTIPLIER,
DRM_COLOROP_3D_LUT, /* TODO: check value w/ kernel */
};

enum drm_colorop_curve_1d_type {
DRM_COLOROP_1D_CURVE_SRGB_EOTF,
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
DRM_COLOROP_1D_CURVE_BT2020_INV_OETF,
DRM_COLOROP_1D_CURVE_BT2020_OETF,
DRM_COLOROP_1D_CURVE_PQ_125_EOTF,
DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF,
DRM_COLOROP_1D_CURVE_COUNT
};
Loading