RAMSES Documentation  27.0.130
Information for RAMSES users and developers
ramses-example-local-dma-offscreenbuffer/src/main.cpp

DMA Offscreen Buffer Example The example demonstrates a realistic usecase of DMA offscreen buffers, where a stream texture provided by a wayland client to the embedded compositor gets processed on CPU side and the result image is calculated on CPU.

The example creates the following setup: A renderer with four DMA OBs and two local scenes:

The example additionally demonstates the following points :

// -------------------------------------------------------------------------
// Copyright (C) 2021 BMW AG
// -------------------------------------------------------------------------
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------------
#include "ramses-client.h"
#include "ramses-utils.h"
#include <unordered_set>
#include <unordered_map>
#include <thread>
#include <cstring>
#include <sys/mman.h>
#include <unistd.h>
#include "linux/dma-buf.h"
#include "linux/ioctl.h"
#include <sys/ioctl.h>
#include <drm_fourcc.h>
#include <gbm.h>
//parameters to control the example
static constexpr ramses::waylandIviSurfaceId_t CompositingSurfaceId{ 789u };
static constexpr uint32_t OffscreenBufferWidth = 200u;
static constexpr uint32_t OffscreenBufferHeight = 200u;
static constexpr uint32_t DisplayWidth = 800u;
static constexpr uint32_t DisplayHeight = 800u;
static constexpr uint32_t DmaBufferFourccFormat = DRM_FORMAT_ARGB8888;
static constexpr std::chrono::seconds ExampleRunDuration{ 60u };
static constexpr bool ExampleTakeScreenshots = false;
constexpr const char* const vertexShader = R"##(
#version 300 es
in lowp vec3 a_position;
in lowp vec2 a_texcoord;
out lowp vec2 v_texcoord;
uniform lowp mat4 mvpMatrix;
void main()
{
v_texcoord = a_texcoord;
gl_Position = mvpMatrix * vec4(a_position, 1.0);
}
)##";
constexpr const char* const fragmentShader = R"##(
#version 300 es
uniform sampler2D textureSampler;
in lowp vec2 v_texcoord;
out lowp vec4 fragColor;
void main(void)
{
fragColor = texture(textureSampler, v_texcoord);
}
)##";
//Helper class to simplify handling renderer events.
//The class blocks queries waiting for events and loops until expected event is reached or timesout
{
public:
: m_renderer(renderer)
{
}
virtual void framebufferPixelsRead(const uint8_t* pixelData, const uint32_t pixelDataSize, ramses::displayId_t, ramses::displayBufferId_t, ramses::ERendererEventResult result) override
{
{
static uint32_t filePostifx = 0u;
const std::string fileName = "./dmaBufExampleScreenshot_" + std::to_string(filePostifx++) + ".png";
if(!ramses::RamsesUtils::SaveImageBufferToPng(fileName, {pixelData, pixelData + pixelDataSize}, DisplayWidth, DisplayHeight))
printf("Error: Failed saving screenshot to %s !!\n", fileName.c_str());
else
printf("Saved screenshot to %s\n", fileName.c_str());
}
else
printf("Error: Failed read pixels!!\n");
}
virtual void sceneStateChanged(ramses::sceneId_t sceneId, ramses::RendererSceneState state) override
{
m_scenes[sceneId].state = state;
}
virtual void displayCreated(ramses::displayId_t displayId, ramses::ERendererEventResult result) override
{
{
m_createdDisplays.insert(displayId);
}
}
virtual void offscreenBufferCreated(ramses::displayId_t, ramses::displayBufferId_t offscreenBufferId, ramses::ERendererEventResult result) override
{
{
m_createdOffscreenBuffers.insert(offscreenBufferId);
}
}
{
if (success)
{
m_scenesConsumingOffscreenBuffer[consumerScene].state = ramses::RendererSceneState::Unavailable;
}
}
void waitForDisplayCreated(const ramses::displayId_t displayId)
{
waitForElementInSet(displayId, m_createdDisplays);
}
void waitForOffscreenBufferCreated(const ramses::displayBufferId_t offscreenBufferId)
{
waitForElementInSet(offscreenBufferId, m_createdOffscreenBuffers);
}
void waitForOffscreenBufferLinkedToConsumingScene(const ramses::sceneId_t sceneId)
{
waitUntilOrTimeout([&] {return m_scenesConsumingOffscreenBuffer.count(sceneId) > 0; });
}
void waitForSceneState(ramses::sceneId_t sceneId, ramses::RendererSceneState state)
{
waitUntilOrTimeout([&] { return m_scenes[sceneId].state == state; });
}
bool waitUntilOrTimeout(const std::function<bool()>& conditionFunction)
{
const std::chrono::steady_clock::time_point timeoutTS = std::chrono::steady_clock::now() + std::chrono::seconds{ 5 };
while (!conditionFunction() && std::chrono::steady_clock::now() < timeoutTS)
{
m_renderer.doOneLoop();
m_renderer.dispatchEvents(*this);
m_renderer.getSceneControlAPI()->dispatchEvents(*this);
}
const auto result = conditionFunction();
if(!result)
printf("Error: timed out waiting for state/condition!\n");
return result;
}
private:
struct SceneInfo
{
};
using SceneSet = std::unordered_map<ramses::sceneId_t, SceneInfo>;
using DataConsumerSet = std::unordered_set<ramses::dataConsumerId_t>;
using DisplaySet = std::unordered_set<ramses::displayId_t>;
using OffscreenBufferSet = std::unordered_set<ramses::displayBufferId_t>;
template <typename T>
void waitForElementInSet(const T element, const std::unordered_set<T>& set)
{
while (set.find(element) == set.end())
{
m_renderer.doOneLoop();
m_renderer.dispatchEvents(*this);
m_renderer.getSceneControlAPI()->dispatchEvents(*this);
std::this_thread::sleep_for(std::chrono::milliseconds(10u));
}
}
SceneSet m_scenes;
SceneSet m_scenesAssignedToOffscreenBuffer;
SceneSet m_scenesConsumingOffscreenBuffer;
DisplaySet m_createdDisplays;
OffscreenBufferSet m_createdOffscreenBuffers;
DataConsumerSet m_dataConsumers;
};
ramses::Effect& createEffect(ramses::Scene& scene, const std::string& effectName)
{
return *scene.createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, effectName.c_str());
}
{
const uint16_t indicesArray[] = { 0, 1, 2, 2, 1, 3 };
const ramses::ArrayResource* indices = scene.createArrayResource(ramses::EDataType::UInt16, 6, indicesArray);
const float vertexPositionsArray[] =
{
-1.f, -1.f, 0.f,
1.f, -1.f, 0.f,
-1.f, 1.f, 0.f,
1.f, 1.f, 0.f
};
const ramses::ArrayResource* vertexPositions = scene.createArrayResource(ramses::EDataType::Vector3F, 4, vertexPositionsArray);
const float textureCoordsArray[] = { 0.f, 1.f, 1.f, 1.f, 0.f, 0.f, 1.f, 0.f };
const ramses::ArrayResource* textureCoords = scene.createArrayResource(ramses::EDataType::Vector2F, 4, textureCoordsArray);
ramses::Appearance* appearance = scene.createAppearance(effect, "quad appearance");
ramses::GeometryBinding* geometry = scene.createGeometryBinding(effect, "quad geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effect.findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
ramses::AttributeInput texCoordsInput;
effect.findAttributeInput("a_texcoord", texCoordsInput);
geometry->setInputBuffer(texCoordsInput, *textureCoords);
ramses::MeshNode* meshNode = scene.createMeshNode();
meshNode->setAppearance(*appearance);
meshNode->setGeometryBinding(*geometry);
ramses::UniformInput textureInput;
effect.findUniformInput("textureSampler", textureInput);
appearance->setInputTexture(textureInput, textureSampler);
return *meshNode;
}
ramses::Scene& createMainScene(ramses::RamsesClient& client, ramses::sceneId_t sceneId, ramses::waylandIviSurfaceId_t streamId, const std::string& processingOutputSamplerName)
{
//scene consists of two quads with textures
//the left quad is stream tex input rendered as is
//the right quad is output result from processing input (from two frames ago)
ramses::Scene* clientScene = client.createScene(sceneId, ramses::SceneConfig(), "main scene");
ramses::OrthographicCamera* camera = clientScene->createOrthographicCamera("main scene camera");
camera->setTranslation(0.0f, 0.0f, 5.0f);
camera->setFrustum(-2.f, 2.f, -2.f, 2.f, 0.1f, 100.f);
ramses::RenderPass* renderPass = clientScene->createRenderPass("main scene render pass");
renderPass->setCamera(*camera);
ramses::RenderGroup* renderGroup = clientScene->createRenderGroup();
renderPass->addRenderGroup(*renderGroup);
ramses::Effect& effect = createEffect(*clientScene, "quad effect main scene");
// Create fallback texture to show when sampler not linked to an offscreen buffer
ramses::Texture2D& fallbackTexture = *ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-example-dma-offscreenbuffer-fallback.png", *clientScene);
ramses::StreamTexture& streamTexture = *clientScene->createStreamTexture(fallbackTexture, streamId, "main scene composited tex sampler");
streamTexture,
"mainSceneStreamTexSampler");
auto& meshCompositedTexture = createQuadWithTexture(*clientScene, effect, streamtextureSampler);
meshCompositedTexture.setTranslation(-1.f, 0.f, 0.f);
renderGroup->addMeshNode(meshCompositedTexture);
fallbackTexture,
1u,
processingOutputSamplerName.c_str());
auto& meshOutputTexture = createQuadWithTexture(*clientScene, effect, outputTextureSampler);
meshOutputTexture.setTranslation(1.f, 0.f, 0.f);
renderGroup->addMeshNode(meshOutputTexture);
return *clientScene;
}
{
//scene consists of one quad with a the stream texture that fills whole OB where scene is rendered
ramses::Scene* clientScene = client.createScene(sceneId, ramses::SceneConfig(), "source scene");
ramses::OrthographicCamera* camera = clientScene->createOrthographicCamera("source scene camera");
camera->setTranslation(0.0f, 0.0f, 5.0f);
camera->setFrustum(-1.f, 1.f, -1.f, 1.f, 0.1f, 100.f);
camera->setViewport(0, 0u, OffscreenBufferWidth, OffscreenBufferHeight);
ramses::RenderPass* renderPass = clientScene->createRenderPass("source scene pass");
renderPass->setCamera(*camera);
ramses::RenderGroup* renderGroup = clientScene->createRenderGroup();
renderPass->addRenderGroup(*renderGroup);
ramses::Effect& effect = createEffect(*clientScene, "quad effect source scene");
// Create fallback texture to show when sampler not linked to an offscreen buffer
ramses::Texture2D& fallbackTexture = *ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-example-dma-offscreenbuffer-fallback.png", *clientScene);
ramses::StreamTexture& streamTexture = *clientScene->createStreamTexture(fallbackTexture, streamId, "source composited tex sampler");
streamTexture,
"source stream tex sampler");
auto& meshCompositedTexture = createQuadWithTexture(*clientScene, effect, streamtextureSampler);
renderGroup->addMeshNode(meshCompositedTexture);
return *clientScene;
}
struct BufferInfo
{
int fd = -1;
uint32_t stride = 0u;
std::size_t bufferSize = 0u;
void* mappedMem = nullptr;
};
std::unordered_map<ramses::displayBufferId_t, BufferInfo> bufferInfoMap;
{
constexpr uint32_t usageFlags = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT;
constexpr uint64_t modifier = DRM_FORMAT_MOD_INVALID;
const auto bufferId = renderer.createDmaOffscreenBuffer(display, OffscreenBufferWidth, OffscreenBufferHeight, DmaBufferFourccFormat, usageFlags, modifier);
if(!bufferId.isValid())
printf("Error: Failed creating offscreen buffer!\n");
return bufferId;
}
bool mapDmaOffscreenBuffer(ramses::RamsesRenderer& renderer, ramses::displayId_t display, ramses::displayBufferId_t displayBuffer, bool readyOnly)
{
errno = 0;
if(bufferInfoMap.find(displayBuffer) != bufferInfoMap.cend())
{
printf("Error: Buffer already mapped!\n");
return false;
}
int bufferFD = -1;
uint32_t bufferStride = 0;
if(renderer.getDmaOffscreenBufferFDAndStride(display, displayBuffer, bufferFD, bufferStride) != ramses::StatusOK)
{
printf("Error: Failed to get FD and stride!\n");
return false;
}
const std::size_t fileSize = static_cast<std::size_t>(lseek(bufferFD, 0u, SEEK_END));
const auto mappingPreviliges = (readyOnly? (PROT_READ) : (PROT_WRITE | PROT_READ));
void* mappedMemory = mmap(nullptr, fileSize, mappingPreviliges, MAP_SHARED, bufferFD, 0u);
if(mappedMemory == MAP_FAILED)
{
const auto errorValue = errno;
printf("Error: Failed to map memory (errno=%i, errnoString=%s)!\n", errorValue, strerror(errorValue));
return false;
}
printf("Mapped OB %u with FD %i successfully to %p\n", displayBuffer.getValue(), bufferFD, mappedMemory);
bufferInfoMap[displayBuffer] = {bufferFD, bufferStride, fileSize, mappedMemory};
return true;
}
{
const auto bufferInfoIt = bufferInfoMap.find(displayBuffer);
if(bufferInfoIt == bufferInfoMap.cend())
{
printf("Error: Failed to find buffer for start sync!\n");
return false;
}
dma_buf_sync syncStartFlags = { 0 };
syncStartFlags.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
const auto syncStartResult = ioctl(bufferInfoIt->second.fd, DMA_BUF_IOCTL_SYNC, &syncStartFlags);
if(syncStartResult != 0)
{
printf("Error: Failed to start sync!\n");
return false;
}
return true;
}
{
const auto bufferInfoIt = bufferInfoMap.find(displayBuffer);
if(bufferInfoIt == bufferInfoMap.cend())
{
printf("Error: Failed to find buffer for end sync!\n");
return false;
}
dma_buf_sync syncEndFlags = { 0 };
syncEndFlags.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
const auto syncEndResult = ioctl(bufferInfoIt->second.fd, DMA_BUF_IOCTL_SYNC, &syncEndFlags);
if(syncEndResult != 0)
{
printf("Failed to end sync!\n");
return false;
}
return true;
}
{
const auto& inputBufferInfo = bufferInfoMap.find(inputBuffer)->second;
const auto& outputBufferInfo = bufferInfoMap.find(outputBuffer)->second;
const auto bufferStride = inputBufferInfo.stride;
if(!startBufferAccess(inputBuffer))
return false;
if(!startBufferAccess(outputBuffer))
return false;
for(uint32_t row = 0u; row < OffscreenBufferHeight; ++row)
{
for(uint32_t col = 0u; col < OffscreenBufferWidth; ++col)
{
uint8_t* inputPixelMem = reinterpret_cast<uint8_t*>(inputBufferInfo.mappedMem) + row * bufferStride + col * 4u;
uint8_t* outputPixelMem = reinterpret_cast<uint8_t*>(outputBufferInfo.mappedMem) + row * bufferStride + col * 4u;
//Magic values for demonestrating noticeable change in several color channels
const float magicValue1 = 1.f * col / OffscreenBufferWidth;
const uint16_t magicValue2 = uint8_t(255.f * col / OffscreenBufferWidth);
const uint8_t magicValue3 = uint8_t(255.f * row / OffscreenBufferHeight);
switch (DmaBufferFourccFormat)
{
case DRM_FORMAT_ARGB8888: //ARGB little endian
outputPixelMem[0] = inputPixelMem[0]; //Blue channel
outputPixelMem[1] = std::min<uint8_t>(uint8_t(magicValue1 * inputPixelMem[1]), 255u); //Green channel
outputPixelMem[2] = uint8_t(std::min<uint16_t>(magicValue2 + inputPixelMem[2], 255u)); //Red channel
outputPixelMem[3] = magicValue3; //Alpha channel
break;
default:
printf("Error: Unsupported format!\n");
return false;
}
}
}
if(!endBufferAccess(inputBuffer))
return false;
if(!endBufferAccess(outputBuffer))
return false;
return true;
}
int main(int argc, char* argv[])
{
ramses::RamsesFrameworkConfig config(argc, argv);
ramses::RamsesFramework framework(config);
ramses::RamsesClient& client(*framework.createClient("ramses-example-local-dma-offscreenbuffer"));
ramses::RendererConfig rendererConfig(argc, argv);
//Set big enough max frame poll time in order to wait for every frame to finish
//This is essential to avoid skipping any frames
rendererConfig.setFrameCallbackMaxPollTime(66000);
ramses::RamsesRenderer& renderer(*framework.createRenderer(rendererConfig));
auto& sceneControlAPI = *renderer.getSceneControlAPI();
framework.connect();
//avoid skipping any frames
SceneStateEventHandler eventHandler(renderer);
//Create display and OBs
ramses::DisplayConfig displayConfig(argc, argv);
displayConfig.setWindowRectangle(0, 0, DisplayWidth, DisplayHeight);
displayConfig.setPlatformRenderNode("/dev/dri/renderD128");
const ramses::displayId_t display = renderer.createDisplay(displayConfig);
renderer.flush();
eventHandler.waitForDisplayCreated(display);
//to simulate double buffering using OBs for reading
const ramses::displayBufferId_t dmaOffscreenBufferRead1 = createDmaOffscreenBuffer(renderer, display);
const ramses::displayBufferId_t dmaOffscreenBufferRead2 = createDmaOffscreenBuffer(renderer, display);
ramses::displayBufferId_t backDMAReadBufferId = dmaOffscreenBufferRead1;
ramses::displayBufferId_t frontDmaReadBufferId = dmaOffscreenBufferRead2;
//to simulate double/tripple buffering using OBs for writing
//Note: double buffering for write buffers "might" not be enough depending on image processing latency,
//because once an OB is linked as input to a texture consumer, two loops must pass before safely writing into that OB again
//so it is possible to have a constellation where:
// one OB is needed since it has ready output for next call to doOneLoop (image processing just finished)
// one OB is needed since it is still in use from previous call to doOneLoop (previous output from CV that is currently rendered)
// one OB is needed to be passed to image processing for writing
const ramses::displayBufferId_t dmaOffscreenBufferWrite1 = createDmaOffscreenBuffer(renderer, display);
const ramses::displayBufferId_t dmaOffscreenBufferWrite2 = createDmaOffscreenBuffer(renderer, display);
ramses::displayBufferId_t backDMAWriteBufferId = dmaOffscreenBufferWrite1;
ramses::displayBufferId_t frontDmaWriteBufferId = dmaOffscreenBufferWrite2;
renderer.flush();
eventHandler.waitForOffscreenBufferCreated(dmaOffscreenBufferRead1);
eventHandler.waitForOffscreenBufferCreated(dmaOffscreenBufferRead2);
eventHandler.waitForOffscreenBufferCreated(dmaOffscreenBufferWrite1);
eventHandler.waitForOffscreenBufferCreated(dmaOffscreenBufferWrite2);
//map DMA OBs once in beginning and keep the mapping as long as the OBs memory
//need to be accesed on CPU
if(!mapDmaOffscreenBuffer(renderer, display, dmaOffscreenBufferRead1, true))
return 1;
if(!mapDmaOffscreenBuffer(renderer, display, dmaOffscreenBufferRead2, true))
return 1;
if(!mapDmaOffscreenBuffer(renderer, display, dmaOffscreenBufferWrite1, false))
return 1;
if(!mapDmaOffscreenBuffer(renderer, display, dmaOffscreenBufferWrite2, false))
return 1;
printf("\n************* All OBs mapped successfully !! **********\n");
//disable clearing for OBs in order to control when does content get overwritten
//for example, the content of the write OBs (final result after processing) is written to memory
//on CPU side, so GPU should not clear that content while rendering
renderer.flush();
const ramses::dataConsumerId_t samplerConsumerId(457u);
const ramses::sceneId_t mainSceneId{1u};
const std::string& processingOutputSamplerName = "processingOutputTexSampler";
ramses::Scene& mainScene = createMainScene(client, mainSceneId, CompositingSurfaceId, processingOutputSamplerName);
const ramses::TextureSampler& processingOutputSampler = *ramses::RamsesUtils::TryConvert<ramses::TextureSampler>(*mainScene.findObjectByName(processingOutputSamplerName.c_str()));
mainScene.createTextureConsumer(processingOutputSampler, samplerConsumerId);
mainScene.flush();
mainScene.publish();
sceneControlAPI.setSceneMapping(mainSceneId, display);
sceneControlAPI.setSceneState(mainSceneId, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
eventHandler.waitForSceneState(mainSceneId, ramses::RendererSceneState::Rendered);
const ramses::sceneId_t sourceSceneId{2u};
ramses::Scene& sourceScene = createSourceScene(client, sourceSceneId, CompositingSurfaceId);
sourceScene.flush();
sourceScene.publish();
sceneControlAPI.setSceneMapping(sourceSceneId, display);
sceneControlAPI.setSceneState(sourceSceneId, ramses::RendererSceneState::Rendered);
sceneControlAPI.setSceneDisplayBufferAssignment(sourceSceneId, backDMAReadBufferId);
sceneControlAPI.flush();
const auto exampleStartTime = std::chrono::steady_clock::now();
while ((std::chrono::steady_clock::now() - exampleStartTime) < ExampleRunDuration)
{
if(ExampleTakeScreenshots)
{
renderer.readPixels(display, renderer.getDisplayFramebuffer(display), 0u, 0u, DisplayWidth, DisplayHeight);
renderer.flush();
}
//Consume input from current "read OB" and write image processing result to current "write OB"
doProcessing(backDMAReadBufferId, backDMAWriteBufferId);
sceneControlAPI.setSceneDisplayBufferAssignment(sourceSceneId, backDMAReadBufferId);
sceneControlAPI.linkOffscreenBuffer(backDMAWriteBufferId, mainSceneId, samplerConsumerId);
sceneControlAPI.flush();
renderer.doOneLoop();
renderer.dispatchEvents(eventHandler);
std::swap(backDMAReadBufferId, frontDmaReadBufferId);
std::swap(backDMAWriteBufferId, frontDmaWriteBufferId);
}
//unmap buffers after they do not need to be accessed from CPU
for(const auto& bufferInfo : bufferInfoMap)
{
errno = 0;
const auto result = munmap(bufferInfo.second.mappedMem, bufferInfo.second.bufferSize);
if(result == -1)
{
const auto errorValue = errno;
printf("Error: Failed to unmap memory for OB %u (errno=%i, errnoString=%s)!\n", bufferInfo.first.getValue(), errorValue, strerror(errorValue));
return 1;
}
printf("Unmapped OB %u with FD %i successfully!\n", bufferInfo.first.getValue(), bufferInfo.second.fd);
}
printf("\n************* All OBs unmapped successfully !! **********\n");
return 0;
}
Definition: main.cpp:48
SceneStateEventHandler(ramses::RendererSceneControl &sceneControlApi, ramses::RamsesRenderer &renderer)
Definition: main.cpp:50
The Appearance describes how an object should look like. This includes GLSL uniform values,...
Definition: Appearance.h:34
status_t setInputTexture(const UniformInput &input, const TextureSampler &textureSampler)
Sets texture sampler to the input.
The ArrayResource stores a data array of a given type. The data is immutable. The resource can be use...
Definition: ArrayResource.h:26
The AttributeInput is a description of an attribute effect input.
Definition: AttributeInput.h:22
status_t setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height)
Sets the viewport to be used when rendering with this camera.
status_t setFrustum(float leftPlane, float rightPlane, float bottomPlane, float topPlane, float nearPlane, float farPlane)
Sets camera frustum planes of the Camera.
The DisplayConfig holds a set of parameters to be used to initialize a display.
Definition: DisplayConfig.h:22
An effect description holds all necessary information for an effect to be created.
Definition: EffectDescription.h:21
status_t setVertexShader(const char *shaderSource)
Sets vertex shader source from string.
status_t setFragmentShader(const char *shaderSource)
Sets fragment shader source from string.
status_t setUniformSemantic(const char *inputName, EEffectUniformSemantic semanticType)
Sets an uniform semantic. Used for uniforms which are not locally available on the client,...
An effect describes how an object will be rendered to the screen.
Definition: Effect.h:26
status_t findUniformInput(const char *inputName, UniformInput &uniformInput) const
Finds uniform input by input name.
status_t findAttributeInput(const char *inputName, AttributeInput &attributeInput) const
Finds attribute input by input name.
A geometry binding together with an appearance describe how an object will be rendered to the screen.
Definition: GeometryBinding.h:25
status_t setIndices(const ArrayResource &indicesResource)
Assign a data array with data type UInt16 or UInt32 to be used when accessing vertex data.
status_t setInputBuffer(const AttributeInput &attributeInput, const ArrayResource &arrayResource, uint32_t instancingDivisor=0)
Assign a data array resource to a given effect attribute input.
The MeshNode holds all information which is needed to render an object to the screen.
Definition: MeshNode.h:25
status_t setAppearance(Appearance &appearance)
Sets the Appearance of the MeshNode.
status_t setGeometryBinding(GeometryBinding &geometry)
Sets the GeometryBinding of the MeshNode.
status_t setTranslation(float x, float y, float z)
Sets the absolute translation the absolute values.
The OrthographicCamera is a local camera which defines an orthographic view into the scene.
Definition: OrthographicCamera.h:22
Entry point of RAMSES client API.
Definition: RamsesClient.h:34
Scene * createScene(sceneId_t sceneId, const SceneConfig &sceneConfig=SceneConfig(), const char *name=nullptr)
Create a new empty Scene.
The RamsesFrameworkConfig holds a set of parameters to be used to initialize ramses.
Definition: RamsesFrameworkConfig.h:23
Class representing ramses framework components that are needed to initialize an instance of ramses cl...
Definition: RamsesFramework.h:35
RamsesRenderer is the main renderer component which provides API to configure and control the way con...
Definition: RamsesRenderer.h:37
status_t setSkippingOfUnmodifiedBuffers(bool enable=true)
Enable or disable skipping of rendering of unmodified buffers. By default the renderer does not re-re...
displayId_t createDisplay(const DisplayConfig &config)
Creates a display based on provided display config. Creation of a display is an asynchronous action a...
status_t flush()
Submits renderer commands (API calls on this instance of RamsesRenderer) since previous flush to be e...
status_t dispatchEvents(IRendererEventHandler &rendererEventHandler)
Most RamsesRenderer methods push commands to an internal queue which is submitted when calling Ramses...
status_t readPixels(displayId_t displayId, displayBufferId_t displayBuffer, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
Triggers an asynchronous read back of a display buffer memory from GPU to system memory.
status_t doOneLoop()
Prepare content to be rendered in next frame and render next frame.
displayBufferId_t createDmaOffscreenBuffer(displayId_t display, uint32_t width, uint32_t height, uint32_t bufferFourccFormat, uint32_t usageFlags, uint64_t modifier)
Additional API to create an offscreen buffer using DMA buffer for internal storage....
status_t getDmaOffscreenBufferFDAndStride(displayId_t display, displayBufferId_t displayBufferId, int &fd, uint32_t &stride) const
Get the FD and stride for a DMA offscreen buffer previously created on the given display.
static status_t setDisplayBufferClearFlags(RamsesRenderer &renderer, displayId_t display, displayBufferId_t displayBuffer, uint32_t clearFlags)
Sets clear flags for a display buffer (display's framebuffer or offscreen buffer).
RendererSceneControl * getSceneControlAPI()
Get scene control API.
displayBufferId_t getDisplayFramebuffer(displayId_t displayId) const
Get display's framebuffer ID. Every display upon creation has one framebuffer which can be referenced...
static bool SaveImageBufferToPng(const std::string &filePath, const std::vector< uint8_t > &imageData, uint32_t width, uint32_t height)
Creates a png from image data, e.g. data generated by RamsesClientService::readPixels....
static Texture2D * CreateTextureResourceFromPng(const char *pngFilePath, Scene &scene, const TextureSwizzle &swizzle={}, const char *name=nullptr)
Creates a Texture from the given png file.
The RenderGroup is a container used to collect renderables which are supposed to be rendered together...
Definition: RenderGroup.h:31
status_t addMeshNode(const MeshNode &mesh, int32_t orderWithinGroup=0)
Add a mesh to this RenderGroup. If a mesh is already contained in this RenderGroup only its render or...
The RenderPass is a container used to collect meshes which are supposed to be rendered together.
Definition: RenderPass.h:31
status_t setCamera(const Camera &camera)
Set the camera to use for rendering the objects of this renderpass.
status_t addRenderGroup(const RenderGroup &renderGroup, int32_t orderWithinPass=0)
Add a RenderGroup to this RenderPass for rendering.
The RendererConfig holds a set of parameters to be used to initialize a renderer.
Definition: RendererConfig.h:26
Convenience empty implementation of IRendererEventHandler that can be used to derive from when only s...
Definition: IRendererEventHandler.h:194
Convenience empty implementation of IRendererSceneControlEventHandler that can be used to derive from...
Definition: IRendererSceneControlEventHandler.h:214
virtual void offscreenBufferLinked(displayBufferId_t offscreenBufferId, sceneId_t consumerScene, dataConsumerId_t consumerId, bool success) override
This method will be called when the data link between offscreen buffer and scene's data slot is estab...
Definition: IRendererSceneControlEventHandler.h:228
virtual void sceneStateChanged(sceneId_t sceneId, RendererSceneState state) override
This method will be called when state of a scene changes.
Definition: IRendererSceneControlEventHandler.h:219
status_t dispatchEvents(IRendererSceneControlEventHandler &eventHandler)
RendererSceneControl methods push commands to an internal queue which is submitted when calling flush...
The SceneConfig holds a set of parameters to be used when creating a scene.
Definition: SceneConfig.h:22
The Scene holds a scene graph. It is the essential class for distributing content to the ramses syste...
Definition: Scene.h:83
OrthographicCamera * createOrthographicCamera(const char *name=nullptr)
Creates a Orthographic Camera in this Scene.
MeshNode * createMeshNode(const char *name=nullptr)
Creates a scene graph MeshNode. MeshNode is a Node with additional properties and bindings that repre...
Effect * createEffect(const EffectDescription &effectDesc, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new Effect by parsing a GLSL shader described by an EffectDescription instance....
GeometryBinding * createGeometryBinding(const Effect &effect, const char *name=nullptr)
Creates a new GeometryBinding.
ArrayResource * createArrayResource(EDataType type, uint32_t numElements, const void *arrayData, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new ArrayResource. It makes a copy of the given data of a certain type as a resource,...
status_t publish(EScenePublicationMode publicationMode=EScenePublicationMode_LocalAndRemote)
Publishes the scene to the ramses system.
RenderPass * createRenderPass(const char *name=nullptr)
Create a render pass in the scene.
Appearance * createAppearance(const Effect &effect, const char *name=nullptr)
Creates a new Appearance.
StreamTexture * createStreamTexture(const Texture2D &fallbackTexture, waylandIviSurfaceId_t source, const char *name=nullptr)
Create a Stream Texture.
RenderGroup * createRenderGroup(const char *name=nullptr)
Create a RenderGroup instance in the scene.
const RamsesObject * findObjectByName(const char *name) const
Get an object from the scene by name.
status_t flush(sceneVersionTag_t sceneVersionTag=InvalidSceneVersionTag)
Commits all changes done to the scene since the last flush or since scene creation....
TextureSampler * createTextureSampler(ETextureAddressMode wrapUMode, ETextureAddressMode wrapVMode, ETextureSamplingMethod minSamplingMethod, ETextureSamplingMethod magSamplingMethod, const Texture2D &texture, uint32_t anisotropyLevel=1, const char *name=nullptr)
Creates a texture sampler object.
status_t createTextureConsumer(const TextureSampler &sampler, dataConsumerId_t dataId)
Annotates a ramses::TextureSampler as a content consumer. Texture provider and texture consumer can b...
StreamTexture is a special kind of texture, which holds a reference to a "fallback texture" and a str...
Definition: StreamTexture.h:25
Helper class to create strongly typed values out of various types.
Definition: StronglyTypedValue.h:23
constexpr BaseType getValue() const
Getter for retrieving the underlying value.
Definition: StronglyTypedValue.h:73
Texture represents a 2-D texture resource.
Definition: Texture2D.h:24
The TextureSampler holds a texture and its sampling parameters.
Definition: TextureSampler.h:29
The UniformInput is a description of an uniform effect input.
Definition: UniformInput.h:22
@ ETextureSamplingMethod_Linear
Definition: TextureEnums.h:21
@ ETextureAddressMode_Repeat
Definition: TextureEnums.h:33
@ EClearFlags_None
Definition: RamsesFrameworkTypes.h:257
@ ModelViewProjectionMatrix
Model-view-projection matrix 4x4.
@ Vector2F
two components of type float per data element
@ UInt16
one component of type uint16_t per data element
@ Vector3F
three components of type float per data element
RendererSceneState
Definition: RendererSceneState.h:19
@ Unavailable
Scene is unavailable, no scene control possible.
@ Rendered
Scene is being rendered.
constexpr const status_t StatusOK
Status returned from RAMSES client API methods that succeeded.
Definition: RamsesFrameworkTypes.h:32
constexpr const resourceCacheFlag_t ResourceCacheFlag_DoNotCache
Requests the render to not cache a resource. This is the default value.
Definition: RamsesFrameworkTypes.h:212
uint64_t sceneVersionTag_t
Scene version tag used to refer to content versions of a scene. A scene version may be updated along ...
Definition: RamsesFrameworkTypes.h:49
ERendererEventResult
Specifies the result of the operation referred to by renderer event.
Definition: Types.h:94
@ ERendererEventResult_OK
Event referring to an operation that succeeded.
Definition: Types.h:95
@ ERendererEventResult_FAIL
Event referring to an operation that failed.
Definition: Types.h:97
constexpr const sceneVersionTag_t InvalidSceneVersionTag
Scene version tag used to refer to an invalid scene version.
Definition: RamsesFrameworkTypes.h:54
int main(int argc, char *argv[])
Definition: main.cpp:21
bool startBufferAccess(ramses::displayBufferId_t displayBuffer)
Definition: main.cpp:403
constexpr const char *const vertexShader
Definition: main.cpp:66
bool endBufferAccess(ramses::displayBufferId_t displayBuffer)
Definition: main.cpp:425
ramses::MeshNode & createQuadWithTexture(ramses::Scene &scene, ramses::Effect &effect, ramses::TextureSampler &textureSampler)
Definition: main.cpp:229
ramses::Scene & createMainScene(ramses::RamsesClient &client, ramses::sceneId_t sceneId, ramses::waylandIviSurfaceId_t streamId, const std::string &processingOutputSamplerName)
Definition: main.cpp:268
ramses::Effect & createEffect(ramses::Scene &scene, const std::string &effectName)
Definition: main.cpp:219
bool mapDmaOffscreenBuffer(ramses::RamsesRenderer &renderer, ramses::displayId_t display, ramses::displayBufferId_t displayBuffer, bool readyOnly)
Definition: main.cpp:370
constexpr const char *const fragmentShader
Definition: main.cpp:80
std::unordered_map< ramses::displayBufferId_t, BufferInfo > bufferInfoMap
Definition: main.cpp:356
ramses::Scene & createSourceScene(ramses::RamsesClient &client, ramses::sceneId_t sceneId, ramses::waylandIviSurfaceId_t streamId)
Definition: main.cpp:316
bool doProcessing(ramses::displayBufferId_t inputBuffer, ramses::displayBufferId_t outputBuffer)
Definition: main.cpp:447
ramses::displayBufferId_t createDmaOffscreenBuffer(ramses::RamsesRenderer &renderer, ramses::displayId_t display)
Definition: main.cpp:358
constexpr uint32_t DisplayWidth
Definition: main.cpp:31
constexpr uint32_t DisplayHeight
Definition: main.cpp:32
Definition: main.cpp:350
int fd
Definition: main.cpp:351
std::size_t bufferSize
Definition: main.cpp:353
void * mappedMem
Definition: main.cpp:354
uint32_t stride
Definition: main.cpp:352