summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kmscube/CMakeLists.txt9
-rw-r--r--kmscube/cube-egl.cpp95
-rw-r--r--kmscube/cube-egl.h34
-rw-r--r--kmscube/cube-gbm.cpp398
-rw-r--r--kmscube/cube-gles2.cpp264
-rw-r--r--kmscube/cube-gles2.h22
-rw-r--r--kmscube/cube-null.cpp36
-rw-r--r--kmscube/cube-wl.cpp122
-rw-r--r--kmscube/cube-x11.cpp67
-rw-r--r--kmscube/cube.cpp69
-rw-r--r--kmscube/cube.h103
-rw-r--r--kmscube/esTransform.c2
-rw-r--r--kmscube/esTransform.h (renamed from kmscube/esUtil.h)0
-rw-r--r--kmscube/kmscube.cpp830
14 files changed, 1123 insertions, 928 deletions
diff --git a/kmscube/CMakeLists.txt b/kmscube/CMakeLists.txt
index 9c1a9d6..15b4dbf 100644
--- a/kmscube/CMakeLists.txt
+++ b/kmscube/CMakeLists.txt
@@ -5,6 +5,9 @@ pkg_check_modules(GBM gbm REQUIRED)
pkg_check_modules(X11 x11 REQUIRED)
pkg_check_modules(XCB xcb REQUIRED)
pkg_check_modules(X11XCB x11-xcb REQUIRED)
+pkg_check_modules(WL wayland-client REQUIRED)
+pkg_check_modules(WL_EGL wayland-egl REQUIRED)
+
include_directories(
${LIBDRM_INCLUDE_DIRS}
@@ -26,7 +29,9 @@ link_directories(
${X11XCB_LIBRARY_DIRS}
)
-add_executable (kmscube kmscube.cpp esTransform.c esUtil.h cube.h)
+add_executable (kmscube cube.cpp cube.h cube-egl.cpp cube-egl.h cube-gles2.cpp cube-gles2.h
+ cube-null.cpp cube-gbm.cpp cube-x11.cpp cube-wl.cpp
+ esTransform.c esTransform.h)
target_link_libraries(kmscube kms++ kmstest
${LIBDRM_LIBRARIES}
${GLESv2_LIBRARIES}
@@ -35,4 +40,6 @@ target_link_libraries(kmscube kms++ kmstest
${X11_LIBRARIES}
${XCB_LIBRARIES}
${X11XCB_LIBRARIES}
+ ${WL_LIBRARIES}
+ ${WL_EGL_LIBRARIES}
)
diff --git a/kmscube/cube-egl.cpp b/kmscube/cube-egl.cpp
new file mode 100644
index 0000000..4213536
--- /dev/null
+++ b/kmscube/cube-egl.cpp
@@ -0,0 +1,95 @@
+#include "cube-egl.h"
+#include "cube.h"
+
+#include "test.h"
+
+using namespace std;
+
+EglState::EglState(void *native_display)
+{
+ EGLBoolean b;
+ EGLint major, minor, n;
+
+ static const EGLint context_attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ static const EGLint config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
+ m_display = eglGetDisplay((EGLNativeDisplayType)native_display);
+ FAIL_IF(!m_display, "failed to get egl display");
+
+ b = eglInitialize(m_display, &major, &minor);
+ FAIL_IF(!b, "failed to initialize");
+
+ if (s_verbose) {
+ printf("Using display %p with EGL version %d.%d\n", m_display, major, minor);
+
+ printf("EGL_VENDOR: %s\n", eglQueryString(m_display, EGL_VENDOR));
+ printf("EGL_VERSION: %s\n", eglQueryString(m_display, EGL_VERSION));
+ printf("EGL_EXTENSIONS: %s\n", eglQueryString(m_display, EGL_EXTENSIONS));
+ printf("EGL_CLIENT_APIS: %s\n", eglQueryString(m_display, EGL_CLIENT_APIS));
+ }
+
+ b = eglBindAPI(EGL_OPENGL_ES_API);
+ FAIL_IF(!b, "failed to bind api EGL_OPENGL_ES_API");
+
+ b = eglChooseConfig(m_display, config_attribs, &m_config, 1, &n);
+ FAIL_IF(!b || n != 1, "failed to choose config");
+
+ auto getconf = [this](EGLint a) { EGLint v = -1; eglGetConfigAttrib(m_display, m_config, a, &v); return v; };
+
+ if (s_verbose) {
+ printf("EGL Config %d: color buf %d/%d/%d/%d = %d, depth %d, stencil %d\n",
+ getconf(EGL_CONFIG_ID),
+ getconf(EGL_ALPHA_SIZE),
+ getconf(EGL_RED_SIZE),
+ getconf(EGL_GREEN_SIZE),
+ getconf(EGL_BLUE_SIZE),
+ getconf(EGL_BUFFER_SIZE),
+ getconf(EGL_DEPTH_SIZE),
+ getconf(EGL_STENCIL_SIZE));
+ }
+
+ m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, context_attribs);
+ FAIL_IF(!m_context, "failed to create context");
+
+ eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, m_context);
+}
+
+EglState::~EglState()
+{
+ eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(m_display);
+}
+
+EglSurface::EglSurface(const EglState &egl, void *native_window)
+ : egl(egl)
+{
+ esurface = eglCreateWindowSurface(egl.display(), egl.config(), (EGLNativeWindowType)native_window, NULL);
+ FAIL_IF(esurface == EGL_NO_SURFACE, "failed to create egl surface");
+}
+
+EglSurface::~EglSurface()
+{
+ eglDestroySurface(egl.display(), esurface);
+}
+
+void EglSurface::make_current()
+{
+ eglMakeCurrent(egl.display(), esurface, esurface, egl.context());
+}
+
+void EglSurface::swap_buffers()
+{
+ eglSwapBuffers(egl.display(), esurface);
+}
diff --git a/kmscube/cube-egl.h b/kmscube/cube-egl.h
new file mode 100644
index 0000000..a7de103
--- /dev/null
+++ b/kmscube/cube-egl.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <EGL/egl.h>
+
+class EglState
+{
+public:
+ EglState(void *native_display);
+ ~EglState();
+
+ EGLDisplay display() const { return m_display; }
+ EGLConfig config() const { return m_config; }
+ EGLContext context() const { return m_context; }
+
+private:
+ EGLDisplay m_display;
+ EGLConfig m_config;
+ EGLContext m_context;
+};
+
+class EglSurface
+{
+public:
+ EglSurface(const EglState& egl, void *native_window);
+ ~EglSurface();
+
+ void make_current();
+ void swap_buffers();
+
+private:
+ const EglState& egl;
+
+ EGLSurface esurface;
+};
diff --git a/kmscube/cube-gbm.cpp b/kmscube/cube-gbm.cpp
new file mode 100644
index 0000000..a65f693
--- /dev/null
+++ b/kmscube/cube-gbm.cpp
@@ -0,0 +1,398 @@
+#include <chrono>
+#include <cstdio>
+#include <vector>
+#include <memory>
+#include <algorithm>
+#include <poll.h>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+
+#include <kms++.h>
+#include "test.h"
+#include "cube-egl.h"
+#include "cube-gles2.h"
+
+using namespace kms;
+using namespace std;
+
+static int s_flip_pending;
+static bool s_need_exit;
+
+static bool s_support_planes;
+
+class GbmDevice
+{
+public:
+ GbmDevice(Card& card)
+ {
+ m_dev = gbm_create_device(card.fd());
+ FAIL_IF(!m_dev, "failed to create gbm device");
+ }
+
+ ~GbmDevice()
+ {
+ gbm_device_destroy(m_dev);
+ }
+
+ GbmDevice(const GbmDevice& other) = delete;
+ GbmDevice& operator=(const GbmDevice& other) = delete;
+
+ struct gbm_device* handle() const { return m_dev; }
+
+private:
+ struct gbm_device* m_dev;
+};
+
+class GbmSurface
+{
+public:
+ GbmSurface(GbmDevice& gdev, int width, int height)
+ {
+ m_surface = gbm_surface_create(gdev.handle(), width, height,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ FAIL_IF(!m_surface, "failed to create gbm surface");
+ }
+
+ ~GbmSurface()
+ {
+ gbm_surface_destroy(m_surface);
+ }
+
+ GbmSurface(const GbmSurface& other) = delete;
+ GbmSurface& operator=(const GbmSurface& other) = delete;
+
+ bool has_free()
+ {
+ return gbm_surface_has_free_buffers(m_surface);
+ }
+
+ gbm_bo* lock_front_buffer()
+ {
+ return gbm_surface_lock_front_buffer(m_surface);
+ }
+
+ void release_buffer(gbm_bo *bo)
+ {
+ gbm_surface_release_buffer(m_surface, bo);
+ }
+
+ struct gbm_surface* handle() const { return m_surface; }
+
+private:
+ struct gbm_surface* m_surface;
+};
+
+class GbmEglSurface
+{
+public:
+ GbmEglSurface(Card& card, GbmDevice& gdev, const EglState& egl, int width, int height)
+ : card(card), gdev(gdev), egl(egl), m_width(width), m_height(height),
+ bo_prev(0), bo_next(0)
+ {
+ gsurface = unique_ptr<GbmSurface>(new GbmSurface(gdev, width, height));
+ esurface = eglCreateWindowSurface(egl.display(), egl.config(), gsurface->handle(), NULL);
+ FAIL_IF(esurface == EGL_NO_SURFACE, "failed to create egl surface");
+ }
+
+ ~GbmEglSurface()
+ {
+ if (bo_next)
+ gsurface->release_buffer(bo_next);
+ eglDestroySurface(egl.display(), esurface);
+ }
+
+ void make_current()
+ {
+ FAIL_IF(!gsurface->has_free(), "No free buffers");
+
+ eglMakeCurrent(egl.display(), esurface, esurface, egl.context());
+ }
+
+ void swap_buffers()
+ {
+ eglSwapBuffers(egl.display(), esurface);
+ }
+
+ static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
+ {
+ auto fb = reinterpret_cast<Framebuffer*>(data);
+ delete fb;
+ }
+
+ static Framebuffer* drm_fb_get_from_bo(struct gbm_bo *bo, Card& card)
+ {
+ auto fb = reinterpret_cast<Framebuffer*>(gbm_bo_get_user_data(bo));
+ if (fb)
+ return fb;
+
+ uint32_t width = gbm_bo_get_width(bo);
+ uint32_t height = gbm_bo_get_height(bo);
+ uint32_t stride = gbm_bo_get_stride(bo);
+ uint32_t handle = gbm_bo_get_handle(bo).u32;
+
+ fb = new ExtFramebuffer(card, width, height, 24, 32, stride, handle);
+
+ gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
+
+ return fb;
+ }
+
+ struct Framebuffer* lock_next()
+ {
+ bo_prev = bo_next;
+ bo_next = gsurface->lock_front_buffer();
+ FAIL_IF(!bo_next, "could not lock gbm buffer");
+ return drm_fb_get_from_bo(bo_next, card);
+ }
+
+ void free_prev()
+ {
+ if (bo_prev) {
+ gsurface->release_buffer(bo_prev);
+ bo_prev = 0;
+ }
+ }
+
+ uint32_t width() const { return m_width; }
+ uint32_t height() const { return m_height; }
+
+private:
+ Card& card;
+ GbmDevice& gdev;
+ const EglState& egl;
+
+ unique_ptr<GbmSurface> gsurface;
+ EGLSurface esurface;
+
+ int m_width;
+ int m_height;
+
+ struct gbm_bo* bo_prev;
+ struct gbm_bo* bo_next;
+};
+
+class OutputHandler : private PageFlipHandlerBase
+{
+public:
+ OutputHandler(Card& card, GbmDevice& gdev, const EglState& egl, Connector* connector, Crtc* crtc, Videomode& mode, Plane* plane, float rotation_mult)
+ : m_frame_num(0), m_connector(connector), m_crtc(crtc), m_plane(plane), m_mode(mode),
+ m_rotation_mult(rotation_mult)
+ {
+ m_surface1 = unique_ptr<GbmEglSurface>(new GbmEglSurface(card, gdev, egl, mode.hdisplay, mode.vdisplay));
+ m_scene1 = unique_ptr<GlScene>(new GlScene());
+ m_scene1->set_viewport(m_surface1->width(), m_surface1->height());
+
+ if (m_plane) {
+ m_surface2 = unique_ptr<GbmEglSurface>(new GbmEglSurface(card, gdev, egl, 400, 400));
+ m_scene2 = unique_ptr<GlScene>(new GlScene());
+ m_scene2->set_viewport(m_surface2->width(), m_surface2->height());
+ }
+ }
+
+ OutputHandler(const OutputHandler& other) = delete;
+ OutputHandler& operator=(const OutputHandler& other) = delete;
+
+ void setup()
+ {
+ int ret;
+
+ m_surface1->make_current();
+ m_surface1->swap_buffers();
+ struct Framebuffer* fb = m_surface1->lock_next();
+
+ struct Framebuffer* planefb = 0;
+
+ if (m_plane) {
+ m_surface2->make_current();
+ m_surface2->swap_buffers();
+ planefb = m_surface2->lock_next();
+ }
+
+
+ ret = m_crtc->set_mode(m_connector, *fb, m_mode);
+ FAIL_IF(ret, "failed to set mode");
+
+ if (m_crtc->card().has_atomic()) {
+ Plane* root_plane = 0;
+ for (Plane* p : m_crtc->get_possible_planes()) {
+ if (p->crtc_id() == m_crtc->id()) {
+ root_plane = p;
+ break;
+ }
+ }
+
+ FAIL_IF(!root_plane, "No primary plane for crtc %d", m_crtc->id());
+
+ m_root_plane = root_plane;
+ }
+
+ if (m_plane) {
+ ret = m_crtc->set_plane(m_plane, *planefb,
+ 0, 0, planefb->width(), planefb->height(),
+ 0, 0, planefb->width(), planefb->height());
+ FAIL_IF(ret, "failed to set plane");
+ }
+ }
+
+ void start_flipping()
+ {
+ m_t1 = chrono::steady_clock::now();
+ queue_next();
+ }
+
+private:
+ void handle_page_flip(uint32_t frame, double time)
+ {
+ ++m_frame_num;
+
+ if (m_frame_num % 100 == 0) {
+ auto t2 = chrono::steady_clock::now();
+ chrono::duration<float> fsec = t2 - m_t1;
+ printf("fps: %f\n", 100.0 / fsec.count());
+ m_t1 = t2;
+ }
+
+ s_flip_pending--;
+
+ m_surface1->free_prev();
+ if (m_plane)
+ m_surface2->free_prev();
+
+ if (s_need_exit)
+ return;
+
+ queue_next();
+ }
+
+ void queue_next()
+ {
+ m_surface1->make_current();
+ m_scene1->draw(m_frame_num * m_rotation_mult);
+ m_surface1->swap_buffers();
+ struct Framebuffer* fb = m_surface1->lock_next();
+
+ struct Framebuffer* planefb = 0;
+
+ if (m_plane) {
+ m_surface2->make_current();
+ m_scene2->draw(m_frame_num * m_rotation_mult * 2);
+ m_surface2->swap_buffers();
+ planefb = m_surface2->lock_next();
+ }
+
+ if (m_crtc->card().has_atomic()) {
+ int r;
+
+ AtomicReq req(m_crtc->card());
+
+ req.add(m_root_plane, "FB_ID", fb->id());
+ if (m_plane)
+ req.add(m_plane, "FB_ID", planefb->id());
+
+ r = req.test();
+ FAIL_IF(r, "atomic test failed");
+
+ r = req.commit(this);
+ FAIL_IF(r, "atomic commit failed");
+ } else {
+ int ret;
+
+ ret = m_crtc->page_flip(*fb, this);
+ FAIL_IF(ret, "failed to queue page flip");
+
+ if (m_plane) {
+ ret = m_crtc->set_plane(m_plane, *planefb,
+ 0, 0, planefb->width(), planefb->height(),
+ 0, 0, planefb->width(), planefb->height());
+ FAIL_IF(ret, "failed to set plane");
+ }
+ }
+
+ s_flip_pending++;
+ }
+
+ int m_frame_num;
+ chrono::steady_clock::time_point m_t1;
+
+ Connector* m_connector;
+ Crtc* m_crtc;
+ Plane* m_plane;
+ Videomode m_mode;
+ Plane* m_root_plane;
+
+ unique_ptr<GbmEglSurface> m_surface1;
+ unique_ptr<GbmEglSurface> m_surface2;
+
+ unique_ptr<GlScene> m_scene1;
+ unique_ptr<GlScene> m_scene2;
+
+ float m_rotation_mult;
+};
+
+void main_gbm()
+{
+ Card card;
+
+ GbmDevice gdev(card);
+ EglState egl(gdev.handle());
+
+ vector<unique_ptr<OutputHandler>> outputs;
+ vector<Plane*> used_planes;
+
+ float rot_mult = 1;
+
+ for (auto pipe : card.get_connected_pipelines()) {
+ auto connector = pipe.connector;
+ auto crtc = pipe.crtc;
+ auto mode = connector->get_default_mode();
+
+ Plane* plane = 0;
+
+ if (s_support_planes) {
+ for (Plane* p : crtc->get_possible_planes()) {
+ if (find(used_planes.begin(), used_planes.end(), p) != used_planes.end())
+ continue;
+
+ if (p->plane_type() != PlaneType::Overlay)
+ continue;
+
+ plane = p;
+ break;
+ }
+ }
+
+ if (plane)
+ used_planes.push_back(plane);
+
+ auto out = new OutputHandler(card, gdev, egl, connector, crtc, mode, plane, rot_mult);
+ outputs.emplace_back(out);
+
+ rot_mult *= 1.33;
+ }
+
+ for (auto& out : outputs)
+ out->setup();
+
+ for (auto& out : outputs)
+ out->start_flipping();
+
+ struct pollfd fds[2] = { 0 };
+ fds[0].fd = 0;
+ fds[0].events = POLLIN;
+ fds[1].fd = card.fd();
+ fds[1].events = POLLIN;
+
+ while (!s_need_exit || s_flip_pending) {
+ int r = poll(fds, ARRAY_SIZE(fds), -1);
+ FAIL_IF(r < 0, "poll error %d", r);
+
+ if (fds[0].revents)
+ s_need_exit = true;
+
+ if (fds[1].revents)
+ card.call_page_flip_handlers();
+ }
+}
diff --git a/kmscube/cube-gles2.cpp b/kmscube/cube-gles2.cpp
new file mode 100644
index 0000000..68b3831
--- /dev/null
+++ b/kmscube/cube-gles2.cpp
@@ -0,0 +1,264 @@
+#include "esTransform.h"
+#include "cube-gles2.h"
+#include "cube.h"
+
+#include "test.h"
+
+using namespace std;
+
+GlScene::GlScene()
+{
+ GLuint vertex_shader, fragment_shader;
+ GLint ret;
+
+ static const GLfloat vVertices[] = {
+ // front
+ -1.0f, -1.0f, +1.0f, // point blue
+ +1.0f, -1.0f, +1.0f, // point magenta
+ -1.0f, +1.0f, +1.0f, // point cyan
+ +1.0f, +1.0f, +1.0f, // point white
+ // back
+ +1.0f, -1.0f, -1.0f, // point red
+ -1.0f, -1.0f, -1.0f, // point black
+ +1.0f, +1.0f, -1.0f, // point yellow
+ -1.0f, +1.0f, -1.0f, // point green
+ // right
+ +1.0f, -1.0f, +1.0f, // point magenta
+ +1.0f, -1.0f, -1.0f, // point red
+ +1.0f, +1.0f, +1.0f, // point white
+ +1.0f, +1.0f, -1.0f, // point yellow
+ // left
+ -1.0f, -1.0f, -1.0f, // point black
+ -1.0f, -1.0f, +1.0f, // point blue
+ -1.0f, +1.0f, -1.0f, // point green
+ -1.0f, +1.0f, +1.0f, // point cyan
+ // top
+ -1.0f, +1.0f, +1.0f, // point cyan
+ +1.0f, +1.0f, +1.0f, // point white
+ -1.0f, +1.0f, -1.0f, // point green
+ +1.0f, +1.0f, -1.0f, // point yellow
+ // bottom
+ -1.0f, -1.0f, -1.0f, // point black
+ +1.0f, -1.0f, -1.0f, // point red
+ -1.0f, -1.0f, +1.0f, // point blue
+ +1.0f, -1.0f, +1.0f // point magenta
+ };
+
+ static const GLfloat vColors[] = {
+ // front
+ 0.0f, 0.0f, 1.0f, // blue
+ 1.0f, 0.0f, 1.0f, // magenta
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 1.0f, 1.0f, // white
+ // back
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 0.0f, 0.0f, // black
+ 1.0f, 1.0f, 0.0f, // yellow
+ 0.0f, 1.0f, 0.0f, // green
+ // right
+ 1.0f, 0.0f, 1.0f, // magenta
+ 1.0f, 0.0f, 0.0f, // red
+ 1.0f, 1.0f, 1.0f, // white
+ 1.0f, 1.0f, 0.0f, // yellow
+ // left
+ 0.0f, 0.0f, 0.0f, // black
+ 0.0f, 0.0f, 1.0f, // blue
+ 0.0f, 1.0f, 0.0f, // green
+ 0.0f, 1.0f, 1.0f, // cyan
+ // top
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 1.0f, 1.0f, // white
+ 0.0f, 1.0f, 0.0f, // green
+ 1.0f, 1.0f, 0.0f, // yellow
+ // bottom
+ 0.0f, 0.0f, 0.0f, // black
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 0.0f, 1.0f, // blue
+ 1.0f, 0.0f, 1.0f // magenta
+ };
+
+ static const GLfloat vNormals[] = {
+ // front
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ +0.0f, +0.0f, +1.0f, // forward
+ // back
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ +0.0f, +0.0f, -1.0f, // backbard
+ // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ +1.0f, +0.0f, +0.0f, // right
+ // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ -1.0f, +0.0f, +0.0f, // left
+ // top
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ +0.0f, +1.0f, +0.0f, // up
+ // bottom
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f, // down
+ +0.0f, -1.0f, +0.0f // down
+ };
+
+ static const char *vertex_shader_source =
+ "uniform mat4 modelviewMatrix; \n"
+ "uniform mat4 modelviewprojectionMatrix;\n"
+ "uniform mat3 normalMatrix; \n"
+ " \n"
+ "attribute vec4 in_position; \n"
+ "attribute vec3 in_normal; \n"
+ "attribute vec4 in_color; \n"
+ "\n"
+ "vec4 lightSource = vec4(2.0, 2.0, 20.0, 0.0);\n"
+ " \n"
+ "varying vec4 vVaryingColor; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = modelviewprojectionMatrix * in_position;\n"
+ " vec3 vEyeNormal = normalMatrix * in_normal;\n"
+ " vec4 vPosition4 = modelviewMatrix * in_position;\n"
+ " vec3 vPosition3 = vPosition4.xyz / vPosition4.w;\n"
+ " vec3 vLightDir = normalize(lightSource.xyz - vPosition3);\n"
+ " float diff = max(0.0, dot(vEyeNormal, vLightDir));\n"
+ " vVaryingColor = vec4(diff * in_color.rgb, 1.0);\n"
+ "} \n";
+
+ static const char *fragment_shader_source =
+ "precision mediump float; \n"
+ " \n"
+ "varying vec4 vVaryingColor; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vVaryingColor; \n"
+ "} \n";
+
+
+ if (s_verbose) {
+ printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
+ printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
+ }
+
+ vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+
+ glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
+ glCompileShader(vertex_shader);
+
+ glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &ret);
+ FAIL_IF(!ret, "vertex shader compilation failed!");
+
+ fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+ glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
+ glCompileShader(fragment_shader);
+
+ glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &ret);
+ FAIL_IF(!ret, "fragment shader compilation failed!");
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vertex_shader);
+ glAttachShader(program, fragment_shader);
+
+ glBindAttribLocation(program, 0, "in_position");
+ glBindAttribLocation(program, 1, "in_normal");
+ glBindAttribLocation(program, 2, "in_color");
+
+ glLinkProgram(program);
+
+ glGetProgramiv(program, GL_LINK_STATUS, &ret);
+ FAIL_IF(!ret, "program linking failed!");
+
+ glUseProgram(program);
+
+ m_modelviewmatrix = glGetUniformLocation(program, "modelviewMatrix");
+ m_modelviewprojectionmatrix = glGetUniformLocation(program, "modelviewprojectionMatrix");
+ m_normalmatrix = glGetUniformLocation(program, "normalMatrix");
+
+ glEnable(GL_CULL_FACE);
+
+ GLintptr positionsoffset = 0;
+ GLintptr colorsoffset = sizeof(vVertices);
+ GLintptr normalsoffset = sizeof(vVertices) + sizeof(vColors);
+ GLuint vbo;
+
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0, GL_STATIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, positionsoffset, sizeof(vVertices), &vVertices[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, colorsoffset, sizeof(vColors), &vColors[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, normalsoffset, sizeof(vNormals), &vNormals[0]);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)positionsoffset);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)normalsoffset);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)colorsoffset);
+ glEnableVertexAttribArray(2);
+}
+
+void GlScene::set_viewport(uint32_t width, uint32_t height)
+{
+ m_width = width;
+ m_height = height;
+}
+
+void GlScene::draw(uint32_t framenum)
+{
+ glViewport(0, 0, m_width, m_height);
+
+ glClearColor(0.5, 0.5, 0.5, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ ESMatrix modelview;
+
+ esMatrixLoadIdentity(&modelview);
+ esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
+ esRotate(&modelview, 45.0f + (0.75f * framenum), 1.0f, 0.0f, 0.0f);
+ esRotate(&modelview, 45.0f - (0.5f * framenum), 0.0f, 1.0f, 0.0f);
+ esRotate(&modelview, 10.0f + (0.45f * framenum), 0.0f, 0.0f, 1.0f);
+
+ GLfloat aspect = (float)m_height / m_width;
+
+ ESMatrix projection;
+ esMatrixLoadIdentity(&projection);
+ esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
+
+ ESMatrix modelviewprojection;
+ esMatrixLoadIdentity(&modelviewprojection);
+ esMatrixMultiply(&modelviewprojection, &modelview, &projection);
+
+ float normal[9];
+ normal[0] = modelview.m[0][0];
+ normal[1] = modelview.m[0][1];
+ normal[2] = modelview.m[0][2];
+ normal[3] = modelview.m[1][0];
+ normal[4] = modelview.m[1][1];
+ normal[5] = modelview.m[1][2];
+ normal[6] = modelview.m[2][0];
+ normal[7] = modelview.m[2][1];
+ normal[8] = modelview.m[2][2];
+
+ glUniformMatrix4fv(m_modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
+ glUniformMatrix4fv(m_modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
+ glUniformMatrix3fv(m_normalmatrix, 1, GL_FALSE, normal);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
+}
diff --git a/kmscube/cube-gles2.h b/kmscube/cube-gles2.h
new file mode 100644
index 0000000..983c133
--- /dev/null
+++ b/kmscube/cube-gles2.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <GLES2/gl2.h>
+
+class GlScene
+{
+public:
+ GlScene();
+
+ GlScene(const GlScene& other) = delete;
+ GlScene& operator=(const GlScene& other) = delete;
+
+ void set_viewport(uint32_t width, uint32_t height);
+
+ void draw(uint32_t framenum);
+
+private:
+ GLint m_modelviewmatrix, m_modelviewprojectionmatrix, m_normalmatrix;
+
+ uint32_t m_width;
+ uint32_t m_height;
+};
diff --git a/kmscube/cube-null.cpp b/kmscube/cube-null.cpp
new file mode 100644
index 0000000..42f2ac2
--- /dev/null
+++ b/kmscube/cube-null.cpp
@@ -0,0 +1,36 @@
+#include <poll.h>
+
+#include "cube-egl.h"
+#include "cube-gles2.h"
+#include "cube.h"
+
+#include "test.h"
+
+using namespace std;
+
+void main_null()
+{
+ EglState egl(EGL_DEFAULT_DISPLAY);
+ EglSurface surface(egl, 0);
+ GlScene scene;
+
+ scene.set_viewport(600, 600);
+
+ int framenum = 0;
+
+ struct pollfd fds[1] = { 0 };
+ fds[0].fd = 0;
+ fds[0].events = POLLIN;
+
+ while (true) {
+ int r = poll(fds, ARRAY_SIZE(fds), 0);
+ ASSERT(r >= 0);
+
+ if (fds[0].revents)
+ break;
+
+ surface.make_current();
+ scene.draw(framenum++);
+ surface.swap_buffers();
+ }
+}
diff --git a/kmscube/cube-wl.cpp b/kmscube/cube-wl.cpp
new file mode 100644
index 0000000..c8dfa56
--- /dev/null
+++ b/kmscube/cube-wl.cpp
@@ -0,0 +1,122 @@
+
+#include <wayland-client.h>
+#include <wayland-egl.h>
+
+#include <EGL/egl.h>
+#include <GL/gl.h>
+
+#include <string.h>
+
+static struct wl_compositor *s_compositor = NULL;
+static struct wl_shell *s_shell = NULL;
+static EGLDisplay s_egl_display;
+static char s_running = 1;
+
+struct window {
+ EGLContext egl_context;
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct wl_egl_window *egl_window;
+ EGLSurface egl_surface;
+};
+
+// listeners
+static void registry_add_object(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
+{
+ if (!strcmp(interface, "wl_compositor"))
+ s_compositor = (struct wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, 0);
+ else if (!strcmp(interface, "wl_shell"))
+ s_shell = (struct wl_shell*)wl_registry_bind(registry, name, &wl_shell_interface, 0);
+}
+
+static void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name)
+{
+
+}
+
+static struct wl_registry_listener registry_listener = { &registry_add_object, &registry_remove_object };
+
+static void shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial)
+{
+ wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void shell_surface_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height)
+{
+ struct window *window = (struct window*)data;
+
+ wl_egl_window_resize(window->egl_window, width, height, 0, 0);
+}
+
+static void shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface)
+{
+
+}
+
+static struct wl_shell_surface_listener shell_surface_listener = { &shell_surface_ping, &shell_surface_configure, &shell_surface_popup_done };
+
+static void create_window(struct window *window, int32_t width, int32_t height)
+{
+ eglBindAPI(EGL_OPENGL_API);
+ EGLint attributes[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_NONE
+ };
+ EGLConfig config;
+ EGLint num_config;
+ eglChooseConfig(s_egl_display, attributes, &config, 1, &num_config);
+ window->egl_context = eglCreateContext(s_egl_display, config, EGL_NO_CONTEXT, NULL);
+
+ window->surface = wl_compositor_create_surface(s_compositor);
+ window->shell_surface = wl_shell_get_shell_surface(s_shell, window->surface);
+ wl_shell_surface_add_listener(window->shell_surface, &shell_surface_listener, window);
+ wl_shell_surface_set_toplevel(window->shell_surface);
+ window->egl_window = wl_egl_window_create(window->surface, width, height);
+ window->egl_surface = eglCreateWindowSurface(s_egl_display, config, window->egl_window, NULL);
+ eglMakeCurrent(s_egl_display, window->egl_surface, window->egl_surface, window->egl_context);
+}
+
+static void delete_window(struct window *window)
+{
+ eglDestroySurface(s_egl_display, window->egl_surface);
+ wl_egl_window_destroy(window->egl_window);
+ wl_shell_surface_destroy(window->shell_surface);
+ wl_surface_destroy(window->surface);
+ eglDestroyContext(s_egl_display, window->egl_context);
+}
+
+static void draw_window(struct window *window)
+{
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers(s_egl_display, window->egl_surface);
+}
+
+int main_wl()
+{
+ struct wl_display *display = wl_display_connect(NULL);
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, &registry_listener, NULL);
+ wl_display_roundtrip(display);
+
+ s_egl_display = eglGetDisplay(display);
+ eglInitialize(s_egl_display, NULL, NULL);
+
+ uint32_t width = 600;
+ uint32_t height = 600;
+
+ struct window window;
+ create_window(&window, width, height);
+
+ while (s_running) {
+ wl_display_dispatch_pending(display);
+ draw_window(&window);
+ }
+
+ delete_window(&window);
+ eglTerminate(s_egl_display);
+ wl_display_disconnect(display);
+ return 0;
+}
diff --git a/kmscube/cube-x11.cpp b/kmscube/cube-x11.cpp
new file mode 100644
index 0000000..7f01ae8
--- /dev/null
+++ b/kmscube/cube-x11.cpp
@@ -0,0 +1,67 @@
+
+#include <X11/Xlib-xcb.h>
+
+#include "cube-egl.h"
+#include "cube-gles2.h"
+
+#include "test.h"
+
+using namespace std;
+
+void main_x11()
+{
+ Display* display = XOpenDisplay(NULL);
+
+ xcb_connection_t *connection = XGetXCBConnection(display);
+
+ /* Get the first screen */
+ const xcb_setup_t *setup = xcb_get_setup (connection);
+ xcb_screen_t *screen = xcb_setup_roots_iterator (setup).data;
+
+ /* Create the window */
+
+ uint32_t width = 600;
+ uint32_t height = 600;
+
+ const uint32_t xcb_window_attrib_mask = XCB_CW_EVENT_MASK;
+ const uint32_t xcb_window_attrib_list[] = {
+ XCB_EVENT_MASK_EXPOSURE,
+ };
+
+ xcb_window_t window = xcb_generate_id (connection);
+ xcb_create_window (connection, /* Connection */
+ XCB_COPY_FROM_PARENT, /* depth (same as root)*/
+ window, /* window Id */
+ screen->root, /* parent window */
+ 0, 0, /* x, y */
+ width, height, /* width, height */
+ 0, /* border_width */
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
+ screen->root_visual, /* visual */
+ xcb_window_attrib_mask,
+ xcb_window_attrib_list);
+
+ xcb_map_window (connection, window);
+ xcb_flush (connection);
+
+ EglState egl(display);
+ EglSurface surface(egl, (void*)(uintptr_t)window);
+ GlScene scene;
+
+ scene.set_viewport(width, height);
+
+ int framenum = 0;
+
+ surface.make_current();
+ surface.swap_buffers();
+
+ xcb_generic_event_t *event;
+ while ( (event = xcb_poll_for_event (connection)) ) {
+
+ surface.make_current();
+ scene.draw(framenum++);
+ surface.swap_buffers();
+ }
+
+ xcb_disconnect (connection);
+}
diff --git a/kmscube/cube.cpp b/kmscube/cube.cpp
new file mode 100644
index 0000000..14c340a
--- /dev/null
+++ b/kmscube/cube.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Arvin Schnell <arvin.schnell@gmail.com>
+ * Copyright (c) 2012 Rob Clark <rob@ti.com>
+ * Copyright (c) 2015 Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * 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, sub license,
+ * 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 (including the
+ * next paragraph) 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 NON-INFRINGEMENT. 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.
+ */
+
+/* Based on a egl cube test app originally written by Arvin Schnell */
+
+#include "cube.h"
+#include "opts.h"
+#include "test.h"
+
+using namespace std;
+
+bool s_verbose;
+
+int main(int argc, char *argv[])
+{
+ OptionSet optionset = {
+ Option("v|verbose",
+ [&]()
+ {
+ s_verbose = true;
+ }),
+ };
+
+ optionset.parse(argc, argv);
+
+ string m;
+
+ if (optionset.params().size() == 0)
+ m = "gbm";
+ else
+ m = optionset.params().front();
+
+ if (m == "gbm")
+ main_gbm();
+ else if (m == "null")
+ main_null();
+ else if (m == "x")
+ main_x11();
+ else if (m == "wl")
+ main_wl();
+ else {
+ printf("Unknown mode %s\n", m.c_str());
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/kmscube/cube.h b/kmscube/cube.h
index 9616c74..8245f0b 100644
--- a/kmscube/cube.h
+++ b/kmscube/cube.h
@@ -1,98 +1,9 @@
-static const GLfloat vVertices[] = {
- // front
- -1.0f, -1.0f, +1.0f, // point blue
- +1.0f, -1.0f, +1.0f, // point magenta
- -1.0f, +1.0f, +1.0f, // point cyan
- +1.0f, +1.0f, +1.0f, // point white
- // back
- +1.0f, -1.0f, -1.0f, // point red
- -1.0f, -1.0f, -1.0f, // point black
- +1.0f, +1.0f, -1.0f, // point yellow
- -1.0f, +1.0f, -1.0f, // point green
- // right
- +1.0f, -1.0f, +1.0f, // point magenta
- +1.0f, -1.0f, -1.0f, // point red
- +1.0f, +1.0f, +1.0f, // point white
- +1.0f, +1.0f, -1.0f, // point yellow
- // left
- -1.0f, -1.0f, -1.0f, // point black
- -1.0f, -1.0f, +1.0f, // point blue
- -1.0f, +1.0f, -1.0f, // point green
- -1.0f, +1.0f, +1.0f, // point cyan
- // top
- -1.0f, +1.0f, +1.0f, // point cyan
- +1.0f, +1.0f, +1.0f, // point white
- -1.0f, +1.0f, -1.0f, // point green
- +1.0f, +1.0f, -1.0f, // point yellow
- // bottom
- -1.0f, -1.0f, -1.0f, // point black
- +1.0f, -1.0f, -1.0f, // point red
- -1.0f, -1.0f, +1.0f, // point blue
- +1.0f, -1.0f, +1.0f // point magenta
-};
+#pragma once
-static const GLfloat vColors[] = {
- // front
- 0.0f, 0.0f, 1.0f, // blue
- 1.0f, 0.0f, 1.0f, // magenta
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 1.0f, 1.0f, // white
- // back
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 0.0f, 0.0f, // black
- 1.0f, 1.0f, 0.0f, // yellow
- 0.0f, 1.0f, 0.0f, // green
- // right
- 1.0f, 0.0f, 1.0f, // magenta
- 1.0f, 0.0f, 0.0f, // red
- 1.0f, 1.0f, 1.0f, // white
- 1.0f, 1.0f, 0.0f, // yellow
- // left
- 0.0f, 0.0f, 0.0f, // black
- 0.0f, 0.0f, 1.0f, // blue
- 0.0f, 1.0f, 0.0f, // green
- 0.0f, 1.0f, 1.0f, // cyan
- // top
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 1.0f, 1.0f, // white
- 0.0f, 1.0f, 0.0f, // green
- 1.0f, 1.0f, 0.0f, // yellow
- // bottom
- 0.0f, 0.0f, 0.0f, // black
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 0.0f, 1.0f, // blue
- 1.0f, 0.0f, 1.0f // magenta
-};
+extern bool s_verbose;
+
+void main_null();
+void main_gbm();
+void main_x11();
+void main_wl();
-static const GLfloat vNormals[] = {
- // front
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- +0.0f, +0.0f, +1.0f, // forward
- // back
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- +0.0f, +0.0f, -1.0f, // backbard
- // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- +1.0f, +0.0f, +0.0f, // right
- // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- -1.0f, +0.0f, +0.0f, // left
- // top
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- +0.0f, +1.0f, +0.0f, // up
- // bottom
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f, // down
- +0.0f, -1.0f, +0.0f // down
-};
diff --git a/kmscube/esTransform.c b/kmscube/esTransform.c
index e3e30e4..899c038 100644
--- a/kmscube/esTransform.c
+++ b/kmscube/esTransform.c
@@ -40,7 +40,7 @@
///
// Includes
//
-#include "esUtil.h"
+#include "esTransform.h"
#include <math.h>
#include <string.h>
diff --git a/kmscube/esUtil.h b/kmscube/esTransform.h
index c0383ab..c0383ab 100644
--- a/kmscube/esUtil.h
+++ b/kmscube/esTransform.h
diff --git a/kmscube/kmscube.cpp b/kmscube/kmscube.cpp
deleted file mode 100644
index e9145c9..0000000
--- a/kmscube/kmscube.cpp
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Copyright (c) 2012 Arvin Schnell <arvin.schnell@gmail.com>
- * Copyright (c) 2012 Rob Clark <rob@ti.com>
- * Copyright (c) 2015 Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * 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, sub license,
- * 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT. 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.
- */
-
-/* Based on a egl cube test app originally written by Arvin Schnell */
-
-#include <chrono>
-#include <cstdio>
-#include <vector>
-#include <memory>
-#include <algorithm>
-#include <poll.h>
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-#include <gbm.h>
-#include <X11/Xlib-xcb.h>
-
-#include "esUtil.h"
-
-#include <kms++.h>
-#include "test.h"
-#include "opts.h"
-
-using namespace kms;
-using namespace std;
-
-static bool s_verbose;
-static int s_flip_pending;
-static bool s_need_exit;
-
-static bool s_support_planes;
-
-class GbmDevice
-{
-public:
- GbmDevice(Card& card)
- {
- m_dev = gbm_create_device(card.fd());
- FAIL_IF(!m_dev, "failed to create gbm device");
- }
-
- ~GbmDevice()
- {
- gbm_device_destroy(m_dev);
- }
-
- GbmDevice(const GbmDevice& other) = delete;
- GbmDevice& operator=(const GbmDevice& other) = delete;
-
- struct gbm_device* handle() const { return m_dev; }
-
-private:
- struct gbm_device* m_dev;
-};
-
-class GbmSurface
-{
-public:
- GbmSurface(GbmDevice& gdev, int width, int height)
- {
- m_surface = gbm_surface_create(gdev.handle(), width, height,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
- FAIL_IF(!m_surface, "failed to create gbm surface");
- }
-
- ~GbmSurface()
- {
- gbm_surface_destroy(m_surface);
- }
-
- GbmSurface(const GbmSurface& other) = delete;
- GbmSurface& operator=(const GbmSurface& other) = delete;
-
- bool has_free()
- {
- return gbm_surface_has_free_buffers(m_surface);
- }
-
- gbm_bo* lock_front_buffer()
- {
- return gbm_surface_lock_front_buffer(m_surface);
- }
-
- void release_buffer(gbm_bo *bo)
- {
- gbm_surface_release_buffer(m_surface, bo);
- }
-
- struct gbm_surface* handle() const { return m_surface; }
-
-private:
- struct gbm_surface* m_surface;
-};
-
-class EglState
-{
-public:
- EglState(EGLNativeDisplayType display_id)
- {
- EGLBoolean b;
- EGLint major, minor, n;
-
- static const EGLint context_attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- static const EGLint config_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 0,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
- };
-
- m_display = eglGetDisplay(display_id);
- FAIL_IF(!m_display, "failed to get egl display");
-
- b = eglInitialize(m_display, &major, &minor);
- FAIL_IF(!b, "failed to initialize");
-
- if (s_verbose) {
- printf("Using display %p with EGL version %d.%d\n", m_display, major, minor);
-
- printf("EGL_VENDOR: %s\n", eglQueryString(m_display, EGL_VENDOR));
- printf("EGL_VERSION: %s\n", eglQueryString(m_display, EGL_VERSION));
- printf("EGL_EXTENSIONS: %s\n", eglQueryString(m_display, EGL_EXTENSIONS));
- printf("EGL_CLIENT_APIS: %s\n", eglQueryString(m_display, EGL_CLIENT_APIS));
- }
-
- b = eglBindAPI(EGL_OPENGL_ES_API);
- FAIL_IF(!b, "failed to bind api EGL_OPENGL_ES_API");
-
- b = eglChooseConfig(m_display, config_attribs, &m_config, 1, &n);
- FAIL_IF(!b || n != 1, "failed to choose config");
-
- auto getconf = [this](EGLint a) { EGLint v = -1; eglGetConfigAttrib(m_display, m_config, a, &v); return v; };
-
- if (s_verbose) {
- printf("EGL Config %d: color buf %d/%d/%d/%d = %d, depth %d, stencil %d\n",
- getconf(EGL_CONFIG_ID),
- getconf(EGL_ALPHA_SIZE),
- getconf(EGL_RED_SIZE),
- getconf(EGL_GREEN_SIZE),
- getconf(EGL_BLUE_SIZE),
- getconf(EGL_BUFFER_SIZE),
- getconf(EGL_DEPTH_SIZE),
- getconf(EGL_STENCIL_SIZE));
- }
-
- m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, context_attribs);
- FAIL_IF(!m_context, "failed to create context");
-
- eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, m_context);
- }
-
- ~EglState()
- {
- eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(m_display);
- }
-
- EGLDisplay display() const { return m_display; }
- EGLConfig config() const { return m_config; }
- EGLContext context() const { return m_context; }
-
-private:
- EGLDisplay m_display;
- EGLConfig m_config;
- EGLContext m_context;
-};
-
-class GlScene
-{
-public:
- GlScene()
- {
- GLuint vertex_shader, fragment_shader;
- GLint ret;
-
-#include "cube.h"
-
- static const char *vertex_shader_source =
- "uniform mat4 modelviewMatrix; \n"
- "uniform mat4 modelviewprojectionMatrix;\n"
- "uniform mat3 normalMatrix; \n"
- " \n"
- "attribute vec4 in_position; \n"
- "attribute vec3 in_normal; \n"
- "attribute vec4 in_color; \n"
- "\n"
- "vec4 lightSource = vec4(2.0, 2.0, 20.0, 0.0);\n"
- " \n"
- "varying vec4 vVaryingColor; \n"
- " \n"
- "void main() \n"
- "{ \n"
- " gl_Position = modelviewprojectionMatrix * in_position;\n"
- " vec3 vEyeNormal = normalMatrix * in_normal;\n"
- " vec4 vPosition4 = modelviewMatrix * in_position;\n"
- " vec3 vPosition3 = vPosition4.xyz / vPosition4.w;\n"
- " vec3 vLightDir = normalize(lightSource.xyz - vPosition3);\n"
- " float diff = max(0.0, dot(vEyeNormal, vLightDir));\n"
- " vVaryingColor = vec4(diff * in_color.rgb, 1.0);\n"
- "} \n";
-
- static const char *fragment_shader_source =
- "precision mediump float; \n"
- " \n"
- "varying vec4 vVaryingColor; \n"
- " \n"
- "void main() \n"
- "{ \n"
- " gl_FragColor = vVaryingColor; \n"
- "} \n";
-
-
- if (s_verbose) {
- printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
- printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
- printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
- printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
- }
-
- vertex_shader = glCreateShader(GL_VERTEX_SHADER);
-
- glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
- glCompileShader(vertex_shader);
-
- glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &ret);
- FAIL_IF(!ret, "vertex shader compilation failed!");
-
- fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
- glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
- glCompileShader(fragment_shader);
-
- glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &ret);
- FAIL_IF(!ret, "fragment shader compilation failed!");
-
- GLuint program = glCreateProgram();
-
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
-
- glBindAttribLocation(program, 0, "in_position");
- glBindAttribLocation(program, 1, "in_normal");
- glBindAttribLocation(program, 2, "in_color");
-
- glLinkProgram(program);
-
- glGetProgramiv(program, GL_LINK_STATUS, &ret);
- FAIL_IF(!ret, "program linking failed!");
-
- glUseProgram(program);
-
- m_modelviewmatrix = glGetUniformLocation(program, "modelviewMatrix");
- m_modelviewprojectionmatrix = glGetUniformLocation(program, "modelviewprojectionMatrix");
- m_normalmatrix = glGetUniformLocation(program, "normalMatrix");
-
- glEnable(GL_CULL_FACE);
-
- GLintptr positionsoffset = 0;
- GLintptr colorsoffset = sizeof(vVertices);
- GLintptr normalsoffset = sizeof(vVertices) + sizeof(vColors);
- GLuint vbo;
-
- glGenBuffers(1, &vbo);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices) + sizeof(vColors) + sizeof(vNormals), 0, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, positionsoffset, sizeof(vVertices), &vVertices[0]);
- glBufferSubData(GL_ARRAY_BUFFER, colorsoffset, sizeof(vColors), &vColors[0]);
- glBufferSubData(GL_ARRAY_BUFFER, normalsoffset, sizeof(vNormals), &vNormals[0]);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)positionsoffset);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)normalsoffset);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)colorsoffset);
- glEnableVertexAttribArray(2);
- }
-
- GlScene(const GlScene& other) = delete;
- GlScene& operator=(const GlScene& other) = delete;
-
- void set_viewport(uint32_t width, uint32_t height)
- {
- m_width = width;
- m_height = height;
- }
-
- void draw(uint32_t framenum)
- {
- glViewport(0, 0, m_width, m_height);
-
- glClearColor(0.5, 0.5, 0.5, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- ESMatrix modelview;
-
- esMatrixLoadIdentity(&modelview);
- esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
- esRotate(&modelview, 45.0f + (0.75f * framenum), 1.0f, 0.0f, 0.0f);
- esRotate(&modelview, 45.0f - (0.5f * framenum), 0.0f, 1.0f, 0.0f);
- esRotate(&modelview, 10.0f + (0.45f * framenum), 0.0f, 0.0f, 1.0f);
-
- GLfloat aspect = (float)m_height / m_width;
-
- ESMatrix projection;
- esMatrixLoadIdentity(&projection);
- esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f);
-
- ESMatrix modelviewprojection;
- esMatrixLoadIdentity(&modelviewprojection);
- esMatrixMultiply(&modelviewprojection, &modelview, &projection);
-
- float normal[9];
- normal[0] = modelview.m[0][0];
- normal[1] = modelview.m[0][1];
- normal[2] = modelview.m[0][2];
- normal[3] = modelview.m[1][0];
- normal[4] = modelview.m[1][1];
- normal[5] = modelview.m[1][2];
- normal[6] = modelview.m[2][0];
- normal[7] = modelview.m[2][1];
- normal[8] = modelview.m[2][2];
-
- glUniformMatrix4fv(m_modelviewmatrix, 1, GL_FALSE, &modelview.m[0][0]);
- glUniformMatrix4fv(m_modelviewprojectionmatrix, 1, GL_FALSE, &modelviewprojection.m[0][0]);
- glUniformMatrix3fv(m_normalmatrix, 1, GL_FALSE, normal);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
- glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
- }
-
-private:
- GLint m_modelviewmatrix, m_modelviewprojectionmatrix, m_normalmatrix;
-
- uint32_t m_width;
- uint32_t m_height;
-};
-
-class GbmEglSurface
-{
-public:
- GbmEglSurface(Card& card, GbmDevice& gdev, const EglState& egl, int width, int height)
- : card(card), gdev(gdev), egl(egl), m_width(width), m_height(height),
- bo_prev(0), bo_next(0)
- {
- gsurface = unique_ptr<GbmSurface>(new GbmSurface(gdev, width, height));
- esurface = eglCreateWindowSurface(egl.display(), egl.config(), gsurface->handle(), NULL);
- FAIL_IF(esurface == EGL_NO_SURFACE, "failed to create egl surface");
- }
-
- ~GbmEglSurface()
- {
- if (bo_next)
- gsurface->release_buffer(bo_next);
- eglDestroySurface(egl.display(), esurface);
- }
-
- void make_current()
- {
- FAIL_IF(!gsurface->has_free(), "No free buffers");
-
- eglMakeCurrent(egl.display(), esurface, esurface, egl.context());
- }
-
- void swap_buffers()
- {
- eglSwapBuffers(egl.display(), esurface);
- }
-
- static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
- {
- auto fb = reinterpret_cast<Framebuffer*>(data);
- delete fb;
- }
-
- static Framebuffer* drm_fb_get_from_bo(struct gbm_bo *bo, Card& card)
- {
- auto fb = reinterpret_cast<Framebuffer*>(gbm_bo_get_user_data(bo));
- if (fb)
- return fb;
-
- uint32_t width = gbm_bo_get_width(bo);
- uint32_t height = gbm_bo_get_height(bo);
- uint32_t stride = gbm_bo_get_stride(bo);
- uint32_t handle = gbm_bo_get_handle(bo).u32;
-
- fb = new ExtFramebuffer(card, width, height, 24, 32, stride, handle);
-
- gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
-
- return fb;
- }
-
- struct Framebuffer* lock_next()
- {
- bo_prev = bo_next;
- bo_next = gsurface->lock_front_buffer();
- FAIL_IF(!bo_next, "could not lock gbm buffer");
- return drm_fb_get_from_bo(bo_next, card);
- }
-
- void free_prev()
- {
- if (bo_prev) {
- gsurface->release_buffer(bo_prev);
- bo_prev = 0;
- }
- }
-
- uint32_t width() const { return m_width; }
- uint32_t height() const { return m_height; }
-
-private:
- Card& card;
- GbmDevice& gdev;
- const EglState& egl;
-
- unique_ptr<GbmSurface> gsurface;
- EGLSurface esurface;
-
- int m_width;
- int m_height;
-
- struct gbm_bo* bo_prev;
- struct gbm_bo* bo_next;
-};
-
-class EglSurface
-{
-public:
- EglSurface(const EglState& egl, EGLNativeWindowType wnd)
- : egl(egl)
- {
- esurface = eglCreateWindowSurface(egl.display(), egl.config(), wnd, NULL);
- FAIL_IF(esurface == EGL_NO_SURFACE, "failed to create egl surface");
- }
-
- ~EglSurface()
- {
- eglDestroySurface(egl.display(), esurface);
- }
-
- void make_current()
- {
- eglMakeCurrent(egl.display(), esurface, esurface, egl.context());
- }
-
- void swap_buffers()
- {
- eglSwapBuffers(egl.display(), esurface);
- }
-
-private:
- const EglState& egl;
-
- EGLSurface esurface;
-};
-
-class OutputHandler : private PageFlipHandlerBase
-{
-public:
- OutputHandler(Card& card, GbmDevice& gdev, const EglState& egl, Connector* connector, Crtc* crtc, Videomode& mode, Plane* plane, float rotation_mult)
- : m_frame_num(0), m_connector(connector), m_crtc(crtc), m_plane(plane), m_mode(mode),
- m_rotation_mult(rotation_mult)
- {
- m_surface1 = unique_ptr<GbmEglSurface>(new GbmEglSurface(card, gdev, egl, mode.hdisplay, mode.vdisplay));
- m_scene1 = unique_ptr<GlScene>(new GlScene());
- m_scene1->set_viewport(m_surface1->width(), m_surface1->height());
-
- if (m_plane) {
- m_surface2 = unique_ptr<GbmEglSurface>(new GbmEglSurface(card, gdev, egl, 400, 400));
- m_scene2 = unique_ptr<GlScene>(new GlScene());
- m_scene2->set_viewport(m_surface2->width(), m_surface2->height());
- }
- }
-
- OutputHandler(const OutputHandler& other) = delete;
- OutputHandler& operator=(const OutputHandler& other) = delete;
-
- void setup()
- {
- int ret;
-
- m_surface1->make_current();
- m_surface1->swap_buffers();
- struct Framebuffer* fb = m_surface1->lock_next();
-
- struct Framebuffer* planefb = 0;
-
- if (m_plane) {
- m_surface2->make_current();
- m_surface2->swap_buffers();
- planefb = m_surface2->lock_next();
- }
-
-
- ret = m_crtc->set_mode(m_connector, *fb, m_mode);
- FAIL_IF(ret, "failed to set mode");
-
- if (m_crtc->card().has_atomic()) {
- Plane* root_plane = 0;
- for (Plane* p : m_crtc->get_possible_planes()) {
- if (p->crtc_id() == m_crtc->id()) {
- root_plane = p;
- break;
- }
- }
-
- FAIL_IF(!root_plane, "No primary plane for crtc %d", m_crtc->id());
-
- m_root_plane = root_plane;
- }
-
- if (m_plane) {
- ret = m_crtc->set_plane(m_plane, *planefb,
- 0, 0, planefb->width(), planefb->height(),
- 0, 0, planefb->width(), planefb->height());
- FAIL_IF(ret, "failed to set plane");
- }
- }
-
- void start_flipping()
- {
- m_t1 = chrono::steady_clock::now();
- queue_next();
- }
-
-private:
- void handle_page_flip(uint32_t frame, double time)
- {
- ++m_frame_num;
-
- if (m_frame_num % 100 == 0) {
- auto t2 = chrono::steady_clock::now();
- chrono::duration<float> fsec = t2 - m_t1;
- printf("fps: %f\n", 100.0 / fsec.count());
- m_t1 = t2;
- }
-
- s_flip_pending--;
-
- m_surface1->free_prev();
- if (m_plane)
- m_surface2->free_prev();
-
- if (s_need_exit)
- return;
-
- queue_next();
- }
-
- void queue_next()
- {
- m_surface1->make_current();
- m_scene1->draw(m_frame_num * m_rotation_mult);
- m_surface1->swap_buffers();
- struct Framebuffer* fb = m_surface1->lock_next();
-
- struct Framebuffer* planefb = 0;
-
- if (m_plane) {
- m_surface2->make_current();
- m_scene2->draw(m_frame_num * m_rotation_mult * 2);
- m_surface2->swap_buffers();
- planefb = m_surface2->lock_next();
- }
-
- if (m_crtc->card().has_atomic()) {
- int r;
-
- AtomicReq req(m_crtc->card());
-
- req.add(m_root_plane, "FB_ID", fb->id());
- if (m_plane)
- req.add(m_plane, "FB_ID", planefb->id());
-
- r = req.test();
- FAIL_IF(r, "atomic test failed");
-
- r = req.commit(this);
- FAIL_IF(r, "atomic commit failed");
- } else {
- int ret;
-
- ret = m_crtc->page_flip(*fb, this);
- FAIL_IF(ret, "failed to queue page flip");
-
- if (m_plane) {
- ret = m_crtc->set_plane(m_plane, *planefb,
- 0, 0, planefb->width(), planefb->height(),
- 0, 0, planefb->width(), planefb->height());
- FAIL_IF(ret, "failed to set plane");
- }
- }
-
- s_flip_pending++;
- }
-
- int m_frame_num;
- chrono::steady_clock::time_point m_t1;
-
- Connector* m_connector;
- Crtc* m_crtc;
- Plane* m_plane;
- Videomode m_mode;
- Plane* m_root_plane;
-
- unique_ptr<GbmEglSurface> m_surface1;
- unique_ptr<GbmEglSurface> m_surface2;
-
- unique_ptr<GlScene> m_scene1;
- unique_ptr<GlScene> m_scene2;
-
- float m_rotation_mult;
-};
-
-static void main_gbm()
-{
- Card card;
-
- GbmDevice gdev(card);
- EglState egl(gdev.handle());
-
- vector<unique_ptr<OutputHandler>> outputs;
- vector<Plane*> used_planes;
-
- float rot_mult = 1;
-
- for (auto pipe : card.get_connected_pipelines()) {
- auto connector = pipe.connector;
- auto crtc = pipe.crtc;
- auto mode = connector->get_default_mode();
-
- Plane* plane = 0;
-
- if (s_support_planes) {
- for (Plane* p : crtc->get_possible_planes()) {
- if (find(used_planes.begin(), used_planes.end(), p) != used_planes.end())
- continue;
-
- if (p->plane_type() != PlaneType::Overlay)
- continue;
-
- plane = p;
- break;
- }
- }
-
- if (plane)
- used_planes.push_back(plane);
-
- auto out = new OutputHandler(card, gdev, egl, connector, crtc, mode, plane, rot_mult);
- outputs.emplace_back(out);
-
- rot_mult *= 1.33;
- }
-
- for (auto& out : outputs)
- out->setup();
-
- for (auto& out : outputs)
- out->start_flipping();
-
- struct pollfd fds[2] = { 0 };
- fds[0].fd = 0;
- fds[0].events = POLLIN;
- fds[1].fd = card.fd();
- fds[1].events = POLLIN;
-
- while (!s_need_exit || s_flip_pending) {
- int r = poll(fds, ARRAY_SIZE(fds), -1);
- FAIL_IF(r < 0, "poll error %d", r);
-
- if (fds[0].revents)
- s_need_exit = true;
-
- if (fds[1].revents)
- card.call_page_flip_handlers();
- }
-}
-
-static void main_x()
-{
- Display* display = XOpenDisplay(NULL);
-
- xcb_connection_t *connection = XGetXCBConnection(display);
-
- /* Get the first screen */
- const xcb_setup_t *setup = xcb_get_setup (connection);
- xcb_screen_t *screen = xcb_setup_roots_iterator (setup).data;
-
- /* Create the window */
-
- uint32_t width = 600;
- uint32_t height = 600;
-
- const uint32_t xcb_window_attrib_mask = XCB_CW_EVENT_MASK;
- const uint32_t xcb_window_attrib_list[] = {
- XCB_EVENT_MASK_EXPOSURE,
- };
-
- xcb_window_t window = xcb_generate_id (connection);
- xcb_create_window (connection, /* Connection */
- XCB_COPY_FROM_PARENT, /* depth (same as root)*/
- window, /* window Id */
- screen->root, /* parent window */
- 0, 0, /* x, y */
- width, height, /* width, height */
- 0, /* border_width */
- XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
- screen->root_visual, /* visual */
- xcb_window_attrib_mask,
- xcb_window_attrib_list);
-
- xcb_map_window (connection, window);
- xcb_flush (connection);
-
- EglState egl(reinterpret_cast<EGLNativeDisplayType>(display));
- EglSurface surface(egl, reinterpret_cast<EGLNativeWindowType>(window));
- GlScene scene;
-
- scene.set_viewport(width, height);
-
- int framenum = 0;
-
- surface.make_current();
- surface.swap_buffers();
-
- xcb_generic_event_t *event;
- while ( (event = xcb_poll_for_event (connection)) ) {
-
- surface.make_current();
- scene.draw(framenum++);
- surface.swap_buffers();
- }
-
- xcb_disconnect (connection);
-}
-
-static void main_null()
-{
- EglState egl(EGL_DEFAULT_DISPLAY);
- EglSurface surface(egl, 0);
- GlScene scene;
-
- scene.set_viewport(600, 600);
-
- int framenum = 0;
-
- struct pollfd fds[1] = { 0 };
- fds[0].fd = 0;
- fds[0].events = POLLIN;
-
- while (true) {
- int r = poll(fds, ARRAY_SIZE(fds), 0);
- ASSERT(r >= 0);
-
- if (fds[0].revents)
- break;
-
- surface.make_current();
- scene.draw(framenum++);
- surface.swap_buffers();
- }
-}
-
-int main(int argc, char *argv[])
-{
- OptionSet optionset = {
- Option("v|verbose",
- [&]()
- {
- s_verbose = true;
- }),
- };
-
- optionset.parse(argc, argv);
-
- string m;
-
- if (optionset.params().size() == 0)
- m = "gbm";
- else
- m = optionset.params().front();
-
- if (m == "gbm")
- main_gbm();
- else if (m == "null")
- main_null();
- else if (m == "x")
- main_x();
- else {
- printf("Unknown mode %s\n", m.c_str());
- return -1;
- }
-
- return 0;
-}