Skip to content

Commit

Permalink
Start implementing libblight
Browse files Browse the repository at this point in the history
  • Loading branch information
Eeems committed Jan 18, 2024
1 parent ef108b1 commit 673f096
Show file tree
Hide file tree
Showing 20 changed files with 871 additions and 82 deletions.
16 changes: 15 additions & 1 deletion applications/display-server/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,22 @@ Surface* Connection::getSurface(QString identifier){

void Connection::readSocket(){
auto socket = m_socketPair.writeSocket();
Blight::Connection connection(socket->socketDescriptor());
while(!socket->atEnd()){
O_DEBUG(socket->readAll());
auto message = connection.read();
switch(message.type()){
case Blight::MessageType::Repaint:{
auto identifier = message.block(1).to_string();
auto surface = getSurface(identifier.c_str());
if(surface != nullptr){
auto data = message.block(2);
emit surface->update(QRect(data[0], data[1], data[2], data[3]));
}
break;
}
default:
O_WARNING("Unexpected message type" << message.type());
}
}
}
#include "moc_connection.cpp"
1 change: 1 addition & 0 deletions applications/display-server/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <QObject>
#include <QFile>
#include <liboxide/socketpair.h>
#include <libblight/connection.h>

#include "surface.h"

Expand Down
1 change: 1 addition & 0 deletions applications/display-server/display-server.pro
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ HEADERS += \
INCLUDEPATH += ../../shared/mxcfb

include(../../qmake/liboxide.pri)
include(../../qmake/libblight.pri)

QMAKE_POST_LINK += sh $$_PRO_FILE_PWD_/generate_xml.sh

Expand Down
1 change: 1 addition & 0 deletions applications/display-server/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <QImage>

#include "../../shared/liboxide/meta.h"
#include "../../shared/libblight/meta.h"

class Surface : public QObject {
Q_OBJECT
Expand Down
135 changes: 60 additions & 75 deletions applications/test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@

#include <cstdlib>
#include <liboxide/eventfilter.h>
#include <liboxide/dbus.h>
#include <liboxide/meta.h>
#include <liboxide/debug.h>
#include <liboxide/sentry.h>
#include <liboxide/oxideqml.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <errno.h>
#include <cstring>
#include <libblight.h>
#include <libblight/connection.h>

using namespace codes::eeems::blight1;
using namespace Oxide;
using namespace Oxide::QML;
using namespace Oxide::Sentry;
Expand All @@ -41,68 +42,41 @@ int main(int argc, char *argv[]){
engine.rootObjects().first()->installEventFilter(new EventFilter(&app));
QTimer::singleShot(0, []{
#ifdef EPAPER
auto bus = QDBusConnection::systemBus();
Blight::connect(true);
#else
auto bus = QDBusConnection::sessionBus();
Blight::connect(false);
#endif
if(!bus.interface()->isServiceRegistered(BLIGHT_SERVICE)){
qFatal(BLIGHT_SERVICE " can't be found");
}
auto compositor = new Compositor(BLIGHT_SERVICE, "/", bus, qApp);
auto res = compositor->open();
if(res.isError()){
qFatal("Failed to get connection: %s", res.error().message().toStdString().c_str());
}
auto qfd = res.value();
if(!qfd.isValid()){
qFatal("Failed to get connection: Invalid file descriptor");
if(!Blight::exists()){
O_WARNING("Service not found!");
qApp->exit(EXIT_FAILURE);
return;
}
auto cfd = qfd.fileDescriptor();
O_DEBUG("Connection file descriptor" << cfd);

QRect geometry(50, 50, 100, 100);
auto identifier = QUuid::createUuid().toString();

int fd = memfd_create(identifier.toStdString().c_str(), MFD_ALLOW_SEALING);
if(fd == -1){
O_WARNING("Unable to create memfd for framebuffer:" << strerror(errno));
int bfd = Blight::open();
if(bfd < 0){
O_WARNING(std::strerror(errno));
qApp->exit(EXIT_FAILURE);
return;
}
O_DEBUG("Connection file descriptor:" << bfd);
QRect geometry(50, 50, 100, 100);
QImage blankImage(geometry.size(), QImage::Format_ARGB32_Premultiplied);
blankImage.fill(Qt::black);
size_t size = blankImage.sizeInBytes();
if(ftruncate(fd, size)){
O_WARNING("Unable to truncate memfd for framebuffer:" << strerror(errno));
if(::close(fd) == -1){
O_WARNING("Failed to close fd:" << strerror(errno));
}
return;
}
int flags = fcntl(fd, F_GET_SEALS);
if(fcntl(fd, F_ADD_SEALS, flags | F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW)){
O_WARNING("Unable to seal memfd for framebuffer:" << strerror(errno));
if(::close(fd) == -1){
O_WARNING("Failed to close fd:" << strerror(errno));
}
return;
}
auto file = new QFile();
if(!file->open(fd, QFile::ReadWrite, QFile::DontCloseHandle)){
O_WARNING("Failed to open QFile:" << file->errorString());
if(::close(fd) == -1){
O_WARNING("Failed to close fd:" << strerror(errno));
}
return;
}
uchar* data = file->map(0, size);
if(data == nullptr){
O_WARNING("Failed to map framebuffer:" << strerror(errno));
file->close();
auto buffer = Blight::createBuffer(
geometry.x(),
geometry.y(),
geometry.width(),
geometry.height(),
blankImage.bytesPerLine(),
Blight::Format::Format_ARGB32_Premultiplied
);
if(buffer.fd == -1 || buffer.data == nullptr){
O_WARNING("Failed to create buffer:" << strerror(errno));
return;
}
memcpy(data, blankImage.constBits(), size);
memcpy(buffer.data, blankImage.constBits(), size);
auto image = new QImage(
data,
buffer.data,
blankImage.width(),
blankImage.height(),
blankImage.bytesPerLine(),
Expand All @@ -114,35 +88,46 @@ int main(int argc, char *argv[]){
if(image->size() != geometry.size()){
O_WARNING("Invalid size" << image->size());
}
auto res2 = compositor->addSurface(
QDBusUnixFileDescriptor(fd),
std::string id = Blight::addSurface(
buffer.fd,
geometry.x(),
geometry.y(),
image->width(),
image->height(),
image->bytesPerLine(),
(int)image->format()
(Blight::Format)image->format()
);
res.waitForFinished();
if(res2.isError()){
qFatal("Failed to add surface: %s", res2.error().message().toStdString().c_str());
if(id.empty()){
O_WARNING("No identifier provided");
}
O_DEBUG("Surface added:" << id.c_str());
auto connection = new Blight::Connection(bfd);
msghdr msg;
memset(&msg, 0, sizeof(msghdr));
iovec i;
auto d = Blight::MessageType::Invalid;
i.iov_base = &d;
i.iov_len = 1;
if(sendmsg(bfd, &msg, 0) < 0){
O_WARNING(std::strerror(errno));
}else{
O_DEBUG("Sent message");
}
auto id = res2.value();
O_DEBUG("Surface added:" << id);
QTimer::singleShot(2000, [id, compositor, image, file]{
O_DEBUG("Switching to yellow");
image->fill(Qt::yellow);
O_DEBUG("Repainting" << id);
auto reply = compositor->repaint(id);
reply.waitForFinished();
if(reply.isError()){
O_WARNING(reply.error().message());
}else{
O_DEBUG("Done!");
}
file->close();
QTimer::singleShot(2000, []{ qApp->exit(); });
});
sleep(1);
O_DEBUG("Switching to yellow");
image->fill(Qt::yellow);
O_DEBUG("Repainting" << id.c_str());
connection->repaint(
id,
geometry.x(),
geometry.y(),
geometry.width(),
geometry.height()
);
O_DEBUG("Done!");
buffer.close();
delete connection;
QTimer::singleShot(2000, []{ qApp->exit(); });
});
return app.exec();
}
1 change: 1 addition & 0 deletions applications/test/test.pro
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ RESOURCES += \
qml.qrc

include(../../qmake/liboxide.pri)
include(../../qmake/libblight.pri)
6 changes: 6 additions & 0 deletions qmake/libblight.pri
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
contains(DEFINES, LIBBLIGHT_PRIVATE){
LIBS_PRIVATE += -L$$OUT_PWD/../../shared/libblight -lblight
}else{
LIBS += -L$$OUT_PWD/../../shared/libblight -lblight
}
INCLUDEPATH += $$OUT_PWD/../../shared/libblight/include
136 changes: 136 additions & 0 deletions shared/libblight/connection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include "connection.h"

namespace Blight{
Block::Block()
: m_iovec{nullptr, 0},
pointer(0)
{}

Block::Block(iovec iovec)
: m_iovec(iovec),
pointer(0)
{

}

void Block::seek(unsigned int i){ pointer = i > m_iovec.iov_len ? m_iovec.iov_len : i; }

unsigned int Block::operator[](unsigned int i){
if(i >= m_iovec.iov_len){
return 0;
}
return data()[i];
}

void Block::setData(data_t data, size_t size){
m_iovec.iov_base = data;
m_iovec.iov_len = size;
}

std::string Block::to_string(){
std::string str;
str.assign(reinterpret_cast<char*>(m_iovec.iov_base), m_iovec.iov_len);
return str;
}

data_t Block::data(){ return reinterpret_cast<data_t>(m_iovec.iov_base); }

Connection::Connection(int fd)
: m_fd(dup(fd))
{}

Connection::~Connection(){
::close(m_fd);
}

Message Connection::read(){
msghdr msg;
memset(&msg, 0, sizeof(msg));
int size = recvmsg(m_fd, &msg, MSG_PEEK | MSG_TRUNC);
if(size < 0){
std::cerr
<< "Failed to recieve connection message: "
<< std::strerror(errno)
<< std::endl;
return Message();
}
return Message(msg);
}

void Connection::repaint(std::string identifier, int x, int y, int width, int height){
char id[identifier.size()];
memcpy(&id, identifier.data(), identifier.size());
repaint_t data{
.x = x,
.y = y,
.width = width,
.height = height
};
Message message(MessageType::Repaint, std::vector<iovec>{
{iovec{
.iov_base = identifier.data(),
.iov_len = identifier.size()
}},
{iovec{
.iov_base = &data,
.iov_len = sizeof(data)
}},
});
if(sendmsg(m_fd, message.data(), 0) < 0){
std::cerr
<< "Failed to send connection message: "
<< std::strerror(errno)
<< std::endl;
}
}

int Connection::peek(msghdr& msg){
memset(&msg, 0, sizeof(msg));
return recvmsg(m_fd, &msg, MSG_PEEK | MSG_TRUNC);
}

Message::Message()
: Message(msghdr{
.msg_name = nullptr,
.msg_namelen = 0,
.msg_iov = nullptr,
.msg_iovlen = 0,
.msg_control = nullptr,
.msg_controllen = 0,
.msg_flags = 0
})
{}

Message::Message(msghdr msg) : msg(msg){
m_type = static_cast<MessageType>(block(0)[0]);
}

Message::Message(MessageType type, std::vector<iovec> data)
: m_type(type)
{
data.insert(data.begin() ,iovec{
.iov_base = &type,
.iov_len = 1
});
msg = msghdr{
.msg_name = nullptr,
.msg_namelen = 0,
.msg_iov = data.data(),
.msg_iovlen = data.size(),
.msg_control = nullptr,
.msg_controllen = 0,
.msg_flags = 0
};
}

Block Message::block(unsigned int i){
if(i >= msg.msg_iovlen){
return Block();
}
return Block(msg.msg_iov[i]);
}

msghdr* Message::data(){ return &msg; }

MessageType Message::type(){ return m_type; }
}
Loading

0 comments on commit 673f096

Please sign in to comment.