Merge branch 'dev' into 'master'

Merge into master

See merge request link/projekte/ws19/vkvm-new/library!3
This commit is contained in:
Julian Hinxlage 2019-11-28 12:28:32 +00:00
commit f04ea0f73e
14 changed files with 334 additions and 82 deletions

View File

@ -9,7 +9,7 @@ filelist="$(find . -not \( -path './*build*' -prune \) -not \( -path './include'
for file in $filelist; do
if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.hpp)$" ; then
#Extra check missing dependencies due to clang-tidy doesn't toggle exit code.
clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' --color -header-filter='.*,-cpptoml.hpp' "$file" -- -I. -std=c++14 2>&1)"
clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' --color "$file" -- -I. -std=c++14 2>&1)"
for tidy_line in $clang_tidy_lib_check; do
echo "$tidy_line" | grep -q -v -E "^Error while processing*"
if [ $? -eq 1 ]; then

View File

@ -1,2 +1,3 @@
Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type'
WarningsAsErrors: 'true'
HeaderFilterRegex: '.*,-catch.hpp'

View File

@ -12,8 +12,7 @@ project(library)
set(CMAKE_CXX_STANDARD 14)
# enable clang_tidy
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*")
set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;)
set(CMAKE_CXX_CLANG_TIDY clang-tidy;)
file(GLOB_RECURSE SOURCES src/*.cpp)
@ -22,7 +21,8 @@ file(GLOB_RECURSE TESTS test/*.cpp)
include_directories(src)
include_directories(test)
add_library(library ${SOURCES} ${HEADERS} src/FontType.cpp)
add_library(library ${SOURCES} ${HEADERS})
file(COPY "${CMAKE_SOURCE_DIR}/src/"
DESTINATION "${CMAKE_SOURCE_DIR}/include"

View File

@ -2,9 +2,16 @@
namespace vkvm {
Color::Color(unsigned char red, unsigned char green, unsigned char blue) noexcept
: red(red), green(green), blue(blue) {
Color::Color() noexcept
: red(0), green(0), blue(0) {}
Color::Color(unsigned char red, unsigned char green, unsigned char blue) noexcept
: red(red), green(green), blue(blue) {}
Color::Color(unsigned int hex) noexcept {
red = (unsigned char) ((hex >> 16 & 0xFF));//NOLINT
green = (unsigned char) ((hex >> 8u & 0xFF));//NOLINT
blue = (unsigned char) ((hex & 0xFF));//NOLINT
}
auto Color::getRed() -> unsigned char {
@ -30,4 +37,12 @@ namespace vkvm {
auto Color::setBlue(unsigned char value) -> void {
blue = value;
}
bool Color::operator==(const Color &other) const {
return this->blue == other.blue && this->green == other.green && this->red == other.red;
}
bool Color::operator!=(const Color &other) const {
return this->blue != other.blue || this->green != other.green || this->red != other.red;
}
}

View File

@ -16,8 +16,12 @@ namespace vkvm {
unsigned char blue;
public:
Color() noexcept;
Color(unsigned char red, unsigned char green, unsigned char blue) noexcept;
explicit Color(unsigned int hex) noexcept;
auto getRed() -> unsigned char;
auto getGreen() -> unsigned char;
@ -30,10 +34,17 @@ namespace vkvm {
auto setBlue(unsigned char value) -> void;
bool operator==(const Color &other) const ;
bool operator!=(const Color &other) const ;
};
const static Color black = Color(0, 0, 0);
const static Color white = Color(255, 255, 255);
const static Color green = Color(0, 255, 0);
const static Color red = Color(255, 0, 0);
const static Color blue = Color(0, 0, 255);
}

View File

@ -11,12 +11,17 @@ namespace vkvm {
enum EventType {
Timer = 1,
MouseMove = 2,
MouseButton = 3,
KeyDown = 4,
KeyUp = 5,
UpdateControlRegisters = 6,
Redraw = 7,
RenderText = 8
MouseLeftUp = 3,
MouseLeftDown = 4,
MouseRightUp = 5,
MouseRightDown = 6,
MouseMiddleDown = 7,
MouseMiddleUp = 8,
KeyDown = 9,
KeyUp = 10,
UpdateControlRegisters = 11,
Redraw = 12,
RenderText = 13
};
}

View File

@ -1,11 +0,0 @@
#include "KeyCode.hpp"
namespace vkvm {
KeyCode::KeyCode(int value) noexcept : value(value) {}
auto KeyCode::getValue() -> int {
return value;
}
}

View File

@ -5,18 +5,53 @@
namespace vkvm {
class KeyCode {
private:
int value;
public:
explicit KeyCode(int value) noexcept;
auto getValue() -> int;
enum KeyCode {
Backspcce = 32,
Tab = 33,
Enter = 37,
ShiftLeft = 249,
ShiftRight = 249,
Ctrl = 251,
Alt = 257,
Delete = 279,
Space = -65224,
Zero = -65208,
One = -65207,
Two = -65206,
Three = -65205,
Four = -65204,
Five = -65203,
Six = -65202,
Seven = -65201,
Eight = -65200,
Nine = -65199,
A = -65159,
B = -65158,
C = -65157,
D = -65156,
E = -65155,
F = -65154,
G = -65153,
H = -65152,
I = -65151,
J = -65150,
K = -65149,
L = -65148,
M = -65147,
N = -65146,
O = -65145,
P = -65144,
Q = -65143,
R = -65142,
S = -65141,
T = -65140,
U = -65139,
V = -65138,
W = -65137,
X = -65136,
Y = -65135,
Z = -65134,
};
const static KeyCode Backspace = KeyCode(8);
const static KeyCode tabulator = KeyCode(9);
}
#endif

View File

@ -11,6 +11,7 @@
#include "SharedMemoryAccess.hpp" /* header is important for the shmID. name could be different. maybe not needed cause: (shmget(memory_access_key, NULL, 0)) */
#include "internal.hpp"
#include "log.hpp"
namespace vkvm {
constexpr int PERM = 0666; /* access rights */
@ -60,18 +61,36 @@ namespace vkvm {
unlockSharedMemory();
}
auto getSharedMemory() -> char * {
int shmId = shmget(impl.sharedMemoryKey, 0, 0);
if (shmId < 0) {
//using a local buffer for shared memory testing
char *getLocalMemory(){
static bool givenWarning {false};
if(!givenWarning && impl.localMemoryWarn){
givenWarning = true;
log(LogLevel::WARNING, "no shared memory found, using local memory instead!");
}
if (localSharedMemory.empty()) {
initSemaphore();
constexpr int kilo = 1024;
localSharedMemory.resize(impl.sharedMemorySize * kilo);
}
return &localSharedMemory[0];
}
return static_cast<char *>(shmat(shmId, nullptr, 0));
auto getSharedMemory() -> char * {
if(impl.sharedMemory != nullptr){
return impl.sharedMemory;
}
int shmId = shmget(impl.sharedMemoryKey, 0, 0);
if (shmId < 0) {
//using a local buffer for shared memory testing
return getLocalMemory();
}
char *ptr = static_cast<char *>(shmat(shmId, nullptr, 0));
if(reinterpret_cast<size_t>(ptr) == static_cast<size_t>(-1)){
log(LogLevel::WARNING, strerror(errno));
}else{
impl.sharedMemory = ptr;
return ptr;
}
return getLocalMemory();
}
auto getSharedMemory(char *address, int size, int offset) -> void {

View File

@ -16,7 +16,7 @@ namespace vkvm {
signal(signalNumber, callback);
}
auto getInterrupTable() -> InterruptEntry * {
auto getInterruptTable() -> InterruptEntry * {
return reinterpret_cast<InterruptEntry *>(getSharedMemory() + sizeof(Registers) + impl.reservedSize);
}
@ -36,9 +36,12 @@ namespace vkvm {
}
auto callEvent(EventType type) -> bool {
auto ivt = getInterrupTable();
if (ivt[type].pid != 0) {
sendSignal(ivt[type].pid, ivt[type].signum);
auto ivt = getInterruptTable();
for(int i = 0; i < impl.interruptEntrysPerEventType;i++){
auto &entry= ivt[type * impl.interruptEntrysPerEventType + i];
if (entry.pid != 0) {
sendSignal(entry.pid, entry.signum);
}
}
return true;
}
@ -71,10 +74,10 @@ namespace vkvm {
auto buttonPressed(KeyCode keyCode) -> void {
lockSharedMemory();
auto reg = getRegisters();
if (reg->keyboardBuffer_index_write == sizeof(reg->keyboardBuffer)) {
if (reg->keyboardBuffer_index_write >= sizeof(reg->keyboardBuffer)) {
reg->keyboardBuffer_index_write = 0;
}
reg->keyboardBuffer[reg->keyboardBuffer_index_write++] = keyCode.getValue();
reg->keyboardBuffer[reg->keyboardBuffer_index_write++] = keyCode;
unlockSharedMemory();
}

View File

@ -6,6 +6,7 @@
#include "GraphicMode.hpp"
#include "KeyCode.hpp"
#include "LayoutVersion.hpp"
#include <array>
#include <functional>
#include <sys/types.h>
#include <vector>
@ -54,9 +55,12 @@ constexpr int keyboardBufferSize = 16;
int sharedMemoryPid;
key_t sharedMemoryKey;
int sharedMemorySize;
int interruptEntyCount = 64; //NOLINT
int interruptEntyCount = 256; //NOLINT
int interruptEntrysPerEventType = 8; //NOLINT
int reservedSize = 1024; //NOLINT
std::vector<std::function<void()>> eventTable;
bool localMemoryWarn = true;
char *sharedMemory = nullptr;
};
extern Impl impl;
@ -75,7 +79,7 @@ constexpr int keyboardBufferSize = 16;
auto onSignal(int signalNumber, void(*callback)(int)) -> void;
auto getInterrupTable() -> InterruptEntry *;
auto getInterruptTable() -> InterruptEntry *;
auto getRegisters() -> Registers *;

View File

@ -16,29 +16,36 @@ namespace vkvm {
}
auto setDefaultValues() -> void {
impl.localMemoryWarn = false;
if(getSharedMemory() != nullptr) {
//set default values
setMode(GraphicMode::RGB);
setCharactersPerRow(60);// NOLINT
setCharactersPerColumn(20);// NOLINT
setHeight(600);// NOLINT
setWidth(800);// NOLINT
setMousePosition(42, 42);// NOLINT
setBackgroundColor(Color(200, 50, 20));// NOLINT
setForegroundColor(Color(20, 200, 50));// NOLINT
setMode(GraphicMode::RGB);// NOLINT
setBackgroundColor(black);
setForegroundColor(white);
setRedrawInterval(20);// NOLINT
setTimerInterruptInterval(10);// NOLINT
setFont(FontType(3,"",0,0));
}
impl.localMemoryWarn = true;
}
auto registerEvent(EventType type, const std::function<void()> &handler) -> bool {
int signum = SIGUSR1 + impl.eventTable.size();
auto ivt = getInterrupTable();
auto ivt = getInterruptTable();
lockSharedMemory();
ivt[type].pid = getpid();
ivt[type].signum = signum;
for(int i = 0; i < impl.interruptEntrysPerEventType;i++){
auto &entry= ivt[type * impl.interruptEntrysPerEventType + i];
if (entry.pid == 0) {
entry.pid = getpid();
entry.signum = signum;
impl.eventTable.push_back(handler);
onSignal(signum, [](int sig){
@ -48,25 +55,105 @@ namespace vkvm {
}
}
});
unlockSharedMemory();
return true;
}
}
unlockSharedMemory();
return false;
}
auto setPixel(int x, int y, Color color) -> bool {
char *ptr = getPixelArea() + (y * getWidth() + x) * 3;
lockSharedMemory();
auto reg = getRegisters();
const int bitsPerPixel = 8;
switch(reg->graphicMode) {
case Text: {
int pixelIndex = (y * getWidth() + x);
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (pixelIndex / bitsPerPixel);
if(color == reg->foreground_color){
//set bit to 1
ptr[0] |= (1 << (pixelIndex % bitsPerPixel));
}
else{
//set bit to 0
ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel));
}
break;
}
case TwoColors: {
int pixelIndex = (y * getWidth() + x);
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (pixelIndex / bitsPerPixel);
if(color == reg->foreground_color){
//set bit to 1
ptr[0] |= (1 << (pixelIndex % bitsPerPixel));
}
else{
//set bit to 0
ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel));
}
break;
}
case Gray_256: {
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (y * getWidth() + x);
int avg = color.getRed() + color.getGreen() + color.getBlue();
avg /= 3;
ptr[0] = avg;
break;
}
case RGB: {
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (y * getWidth() + x) * 3;
ptr[0] = color.getRed();
ptr[1] = color.getGreen();
ptr[2] = color.getBlue();
break;
}
}
unlockSharedMemory();
return false;
}
auto getPixel(int x, int y) -> Color {
//TODO(julian): other than RGB colores
//only RGB colores for now
Color color = Color(0,0,0);
auto reg = getRegisters();
const int bitsPerPixel = 8;
switch(reg->graphicMode) {
case Text: {
int pixelIndex = (y * getWidth() + x);
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + pixelIndex / bitsPerPixel;
bool bit = static_cast<bool>(ptr[0] & (1 << (pixelIndex % bitsPerPixel)));
if(bit){
color = reg->foreground_color;
}else{
color =reg->background_color;
}
break;
}
case TwoColors: {
int pixelIndex = (y * getWidth() + x);
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (pixelIndex / bitsPerPixel);
bool bit = static_cast<bool>(ptr[0] & (1 << (pixelIndex % bitsPerPixel)));
if(bit){
color = reg->foreground_color;
}else{
color =reg->background_color;
}
break;
}
case Gray_256: {
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (y * getWidth() + x) * 1;
color = {ptr[0], ptr[0], ptr[0]};
break;
}
case RGB: {
unsigned char *ptr = reinterpret_cast<unsigned char *>(getPixelArea()) + (y * getWidth() + x) * 3;
return {ptr[0], ptr[1], ptr[2]};
color = {ptr[0], ptr[1], ptr[2]};
break;
}
}
return color;
}
auto setText(std::string text) -> bool {
@ -123,7 +210,32 @@ namespace vkvm {
auto setMode(GraphicMode newValue) -> void {
lockSharedMemory();
auto reg = getRegisters();
if(reg->graphicMode != newValue){
std::vector<Color> pixels;
int height = reg->height_pixels;
int width = reg->width_pixels;
pixels.resize(height * width);
for(int y = 0; y < height;y++){
for(int x = 0;x < width;x++){
pixels[y * width + x] = getPixel(x,y);
}
}
getRegisters()->graphicMode = newValue;
unlockSharedMemory();
for(int y = 0; y < height;y++){
for(int x = 0;x < width;x++){
setPixel(x,y, pixels[y * width + x]);
}
}
lockSharedMemory();
}else{
reg->graphicMode = newValue;
}
unlockSharedMemory();
}
@ -151,7 +263,7 @@ namespace vkvm {
return getRegisters()->background_color;
}
auto setBackgroundColor(Color newValue) -> void {
auto setBackgroundColor(const Color &newValue) -> void {
lockSharedMemory();
getRegisters()->background_color = newValue;
unlockSharedMemory();
@ -161,7 +273,7 @@ namespace vkvm {
return getRegisters()->foreground_color;
}
auto setForegroundColor(Color newValue) -> void {
auto setForegroundColor(const Color &newValue) -> void {
lockSharedMemory();
getRegisters()->foreground_color = newValue;
unlockSharedMemory();
@ -177,7 +289,7 @@ namespace vkvm {
auto getFont() -> FontType {
//TODO(julian): get font properly
return font_1;
return {getRegisters()->textMode_font, "", 0, 0};
}
auto setFont(const FontType &newValue) -> void {
@ -192,8 +304,17 @@ namespace vkvm {
}
auto getLastPressedKey() -> KeyCode {
//TODO(julian): get key properly
return KeyCode(0);
lockSharedMemory();
auto keyCode = KeyCode(0);
auto reg = getRegisters();
if(reg->keyboardBuffer_index_read != reg->keyboardBuffer_index_write) {
keyCode = static_cast<KeyCode>(reg->keyboardBuffer[reg->keyboardBuffer_index_read++]);
if (reg->keyboardBuffer_index_read >= sizeof(reg->keyboardBuffer)) {
reg->keyboardBuffer_index_read = 0;
}
}
unlockSharedMemory();
return keyCode;
}
}

View File

@ -153,7 +153,7 @@ namespace vkvm {
* set background color in two color mode.
* @param newValue new background color.
*/
auto setBackgroundColor(Color newValue) -> void;
auto setBackgroundColor(const Color &newValue) -> void;
/**
* get foreground color in two color mode.
@ -165,7 +165,7 @@ namespace vkvm {
* set foreground color in two color mode.
* @param newValue new foreground color.
*/
auto setForegroundColor(Color newValue) -> void;
auto setForegroundColor(const Color &newValue) -> void;
//text mode

49
test/color_test.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "../src/vkvm.hpp"
#include <catch2/catch.hpp>
#include <iostream>
TEST_CASE("Colors") {
vkvm::initialize(0);
vkvm::setPixel(10, 10, vkvm::black);//NOLINT
vkvm::setPixel(11, 11, vkvm::white);//NOLINT
vkvm::setPixel(12, 12, vkvm::green);//NOLINT
vkvm::setPixel(13, 13, vkvm::red);//NOLINT
vkvm::setPixel(14, 14, vkvm::blue);//NOLINT
vkvm::setPixel(15, 15, vkvm::Color(66, 77, 88)); //NOLINT
vkvm::setPixel(16, 16, vkvm::Color(0xFFFFFF));//NOLINT
SECTION("RGB") {
REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT
REQUIRE(vkvm::getPixel(12, 12) == vkvm::green);//NOLINT
REQUIRE(vkvm::getPixel(13, 13) == vkvm::red);//NOLINT
REQUIRE(vkvm::getPixel(14, 14) == vkvm::blue);//NOLINT
REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(66, 77, 88));//NOLINT
REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT
}
SECTION("TwoColors") {
vkvm::setMode(vkvm::TwoColors);
REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT
REQUIRE(vkvm::getPixel(12, 12) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(13, 13) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(14, 14) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(15, 15) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT
}
SECTION("Gray256") {
vkvm::setMode(vkvm::Gray_256);
REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT
REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT
REQUIRE(vkvm::getPixel(12, 12) == vkvm::Color(85, 85, 85));//NOLINT
REQUIRE(vkvm::getPixel(13, 13) == vkvm::Color(85, 85, 85));//NOLINT
REQUIRE(vkvm::getPixel(14, 14) == vkvm::Color(85, 85, 85));//NOLINT
REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(77, 77, 77));//NOLINT
REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT
}
}