Skip to content

Commit

Permalink
Expose framebuffer as image
Browse files Browse the repository at this point in the history
  • Loading branch information
Eeems committed Jul 4, 2023
1 parent bff203f commit fba2964
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 30 deletions.
38 changes: 29 additions & 9 deletions applications/system-service/dbusservice.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ struct ChildEntry {
void* fbData = nullptr;
QImage* fbImage = nullptr;
std::string uniqueName() const{
return QString("%1-%2-%3").arg(service.c_str()).arg(name.c_str()).arg(pid).toStdString();
}
ssize_t size() const {
return fbWidth * fbHeight;
return QString("%1-%2-%3")
.arg(service.c_str())
.arg(name.c_str())
.arg(pid)
.toStdString();
}
ssize_t size() const { return fbWidth * fbHeight; }
QImage* frameBuffer() {
if(fbImage){
return fbImage;
Expand All @@ -68,7 +70,7 @@ struct ChildEntry {
if(fbData == MAP_FAILED){
return nullptr;
}
fbImage = new QImage((uchar*)fbData, fbWidth, fbHeight, QImage::Format_Mono);
fbImage = new QImage((uchar*)fbData, fbWidth, fbHeight, fbWidth, QImage::Format_Mono);
return fbImage;
}
};
Expand Down Expand Up @@ -298,6 +300,19 @@ class DBusService : public APIBase {
return QDBusUnixFileDescriptor();
}

Q_INVOKABLE QList<int> getFrameBufferSize(QDBusMessage message){
auto service = message.service().toStdString();
QMutableListIterator<ChildEntry> i(children);
while(i.hasNext()){
auto child = i.next();
if(child.service != service){
continue;
}
return QList<int>{child.fbWidth, child.fbHeight};
}
return QList<int>{ -1, -1 };
}

Q_INVOKABLE QDBusUnixFileDescriptor createFrameBuffer(int width, int height, QDBusMessage message){
auto service = message.service().toStdString();
QMutableListIterator<ChildEntry> i(children);
Expand Down Expand Up @@ -480,16 +495,21 @@ private slots:
continue;
}
i.remove();
if(child.fbImage != nullptr){
delete child.fbImage;
}
if(child.fbData != nullptr && child.fbData != MAP_FAILED && munmap(child.fbData, child.size()) == -1){
O_WARNING("Failed to unmap framebuffer:" << strerror(errno));
}
if(child.fb != -1 && close(child.fb)){
O_WARNING("Failed to close framebuffer" << strerror(errno));
O_WARNING("Failed to close framebuffer:" << strerror(errno));
}
if(child.eventRead != -1 && close(child.eventRead)){
O_WARNING("Failed to close event read pipe" << strerror(errno));
O_WARNING("Failed to close event read pipe:" << strerror(errno));
}
if(child.eventWrite != -1 && close(child.eventWrite)){
O_WARNING("Failed to close event write pipe" << strerror(errno));
O_WARNING("Failed to close event write pipe:" << strerror(errno));
}

}
}
};
Expand Down
4 changes: 4 additions & 0 deletions interfaces/dbusservice.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<method name="getFrameBuffer">
<arg type="h" direction="out"/>
</method>
<method name="getFrameBufferSize">
<arg type="ai" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;int&gt;"/>
</method>
<method name="createFrameBuffer">
<arg type="h" direction="out"/>
<arg name="width" type="i" direction="in"/>
Expand Down
101 changes: 81 additions & 20 deletions shared/liboxide/tarnish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#include "meta.h"
#include "debug.h"

#include <sys/mman.h>
#include <QDBusConnection>
#include <QImage>

codes::eeems::oxide1::General* api_general = nullptr;
codes::eeems::oxide1::Power* api_power = nullptr;
Expand All @@ -11,8 +13,11 @@ codes::eeems::oxide1::Screen* api_screen = nullptr;
codes::eeems::oxide1::Apps* api_apps = nullptr;
codes::eeems::oxide1::System* api_system = nullptr;
codes::eeems::oxide1::Notifications* api_notification = nullptr;
int frameBuffer = -1;
int events = -1;
int frameBufferFd = -1;
int eventsFd = -1;
uchar* fbData = nullptr;
QImage* fbImage = nullptr;
QList<int> fbSize;

bool verifyConnection(){
if(api_general == nullptr){
Expand Down Expand Up @@ -82,13 +87,22 @@ namespace Oxide::Tarnish {
freeAPI(system);
freeAPI(notification);
freeAPI(general);
if(frameBuffer != -1){
close(frameBuffer);
frameBuffer = -1;
if(fbData != nullptr){
munmap(fbData, fbSize.at(0) * fbSize.at(1));
fbData = nullptr;
}
if(events != -1){
close(events);
events = -1;
fbSize.clear();
if(fbImage != nullptr){
delete fbImage;
fbImage = nullptr;
}
if(frameBufferFd != -1){
close(frameBufferFd);
frameBufferFd = -1;
}
if(eventsFd != -1){
close(eventsFd);
eventsFd = -1;
}
QDBusConnection::disconnectFromBus(QDBusConnection::systemBus().name());
#undef freeAPI
Expand All @@ -104,9 +118,9 @@ namespace Oxide::Tarnish {
connect();
return api_general->tarnishPid();
}
int getFrameBuffer(){
if(frameBuffer != -1){
return frameBuffer;
int getFrameBufferFd(){
if(frameBufferFd != -1){
return frameBufferFd;
}
connect();
QDBusPendingReply<QDBusUnixFileDescriptor> reply = api_general->getFrameBuffer();
Expand All @@ -120,11 +134,11 @@ namespace Oxide::Tarnish {
O_WARNING("Unable to get framebuffer: No framebuffer provided");
return -1;
}
frameBuffer = dup(fd);
return frameBuffer;
frameBufferFd = dup(fd);
return frameBufferFd;
}
int createFrameBuffer(int width, int height){
if(frameBuffer != -1){
if(frameBufferFd != -1){
O_WARNING("Framebuffer already exists");
return -1;
}
Expand All @@ -144,13 +158,60 @@ namespace Oxide::Tarnish {
O_WARNING("Unable to get framebuffer: No framebuffer provided");
return -1;
}
frameBuffer = dup(fd);
frameBufferFd = dup(fd);
api_general->enableFrameBuffer();
return frameBuffer;
return frameBufferFd;
}
QList<int> frameBufferSize(){
if(!fbSize.isEmpty()){
return fbSize;
}
connect();
QDBusPendingReply<QList<int>> reply = api_general->getFrameBufferSize();
if(reply.isError() || !reply.isValid()){
return fbSize;
}
auto size = reply.value();
fbSize.swap(size);
return fbSize;
}
uchar* frameBuffer(){
if(fbData != nullptr){
return fbData;
}
auto fd = getFrameBufferFd();
if(fd == -1){
return nullptr;
}
auto size = frameBufferSize();
if(size.isEmpty()){
return nullptr;
}
auto data = mmap(NULL, size[0] * size[1], PROT_READ | PROT_WRITE, MAP_SHARED | MAP_SYNC | MAP_HUGETLB, fd, 0);
if(data == MAP_FAILED){
return nullptr;
}
fbData = (uchar*)data;
return fbData;
}
QImage* frameBufferImage(){
if(fbImage){
return fbImage;
}
auto data = frameBuffer();
if(data == nullptr){
return nullptr;
}
auto size = frameBufferSize();
if(size.isEmpty()){
return nullptr;
}
fbImage = new QImage((uchar*)data, size[0], size[1], size[0], QImage::Format_Mono);
return fbImage;
}
int getEventPipe(){
if(events != -1){
return events;
if(eventsFd != -1){
return eventsFd;
}
connect();
QDBusPendingReply<QDBusUnixFileDescriptor> reply = api_general->getEventPipe();
Expand All @@ -164,9 +225,9 @@ namespace Oxide::Tarnish {
O_WARNING("Unable to get framebuffer: No framebuffer provided");
return -1;
}
events = dup(fd);
eventsFd = dup(fd);
api_general->enableEventPipe();
return events;
return eventsFd;
}
codes::eeems::oxide1::Power* powerAPI(){
if(api_power != nullptr){
Expand Down
17 changes: 16 additions & 1 deletion shared/liboxide/tarnish.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,29 @@ namespace Oxide::Tarnish {
* \brief getFrameBuffer
* \return
*/
int getFrameBuffer();
int getFrameBufferFd();
/*!
* \brief createFrameBuffer
* \param width
* \param height
* \return
*/
int createFrameBuffer(int width, int height);
/*!
* \brief frameBufferSize
* \return
*/
QList<int> frameBufferSize();
/*!
* \brief frameBuffer
* \return
*/
uchar* frameBuffer();
/*!
* \brief frameBuffer
* \return
*/
QImage* frameBufferImage();
/*!
* \brief getEventPipe
* \return
Expand Down

0 comments on commit fba2964

Please sign in to comment.