Skip to content
Merged
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
605 changes: 473 additions & 132 deletions Compositor/lib/Mesa/Compositor.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Compositor/lib/Mesa/backend/src/DRM/Atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace Compositor {
namespace Backend {
class Transaction {
private:
static constexpr uint32_t DefaultDrmAtomicFlags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
static constexpr uint32_t DefaultDrmAtomicFlags = DRM_MODE_PAGE_FLIP_EVENT;

// Convert integer pixel value to DRM 16.16 fixed-point format
static constexpr uint64_t ToFixedPoint16_16(uint32_t value)
Expand Down
20 changes: 10 additions & 10 deletions Compositor/lib/Mesa/backend/src/DRM/Connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ namespace Compositor {
: _swap()
, _fd(-1)
, _activePlane(~0)
, _buffer()
, _frameId()
, _frameBuffer()
{
// Double buffering: 0=current, 1=next, swap via XOR
_buffer[0] = Core::ProxyType<Exchange::IGraphicsBuffer>();
Expand Down Expand Up @@ -129,11 +132,7 @@ namespace Compositor {
}
Compositor::DRM::Identifier Id() const
{
return _frameId[_activePlane]; // Current buffer's frame ID
}
Core::ProxyType<Exchange::IGraphicsBuffer> Buffer() const
{
return _buffer[_activePlane];
return _frameId[_activePlane];
}
void Swap()
{
Expand Down Expand Up @@ -183,7 +182,7 @@ namespace Compositor {
TRACE(Trace::Backend, ("Connector %d is not in a valid state", connectorId));
} else {
// Apply scan results
_needsModeSet = scanResult.needsModeSet;
_needsModeSet.store(scanResult.needsModeSet, std::memory_order_relaxed);
_selectedMode = scanResult.selectedMode;
_dimensionsAdjusted = scanResult.dimensionsAdjusted;
_gpuNode = scanResult.gpuNode;
Expand All @@ -201,7 +200,7 @@ namespace Compositor {

TRACE(Trace::Information, (_T("Selecting format... ")));

TRACE(Trace::Backend, ("DRM formats: %s", Compositor::ToString(drmFormats).c_str()));
TRACE(Trace::Backend, ("DRM formats: %s", Compositor::ToString(drmFormats).c_str()));
TRACE(Trace::Backend, (_T("Renderer exposes %d render formats. "), renderer->RenderFormats().size()));
TRACE(Trace::Backend, (_T("Backend accepts %d formats."), drmFormats.size()));

Expand Down Expand Up @@ -234,7 +233,8 @@ namespace Compositor {

bool NeedsModeSet() const
{
return _needsModeSet;
// no hotplug detection by design.
return _needsModeSet.exchange(false, std::memory_order_acq_rel);
}

const drmModeModeInfo* SelectedMode() const
Expand Down Expand Up @@ -335,7 +335,7 @@ namespace Compositor {
}
Core::ProxyType<Compositor::IRenderer::IFrameBuffer> FrameBuffer() const override
{
return (_frameBuffer.IsValid() == true) ? _frameBuffer.FrameBuffer() : Core::ProxyType<Compositor::IRenderer::IFrameBuffer>();
return (_frameBuffer.IsValid() == true) ? _frameBuffer.FrameBuffer() : Core::ProxyType<Compositor::IRenderer::IFrameBuffer>();
}

private:
Expand All @@ -350,7 +350,7 @@ namespace Compositor {

Compositor::IOutput::ICallback* _feedback;

bool _needsModeSet;
mutable std::atomic<bool> _needsModeSet;
drmModeModeInfo _selectedMode;
bool _dimensionsAdjusted;
};
Expand Down
12 changes: 4 additions & 8 deletions Compositor/lib/Mesa/backend/src/DRM/DRM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,11 @@ namespace Compositor {
_connectors.Visit([&](const string& /*name*/, const Core::ProxyType<Connector> connector) {
connector->Presented(0, 0); // notify connector implementation the buffer failed to display.
});
} else {
if (doModeSet) {
_firstCommit = false;
}
}

if (doModeSet) {
_firstCommit = false;
}

TRACE_GLOBAL(Trace::Information, ("Committed connectors: %u", result));
} else {
TRACE_GLOBAL(Trace::Information, ("Commit in progress, skipping commit request"));
result = Core::ERROR_INPROGRESS;
Expand All @@ -228,8 +226,6 @@ namespace Compositor {
presentationTimestamp.tv_nsec = useconds * 1000;

connector->Presented(sequence, Core::Time(presentationTimestamp).Ticks());
// TODO: Check with Bram the intention of the Release()
// connector->Release();

TRACE(Trace::Backend, ("Pageflip finished for %s", name.c_str()));
}
Expand Down
36 changes: 27 additions & 9 deletions Compositor/lib/Mesa/include/IRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace Compositor {
/**
* @brief A frame buffer represents an image used as a target for rendering.
*/
struct IFrameBuffer{
struct IFrameBuffer {
virtual ~IFrameBuffer() = default;

virtual bool IsValid() const = 0;
Expand All @@ -42,10 +42,13 @@ namespace Compositor {
* @brief A texture represents an image used as a source for rendering.
*/
struct ITexture {
using Id = uint32_t;

virtual ~ITexture() = default;

virtual bool IsValid() const = 0;

virtual Id Identifier() const = 0;
virtual uint32_t Width() const = 0;
virtual uint32_t Height() const = 0;
}; // struct ITexture
Expand All @@ -72,23 +75,35 @@ namespace Compositor {
virtual uint32_t Unbind(const Core::ProxyType<IFrameBuffer>& framebuffer) = 0;

/**
* @brief Start a render pass with the provided viewport.
*
* This should be called after a binding a buffer, callee must call
* End() when they are done rendering.
* @brief Begins recording rendering commands for the current frame.
*
* @param width Viewport width in pixels
* @param height Viewport height in pixels
* @return false on failure, in which case compositors shouldn't try rendering.
* @return false on failure
*/
virtual bool Begin(uint32_t width, uint32_t height) = 0;

/**
* @brief Ends a render pass.
* @brief Ends recording rendering commands for the current frame.
*
* After calling End(), the command buffer is closed but NOT yet submitted to GPU.
* Call Finish() to submit and wait for GPU completion.
*
* @param dump If true, captures a snapshot of the rendered frame
*/
virtual void End(bool dump = false) = 0;

/**
* @brief Submits recorded commands to GPU and waits for completion.
*
* This call blocks until all rendering commands have finished executing on the GPU.
* Must be called after End() and before committing the frame buffer to display hardware.
*
* @param timeoutMs Maximum time to wait in milliseconds (default: 100ms)
* @return uint32_t Core::ERROR_NONE if rendering completed, Core::ERROR_TIMEDOUT on timeout
*/
virtual uint32_t Finish(uint32_t timeoutMs = 100) = 0;

/**
* @brief Clear the viewport with the provided color
*
Expand Down Expand Up @@ -130,7 +145,10 @@ namespace Compositor {
* @return A proxy to the ITexture representing the texture derived from
* the provided composition buffer.
*/
virtual Core::ProxyType<ITexture> Texture(const Core::ProxyType<Exchange::IGraphicsBuffer>& buffer) = 0;
virtual Core::ProxyType<ITexture> CreateTexture(const Core::ProxyType<Exchange::IGraphicsBuffer>& buffer) = 0;


virtual void DestroyTexture(ITexture::Id id) = 0;

/**
* @brief Renders a texture on the bound buffer at the given region with
Expand All @@ -144,7 +162,7 @@ namespace Compositor {
*
* @return uint32_t Core::ERROR_NONE if all went ok, error code otherwise.
*/
virtual uint32_t Render(const Core::ProxyType<ITexture>& texture, const Exchange::IComposition::Rectangle& region, const Matrix transform, float alpha) = 0;
virtual uint32_t Render(const ITexture::Id textureId, const Exchange::IComposition::Rectangle& region, const Matrix transform, float alpha) = 0;

/**
* @brief Renders a solid quadrangle* in the specified color with the specified matrix.
Expand Down
68 changes: 41 additions & 27 deletions Compositor/lib/Mesa/renderer/src/GL/EGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,57 +295,71 @@ namespace Compositor {

EGLDeviceEXT* eglDevices = static_cast<EGLDeviceEXT*>(ALLOCA(nEglDevices * sizeof(EGLDeviceEXT)));

memset(eglDevices, 0, sizeof(nEglDevices * sizeof(EGLDeviceEXT)));
// FIXED: memset was wrong
memset(eglDevices, 0, nEglDevices * sizeof(EGLDeviceEXT));

_api.eglQueryDevicesEXT(nEglDevices, eglDevices, &nEglDevices);

if (nEglDevices > 0) {
drmDevice* drmDevice = nullptr;
int ret = drmGetDevice(drmFd, &drmDevice);
drmDevice* drmDev = nullptr;
int ret = drmGetDevice(drmFd, &drmDev);

if ((ret == 0) && (drmDevice != nullptr)) {
if ((ret == 0) && (drmDev != nullptr)) {
for (int i = 0; i < nEglDevices; i++) {
TRACE(Trace::EGL, ("Trying device %d [%p]", i, eglDevices[i]));

EGLDeviceEXT dev = eglDevices[i];
TRACE(Trace::EGL, ("Trying device %d [%p]", i, dev));

#ifdef __DEBUG__
const char* extensions = _api.eglQueryDeviceStringEXT(eglDevices[i], EGL_EXTENSIONS);
const char* extensions = _api.eglQueryDeviceStringEXT(dev, EGL_EXTENSIONS);
if (extensions != nullptr) {
TRACE(Trace::EGL, ("EGL extensions: %s", extensions));
}
#endif
const char* renderName = _api.eglQueryDeviceStringEXT(eglDevices[i], EGL_DRM_RENDER_NODE_FILE_EXT);

if (renderName != nullptr) {
const char* renderName = _api.eglQueryDeviceStringEXT(dev, EGL_DRM_RENDER_NODE_FILE_EXT);

const char* deviceName = _api.eglQueryDeviceStringEXT(dev, EGL_DRM_DEVICE_FILE_EXT);

if (renderName)
TRACE(Trace::EGL, ("EGL render node: %s", renderName));
} else {
TRACE(Trace::Error, ("No EGL render node associated to %p", eglDevices[i]));
else
TRACE(Trace::Error, ("No EGL render node associated to %p", dev));

if (deviceName)
TRACE(Trace::EGL, ("Found EGL device %s", deviceName));
else {
TRACE(Trace::Error, ("No EGL device name returned for %p", dev));
continue;
}

const char* deviceName = _api.eglQueryDeviceStringEXT(eglDevices[i], EGL_DRM_DEVICE_FILE_EXT);
bool nodePresent(false);
bool renderMatch = false;
bool primaryMatch = false;

if (deviceName == nullptr) {
TRACE(Trace::Error, ("No EGL device name returned for %p", eglDevices[i]));
continue;
} else {
TRACE(Trace::EGL, ("Found EGL device %s", deviceName));
// Prefer matching render node
if (renderName && (drmDev->available_nodes & (1 << DRM_NODE_RENDER)) && strcmp(drmDev->nodes[DRM_NODE_RENDER], renderName) == 0) {
renderMatch = true;
}

for (uint16_t i = 0; i < DRM_NODE_MAX; i++) {
if ((drmDevice->available_nodes & (1 << i)) && (strcmp(drmDevice->nodes[i], deviceName) == 0)) {
nodePresent = true;
break;
}
}
// Then fallback to primary node
if (deviceName && (drmDev->available_nodes & (1 << DRM_NODE_PRIMARY)) && strcmp(drmDev->nodes[DRM_NODE_PRIMARY], deviceName) == 0) {
primaryMatch = true;
}

if (renderMatch) {
TRACE(Trace::EGL, ("Using EGL device (render node): %s", renderName));
result = dev;
break;
}

if ((deviceName != nullptr) && (nodePresent == true)) {
TRACE(Trace::EGL, ("Using EGL device %s", deviceName));
result = eglDevices[i];
if (primaryMatch) {
TRACE(Trace::EGL, ("Using EGL device (primary node fallback): %s", deviceName));
result = dev;
break;
}
}

drmFreeDevice(&drmDevice);
drmFreeDevice(&drmDev);
} else {
TRACE(Trace::Error, ("No DRM devices found"));
}
Expand Down
45 changes: 45 additions & 0 deletions Compositor/lib/Mesa/renderer/src/GL/EGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,51 @@ namespace Compositor {
EGLSurface _readSurface;
};

void DestroySync(EGLSync& sync) const
{
if (sync != EGL_NO_SYNC && _api.eglDestroySync != nullptr) {
_api.eglDestroySync(_display, sync);
sync = EGL_NO_SYNC;
}
}

EGLSync CreateSync() const
{
EGLSync sync = EGL_NO_SYNC;

if (_api.eglCreateSync != nullptr) {
sync = _api.eglCreateSync(_display, EGL_SYNC_FENCE, nullptr);
}

return sync;
}

EGLint WaitSync(EGLSync& sync, const EGLTime timeoutNs = EGL_FOREVER) const
{
EGLint status = EGL_UNSIGNALED;

if (sync != EGL_NO_SYNC && _api.eglWaitSync != nullptr) {
status = _api.eglClientWaitSync(_display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT, timeoutNs);
}

return status;
}

int ExportSyncAsFd(EGLSync sync) const
{
int fd = -1;

if (sync != EGL_NO_SYNC && _api.eglDupNativeFenceFDANDROID != nullptr) {
fd = _api.eglDupNativeFenceFDANDROID(_display, sync);

if (fd < 0) {
TRACE(Trace::Error, ("Failed to export sync as fd: 0x%x", eglGetError()));
}
}

return fd;
}

private:
EGLDeviceEXT FindEGLDevice(const int drmFd);
uint32_t Initialize(EGLenum platform, void* remote_display, bool isMaster);
Expand Down
Loading
Loading