Skip to content

Commit

Permalink
Add liboxide
Browse files Browse the repository at this point in the history
  • Loading branch information
Eeems committed Dec 23, 2023
1 parent 9242399 commit 4a31b71
Show file tree
Hide file tree
Showing 37 changed files with 3,418 additions and 32 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![rm1](https://img.shields.io/badge/rM1-supported-green)](https://remarkable.com/store/remarkable) [![rm2](https://img.shields.io/badge/rM2-supported-green)](https://remarkable.com/store/remarkable-2) [![Discord](https://img.shields.io/discord/385916768696139794.svg?label=reMarkable&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/ATqQGfu)

reMarkable Template Qt Application
==================================
reMarkable Template Qt Oxide Application
========================================

- [src/vendor/epaper/epframebuffer.h](src/vendor/epaper/epframebuffer.h) - Methods for direct access to the reMarkable screen.
- [src/vendor/epaper/libqsgepaper.a](src/vendor/epaper/libqsgepaper.a) - Static library that contains the epaper Qt platform. This is required for Qt to be able to interact with the screen on the reMarkable.
Expand Down
37 changes: 7 additions & 30 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <cstdlib>
#include <signal.h>

#include <liboxide.h>
#include <liboxide/eventfilter.h>

#include "controller.h"

// This is required for Qt to display to the reMarkable's display
Expand All @@ -19,40 +22,13 @@ void sigHandler(int signal){
}

int main(int argc, char *argv[]){
auto qt_version = qVersion();
qDebug() << "Qt Runtime: " << qt_version;
qDebug() << "Qt Build: " << QT_VERSION_STR;
QCoreApplication::addLibraryPath("/opt/usr/lib/plugins");
// Setup correct Qt settings for application to load
// This will overwrite any passed in environment variables
// If you want to support overriding these values, you will need to either
// check that they are not populated here, or move them to a wrapper script
// and remove this code
qputenv("QMLSCENE_DEVICE", "epaper");
qputenv("QT_QUICK_BACKEND","epaper");
qputenv("QT_QPA_PLATFORM", "epaper:enable_fonts");
qputenv("QT_QPA_GENERIC_PLUGINS", "evdevtablet");
QFile file("/sys/devices/soc0/machine");
if(!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "Couldn't open " << file.fileName();
return EXIT_FAILURE;
}
QTextStream in(&file);
QString modelName = in.readLine();
if(modelName.startsWith("reMarkable 2")){
qDebug() << "RM2 detected...";
qputenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS", "rotate=180:invertx");
qputenv("QT_QPA_EVDEV_TABLET_PARAMETERS", "");
}else{
qDebug() << "RM1 detected...";
qputenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS", "rotate=180");
qputenv("QT_QPA_EVDEV_TABLET_PARAMETERS", "");
}

deviceSettings.setupQtEnvironment();
QGuiApplication app(argc, argv);
app.setApplicationName("myapp");
app.setApplicationDisplayName("My Application");
app.setApplicationVersion(APP_VERSION);
auto filter = new Oxide::EventFilter(&app);
app.installEventFilter(filter);
Controller controller(&app);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
Expand All @@ -68,6 +44,7 @@ int main(int argc, char *argv[]){
}
auto root = engine.rootObjects().first();
controller.setRoot(root);
filter->root = (QQuickItem*)root;

// Setup some signal handlers to make sure to quit the application normally if these signals are recieved
signal(SIGINT, sigHandler);
Expand Down
1 change: 1 addition & 0 deletions src/src.pro
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ RESOURCES += \
qml.qrc

include(vendor/epaper.pri)
include(vendor/liboxide.pri)
3 changes: 3 additions & 0 deletions src/vendor/liboxide.pri
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
LIBS += -L$$PWD/liboxide -lliboxide
INCLUDEPATH += $$PWD/liboxide
QT += dbus
200 changes: 200 additions & 0 deletions src/vendor/liboxide/epframebuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#ifndef EPFRAMEBUFFER_H
#define EPFRAMEBUFFER_H

#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QMutex>
#include <QtCore/QObject>
#include <QtGui/QImage>

#include <atomic>
#include <mutex>

#if defined(LIBOXIDE_LIBRARY)
#include "liboxide_global.h"
#ifdef __arm__
Q_IMPORT_PLUGIN(QsgEpaperPlugin)
#endif
#else
#include <liboxide/liboxide_global.h>
#endif


class LIBOXIDE_EXPORT EPFrameBuffer : public QObject
{
Q_OBJECT

// Testing results:
// 0: ~780ms, initialize to white
// 1: ~170ms, mono, no flashing
// 2: ~460ms, 15 grayscale, flashing all pixels white -> black pixels
// 3: ~460ms, 15, grayscale, flashing all pixels white -> black pixels
// 4: ~460ms, 4 grayscale, flashing all pixels white -> black pixels
// 5: ~460ms, 4 grayscale, flashing all pixels white -> black pixels
// 6: ~135ms, no flashing
// 7: ~300ms, white, 2 gray, 1 black, no flashing, stuck black?
// 8: ~435ms, fast flashing, all gray, highlight, several grays, lowest color - 1 gets stuck
// 9: ~2365ms, lots of flashing, delta something?

enum Waveform {
/** Display initialization
* All -> white
* 2000ms
* ~780ms stall in driver
* Supposedly low ghosting, high ghosting in practice.
*/
INIT = 0,

/**
* Monochrome menu, text input, pen input
* All -> black/white
* 260ms to complete
* 170ms stall in driver
* Low ghosting
*/
DU = 1,

/** High quality images
* All -> all
* 480ms to complete
* 460ms stall in driver
* Very low ghosting
*/
GC16 = 2,

/** Text with white background
* 16 -> 16
* 480ms to complete
* 460ms stall in driver
* Medium ghosting
*
* Local update when white to white, Global update when 16 gray levels
* For drawing anti-aliased text with reduced flash. This waveform makes full screen update
* - the entire display except pixels staying in white will update as the new image is
* written.
*/
GL16 = 3,

/** Text with white background
* All -> all
* 480ms to complete
* 460ms stall in driver
* Low ghosting
*
* Global Update
* For drawing anti-aliased text with reduced flash and image artifacts (used in
* conjunction with an image preprocessing algorithm, very little ghosting). Drawing time
* is around 600ms. This waveform makes full screen update - all the pixels are updated or
* cleared. Use this for anti-aliased text.
*/
GLR16 = 4,

/** Text and graphics with white background
* All -> all
* 480ms to complete
* 460ms stall in driver
* Low ghosting
*
* Global Update
* For drawing anti-aliased text with reduced flash and image artifacts (used in
* conjunction with an image preprocessing algorithm, very little ghosting) even more
* compared to the GLR16 mode. Drawing time is around 600ms. This waveform makes full
* screen update - all the pixels are updated or cleared. Use this for anti-aliased text.
*/
GLD16 = 5,

/** Fast page flipping at reduced contrast
* [0, 29, 30, 31] -> [0, 30]
* 120ms to complete
* 135ms stall in driver
* Medium ghosting
*
* Local Update
* For drawing black and white 2-color images. This waveform supports transitions from and
* to black or white only. It cannot be used to update to any graytone other than black or
* white. Drawing time is around 120ms. This waveform makes partial screen update - it
* updates only changed pixels. Image quality is reduced in exchange for the quicker
* response time. This waveform can be used for fast updates and simple animation.
*/
A2 = 6,

/** Anti-aliased text in menus, touch and pen input
* All -> [0, 10, 20, 30]
* 290ms to complete
* 300ms stall in driver
*
* No flashing, black seems to be stuck afterwards?
*/
DU4 = 7,

/** Unknown1
* 435ms stall in driver
*
* Fast flashing, all gray, highlight?
* Multiple grays
* Next to lowest color gets stuck
*/
UNKNOWN = 8,

/** Init?
* 2365ms stall in driver
*
* Lots of flashing, seems to do some delta updates (inverting unchanged?)
*/
INIT2 = 9
};

public:
static EPFrameBuffer *instance();

/// Which waveforms we use for different kinds of updates
enum WaveformMode {
Initialize = INIT,
Mono = DU,
Grayscale = GL16,
HighQualityGrayscale = GC16,
Highlight = UNKNOWN
};

enum UpdateMode {
PartialUpdate = 0x0,
FullUpdate = 0x1
};

static QImage *framebuffer() {
return &instance()->m_fb;
}

Q_INVOKABLE static void setForceFull(bool force) { instance()->m_forceFull = force; }
static bool isForceFull() { return instance()->m_forceFull; }

int lastUpdateId() const { return m_lastUpdateId; }

void setSuspended(bool suspended) { m_suspended = suspended; }
bool isSuspended() const {
std::lock_guard<std::mutex> locker(fbMutex);
return m_suspended;
}

mutable std::mutex fbMutex;

qint64 timeSinceLastUpdate() const;

public slots:
static void clearScreen();
static void sendUpdate(QRect rect, WaveformMode waveform, UpdateMode mode, bool sync = false);
static void waitForLastUpdate();

private:
EPFrameBuffer();
QImage m_fb;
QFile m_deviceFile;
bool m_forceFull = false;
bool m_suspended = false;
int m_lastUpdateId = 0;

std::mutex m_timerLock;
QElapsedTimer m_lastUpdateTimer;
};

#endif // EPFRAMEBUFFER_H
1 change: 1 addition & 0 deletions src/vendor/liboxide/libliboxide.so
1 change: 1 addition & 0 deletions src/vendor/liboxide/libliboxide.so.2
1 change: 1 addition & 0 deletions src/vendor/liboxide/libliboxide.so.2.7
Binary file added src/vendor/liboxide/libliboxide.so.2.7.0
Binary file not shown.
2 changes: 2 additions & 0 deletions src/vendor/liboxide/liboxide.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#include "liboxide/liboxide.h"
Loading

0 comments on commit 4a31b71

Please sign in to comment.