pandemonium_engine/platform/frt/video_fbdev.cpp

161 lines
3.9 KiB
C++

// video_fbdev.cc
/*
* FRT - A Godot platform targeting single board computers
* Copyright (c) 2017-2019 Emanuele Fornara
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "frt.h"
#include <stdio.h>
#include "bits/egl_base_context.h"
#define FRT_DL_SKIP
#include "dl/gles2.gen.h"
static bool frt_load_gles(int version) {
return frt_load_gles2("libGLESv2.so.2");
}
#define FRT_FBDEV_MALI 1
static int probe_fbdev() {
return FRT_FBDEV_MALI;
}
namespace frt {
class EGLFBDevContext : public EGLBaseContext {
public:
virtual void create_surface(const Vec2 &size) = 0;
virtual ~EGLFBDevContext() {}
};
class EGLMaliContext : public EGLFBDevContext {
private:
struct {
uint16_t width;
uint16_t height;
} nativewindow;
public:
void create_surface(const Vec2 &size) {
nativewindow.width = size.x;
nativewindow.height = size.y;
surface = eglCreateWindowSurface(display, config,
(EGLNativeWindowType)&nativewindow, 0);
if (surface == EGL_NO_SURFACE)
fatal("video_fbdev: eglCreateWindowSurface failed.");
}
};
class VideoFBDev : public Video, public ContextGL {
private:
bool initialized;
Vec2 screen_size;
Vec2 view_size;
EGLFBDevContext *egl;
int gl_version;
bool vsync;
void gles_init() {
egl->init(gl_version);
egl->create_surface(view_size);
egl->make_current();
initialized = true;
}
public:
// Module
VideoFBDev()
: initialized(false), egl(0), gl_version(2), vsync(true) {}
const char *get_id() const { return "video_fbdev"; }
bool probe() {
if (egl)
return true;
switch (probe_fbdev()) {
case FRT_FBDEV_MALI:
egl = new EGLMaliContext();
break;
default:
fatal("video_fbdev: internal error.");
}
if (!frt_load_egl("libEGL.so.1")) {
delete egl;
egl = 0;
return false;
}
screen_size.x = 720;
screen_size.y = 480;
return true;
}
void cleanup() {
if (initialized) {
egl->destroy_surface();
egl->cleanup();
initialized = false;
}
if (egl) {
delete egl;
egl = 0;
}
}
// Video
Vec2 get_screen_size() const { return screen_size; }
Vec2 get_view_size() const { return view_size; }
void set_title(const char *title) {}
Vec2 move_pointer(const Vec2 &screen) { return screen; }
void show_pointer(bool enable) {}
ContextGL *create_the_gl_context(int version, Vec2 size) {
if (!frt_load_gles(version))
return 0;
gl_version = version;
view_size = size;
return this;
}
bool provides_quit() { return false; }
// ContextGL
void release_current() {
egl->release_current();
}
void make_current() {
egl->make_current();
}
void swap_buffers() {
egl->swap_buffers();
}
int get_window_width() { return view_size.x; }
int get_window_height() { return view_size.y; }
bool initialize() {
gles_init();
return true;
}
void set_use_vsync(bool use) {
egl->swap_interval(use ? 1 : 0);
vsync = use;
}
bool is_using_vsync() const { return vsync; }
};
FRT_REGISTER(VideoFBDev)
} // namespace frt