=== modified file 'android/jni/Android.mk'
@@ -65,7 +65,7 @@
$(LOCAL_PATH)/src/libjpeg-turbo \
$(LOCAL_PATH)/src/libpng \
external/zlib
-LOCAL_SRC_FILES := $(filter-out src/canvas% src/main.cpp, \
+LOCAL_SRC_FILES := $(filter-out src/canvas% src/gl-state% src/native-state% src/main.cpp, \
$(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/*.cpp))) \
$(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/scene-terrain/*.cpp)) \
src/canvas-android.cpp
=== modified file 'android/jni/Android.ndk.mk'
@@ -57,7 +57,7 @@
$(LOCAL_PATH)/src/scene-terrain \
$(LOCAL_PATH)/src/libjpeg-turbo \
$(LOCAL_PATH)/src/libpng
-LOCAL_SRC_FILES := $(filter-out src/canvas% src/main.cpp, \
+LOCAL_SRC_FILES := $(filter-out src/canvas% src/gl-state% src/native-state% src/main.cpp, \
$(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/*.cpp))) \
$(subst $(LOCAL_PATH)/,,$(wildcard $(LOCAL_PATH)/src/scene-terrain/*.cpp)) \
src/canvas-android.cpp
=== removed file 'src/canvas-drm.cpp'
@@ -1,587 +0,0 @@
-//
-// Copyright Š 2012 Linaro Limited
-//
-// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
-//
-// glmark2 is free software: you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the Free Software
-// Foundation, either version 3 of the License, or (at your option) any later
-// version.
-//
-// glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// glmark2. If not, see <http://www.gnu.org/licenses/>.
-//
-// Authors:
-// Simon Que
-// Jesse Barker
-//
-#include "canvas-drm.h"
-#include "log.h"
-#include "options.h"
-#include "util.h"
-
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-
-#include <fstream>
-#include <sstream>
-#include <list>
-
-/******************
- * Public methods *
- ******************/
-
-bool
-CanvasDRM::reset()
-{
- if (!reset_context())
- return false;
-
- if (!make_current())
- return false;
-
- if (!supports_gl2()) {
- Log::error("Glmark2 needs OpenGL(ES) version >= 2.0 to run"
- " (but version string is: '%s')!\n",
- glGetString(GL_VERSION));
- return false;
- }
-
- glViewport(0, 0, width_, height_);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-
- clear();
- egl_.swap();
-
- if (!drm_.reset()) {
- return false;
- }
-
- return true;
-}
-
-void
-DRMState::fb_destroy_callback(gbm_bo* bo, void* data)
-{
- DRMFBState* fb = reinterpret_cast<DRMFBState*>(data);
- if (fb && fb->fb_id) {
- drmModeRmFB(fb->fd, fb->fb_id);
- }
- delete fb;
- gbm_device* dev = gbm_bo_get_device(bo);
- Log::debug("Got GBM device handle %p from buffer object\n", dev);
-}
-
-DRMFBState*
-DRMState::fb_get_from_bo(gbm_bo* bo)
-{
- DRMFBState* fb = reinterpret_cast<DRMFBState*>(gbm_bo_get_user_data(bo));
- if (fb) {
- return fb;
- }
-
- unsigned int width = gbm_bo_get_width(bo);
- unsigned int height = gbm_bo_get_height(bo);
- unsigned int stride = gbm_bo_get_stride(bo);
- unsigned int handle = gbm_bo_get_handle(bo).u32;
- unsigned int fb_id(0);
- int status = drmModeAddFB(fd_, width, height, 24, 32, stride, handle, &fb_id);
- if (status < 0) {
- Log::error("Failed to create FB: %d\n", status);
- return 0;
- }
-
- fb = new DRMFBState();
- fb->fd = fd_;
- fb->bo = bo;
- fb->fb_id = fb_id;
-
- gbm_bo_set_user_data(bo, fb, fb_destroy_callback);
- return fb;
-}
-
-bool
-DRMState::init_gbm()
-{
- dev_ = gbm_create_device(fd_);
- if (!dev_) {
- Log::error("Failed to create GBM device\n");
- return false;
- }
-
- surface_ = gbm_surface_create(dev_, mode_->hdisplay, mode_->vdisplay,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
- if (!surface_) {
- Log::error("Failed to create GBM surface\n");
- return false;
- }
-
- return true;
-}
-
-bool
-DRMState::init()
-{
- // TODO: Replace this with something that explicitly probes for the loaded
- // driver (udev?).
- static const char* drm_modules[] = {
- "i915",
- "nouveau",
- "radeon",
- "vmgfx",
- "omapdrm",
- "exynos"
- };
-
- unsigned int num_modules(sizeof(drm_modules)/sizeof(drm_modules[0]));
- for (unsigned int m = 0; m < num_modules; m++) {
- fd_ = drmOpen(drm_modules[m], 0);
- if (fd_ < 0) {
- Log::debug("Failed to open DRM module '%s'\n", drm_modules[m]);
- continue;
- }
- Log::debug("Opened DRM module '%s'\n", drm_modules[m]);
- break;
- }
-
- if (fd_ < 0) {
- Log::error("Failed to find a suitable DRM device\n");
- return false;
- }
-
- resources_ = drmModeGetResources(fd_);
- if (!resources_) {
- Log::error("drmModeGetResources failed\n");
- return false;
- }
-
- // Find a connected connector
- for (int c = 0; c < resources_->count_connectors; c++) {
- connector_ = drmModeGetConnector(fd_, resources_->connectors[c]);
- if (DRM_MODE_CONNECTED == connector_->connection) {
- break;
- }
- drmModeFreeConnector(connector_);
- connector_ = 0;
- }
-
- if (!connector_) {
- Log::error("Failed to find a suitable connector\n");
- return false;
- }
-
- // Find the best resolution (we will always operate full-screen).
- unsigned int bestArea(0);
- for (int m = 0; m < connector_->count_modes; m++) {
- drmModeModeInfo* curMode = &connector_->modes[m];
- unsigned int curArea = curMode->hdisplay * curMode->vdisplay;
- if (curArea > bestArea) {
- mode_ = curMode;
- bestArea = curArea;
- }
- }
-
- if (!mode_) {
- Log::error("Failed to find a suitable mode\n");
- return false;
- }
-
- // Find a suitable encoder
- for (int e = 0; e < resources_->count_encoders; e++) {
- encoder_ = drmModeGetEncoder(fd_, resources_->encoders[e]);
- if (encoder_ && encoder_->encoder_id == connector_->encoder_id) {
- break;
- }
- drmModeFreeEncoder(encoder_);
- encoder_ = 0;
- }
-
- if (!encoder_) {
- Log::error("Failed to find a suitable encoder\n");
- return false;
- }
-
- if (!init_gbm()) {
- return false;
- }
-
- crtc_ = drmModeGetCrtc(fd_, encoder_->crtc_id);
- if (!crtc_) {
- Log::error("Failed to get current CRTC\n");
- return false;
- }
-
- signal(SIGINT, &DRMState::quit_handler);
-
- return true;
-}
-
-bool
-DRMState::reset()
-{
- if (bo_) {
- gbm_surface_release_buffer(surface_, bo_);
- }
-
- bo_ = gbm_surface_lock_front_buffer(surface_);
- fb_ = fb_get_from_bo(bo_);
-
- int status = drmModeSetCrtc(fd_, encoder_->crtc_id, fb_->fb_id, 0, 0,
- &connector_->connector_id, 1, mode_);
- if (status < 0) {
- Log::error("Failed to set CRTC: %d\n", status);
- return false;
- }
-
- return true;
-}
-
-
-bool DRMState::should_quit_ = false;
-
-void
-DRMState::quit_handler(int signo)
-{
- Log::debug("Got SIGINT (%d).\n", signo);
- should_quit_ = true;
-}
-void
-DRMState::page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void* data)
-{
- unsigned int* waiting = reinterpret_cast<unsigned int*>(data);
- *waiting = 0;
- // Deal with unused parameters
- static_cast<void>(fd);
- static_cast<void>(frame);
- static_cast<void>(sec);
- static_cast<void>(usec);
-}
-
-void
-DRMState::do_flip()
-{
- gbm_bo* next = gbm_surface_lock_front_buffer(surface_);
- fb_ = fb_get_from_bo(next);
- unsigned int waiting(1);
- int status = drmModePageFlip(fd_, encoder_->crtc_id, fb_->fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, &waiting);
- if (status < 0) {
- Log::error("Failed to enqueue page flip: %d\n", status);
- return;
- }
-
- fd_set fds;
- FD_ZERO(&fds);
- FD_SET(fd_, &fds);
- drmEventContext evCtx;
- evCtx.version = DRM_EVENT_CONTEXT_VERSION;
- evCtx.page_flip_handler = page_flip_handler;
-
- while (waiting) {
- status = select(fd_ + 1, &fds, 0, 0, 0);
- if (status < 0) {
- // Most of the time, select() will return an error because the
- // user pressed Ctrl-C. So, only print out a message in debug
- // mode, and just check for the likely condition and release
- // the current buffer object before getting out.
- Log::debug("Error in select\n");
- if (should_quit()) {
- gbm_surface_release_buffer(surface_, bo_);
- bo_ = next;
- }
- return;
- }
- drmHandleEvent(fd_, &evCtx);
- }
-
- gbm_surface_release_buffer(surface_, bo_);
- bo_ = next;
-}
-
-void
-DRMState::cleanup()
-{
- // Restore CRTC state if necessary
- if (crtc_) {
- int status = drmModeSetCrtc(fd_, crtc_->crtc_id, crtc_->buffer_id,
- crtc_->x, crtc_->y, &connector_->connector_id,
- 1, &crtc_->mode);
- if (status < 0) {
- Log::error("Failed to restore original CRTC: %d\n", status);
- }
- drmModeFreeCrtc(crtc_);
- crtc_ = 0;
- }
- if (surface_) {
- gbm_surface_destroy(surface_);
- surface_ = 0;
- }
- if (dev_) {
- gbm_device_destroy(dev_);
- dev_ = 0;
- }
- if (connector_) {
- drmModeFreeConnector(connector_);
- connector_ = 0;
- }
- if (encoder_) {
- drmModeFreeEncoder(encoder_);
- encoder_ = 0;
- }
- if (resources_) {
- drmModeFreeResources(resources_);
- resources_ = 0;
- }
- if (fd_ > 0) {
- drmClose(fd_);
- }
- fd_ = 0;
- mode_ = 0;
-}
-
-bool
-CanvasDRM::init()
-{
- Log::info("NOTE: The DRM canvas is still experimental and its behavior\n");
- Log::info(" is subject to change as GBM and modesetting behavior\n");
- Log::info(" evolves\n");
-
- if (!drm_.init()) {
- Log::error("Failed to initialize the DRM canvas\n");
- drm_.cleanup();
- return false;
- }
-
- width_ = drm_.mode_width();
- height_ = drm_.mode_height();
- resize_no_viewport(width_, height_);
-
- if (!egl_.init_display(drm_.device(), visual_config_)) {
- return false;
- }
- if (!egl_.init_surface(drm_.surface())) {
- return false;
- }
- if (!egl_.valid()) {
- return false;
- }
-
- return reset();
-}
-
-
-CanvasDRM::~CanvasDRM()
-{
- drm_.cleanup();
-}
-
-void
-CanvasDRM::visible(bool /* visible */)
-{
-}
-
-void
-CanvasDRM::clear()
-{
- glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
-#if USE_GL
- glClearDepth(1.0f);
-#elif USE_GLESv2
- glClearDepthf(1.0f);
-#endif
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void
-CanvasDRM::update()
-{
- Options::FrameEnd m = Options::frame_end;
-
- if (m == Options::FrameEndDefault) {
- if (offscreen_)
- m = Options::FrameEndFinish;
- else
- m = Options::FrameEndSwap;
- }
-
- switch(m) {
- case Options::FrameEndSwap:
- swap_buffers();
- break;
- case Options::FrameEndFinish:
- glFinish();
- break;
- case Options::FrameEndReadPixels:
- read_pixel(width_ / 2, height_ / 2);
- break;
- case Options::FrameEndNone:
- default:
- break;
- }
-}
-
-void
-CanvasDRM::print_info()
-{
- make_current();
-
- std::stringstream ss;
- ss << " OpenGL Information" << std::endl;
- ss << " GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
- ss << " GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
- ss << " GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
- Log::info("%s", ss.str().c_str());
-}
-
-Canvas::Pixel
-CanvasDRM::read_pixel(int x, int y)
-{
- uint8_t pixel[4];
- glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
- return Canvas::Pixel(pixel[0], pixel[1], pixel[2], pixel[3]);
-}
-
-void
-CanvasDRM::write_to_file(std::string &filename)
-{
- char *pixels = new char[width_ * height_ * 4];
-
- for (int i = 0; i < height_; i++) {
- glReadPixels(0, i, width_, 1, GL_RGBA, GL_UNSIGNED_BYTE,
- &pixels[(height_ - i - 1) * width_ * 4]);
- }
-
- std::ofstream output (filename.c_str(), std::ios::out | std::ios::binary);
- output.write(pixels, 4 * width_ * height_);
-
- delete [] pixels;
-}
-
-bool
-CanvasDRM::should_quit()
-{
- return drm_.should_quit();
-}
-
-void
-CanvasDRM::resize(int width, int height)
-{
- resize_no_viewport(width, height);
- glViewport(0, 0, width_, height_);
-}
-
-/*********************
- * Protected methods *
- *********************/
-
-bool
-CanvasDRM::supports_gl2()
-{
- std::string gl_version_str(
- reinterpret_cast<const char*>(glGetString(GL_VERSION)));
- int gl_major = 0;
-
- size_t point_pos(gl_version_str.find('.'));
-
- if (point_pos != std::string::npos) {
- point_pos--;
-
- size_t start_pos(gl_version_str.rfind(' ', point_pos));
- if (start_pos == std::string::npos)
- start_pos = 0;
- else
- start_pos++;
-
- gl_major = Util::fromString<int>(
- gl_version_str.substr(start_pos, point_pos - start_pos + 1)
- );
- }
-
- return gl_major >= 2;
-}
-
-bool
-CanvasDRM::make_current()
-{
- if (!egl_.valid()) {
- Log::error("CanvasDRM: Invalid EGL state\n");
- return false;
- }
-
- init_gl_extensions();
-
- return true;
-}
-
-bool
-CanvasDRM::reset_context()
-{
- return egl_.reset();
-}
-
-void
-CanvasDRM::swap_buffers()
-{
- egl_.swap();
- drm_.do_flip();
-}
-
-void
-CanvasDRM::init_gl_extensions()
-{
-#if USE_GLESv2
- /*
- * Parse the extensions we care about from the extension string.
- * Don't even bother to get function pointers until we know the
- * extension is present.
- */
- std::string extString;
- const char* exts =
- reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
- if (exts)
- extString = exts;
-
- if (extString.find("GL_OES_mapbuffer") != std::string::npos) {
- GLExtensions::MapBuffer = reinterpret_cast<PFNGLMAPBUFFEROESPROC>(
- eglGetProcAddress("glMapBufferOES"));
- GLExtensions::UnmapBuffer = reinterpret_cast<PFNGLUNMAPBUFFEROESPROC>(
- eglGetProcAddress("glUnmapBufferOES"));
- }
-#elif USE_GL
- GLExtensions::MapBuffer = glMapBuffer;
- GLExtensions::UnmapBuffer = glUnmapBuffer;
-#endif
-}
-
-
-/*******************
- * Private methods *
- *******************/
-
-void
-CanvasDRM::resize_no_viewport(int width, int height)
-{
- width_ = drm_.mode_width();
- height_ = drm_.mode_height();
-
- if (!width_)
- width_ = width;
- if (!height_)
- height_ = height;
-
- projection_ =
- LibMatrix::Mat4::perspective(60.0, width_ / static_cast<float>(height_),
- 1.0, 1024.0);
-}
=== removed file 'src/canvas-drm.h'
@@ -1,132 +0,0 @@
-//
-// Copyright Š 2012 Linaro Limited
-//
-// This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
-//
-// glmark2 is free software: you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the Free Software
-// Foundation, either version 3 of the License, or (at your option) any later
-// version.
-//
-// glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-// details.
-//
-// You should have received a copy of the GNU General Public License along with
-// glmark2. If not, see <http://www.gnu.org/licenses/>.
-//
-// Authors:
-// Simon Que
-// Jesse Barker
-//
-#ifndef GLMARK2_CANVAS_DRM_H_
-#define GLMARK2_CANVAS_DRM_H_
-
-#include <cstring>
-#include <gbm.h>
-#include <drm.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include "canvas.h"
-#include "egl-state.h"
-
-struct DRMFBState
-{
- int fd;
- gbm_bo* bo;
- uint32_t fb_id;
-};
-
-class DRMState
-{
- static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void* data);
- static void fb_destroy_callback(gbm_bo* bo, void* data);
- static void quit_handler(int signum);
- static bool should_quit_;
- DRMFBState* fb_get_from_bo(gbm_bo* bo);
- bool init_gbm();
- int fd_;
- drmModeRes* resources_;
- drmModeConnector* connector_;
- drmModeEncoder* encoder_;
- drmModeCrtcPtr crtc_;
- drmModeModeInfo* mode_;
- gbm_device* dev_;
- gbm_surface* surface_;
- gbm_bo* bo_;
- DRMFBState* fb_;
-
-public:
- DRMState() :
- fd_(0),
- resources_(0),
- connector_(0),
- encoder_(0),
- mode_(0),
- dev_(0),
- surface_(0),
- bo_(0),
- fb_(0) {}
- ~DRMState() { cleanup(); }
- void cleanup();
- bool init();
- bool reset();
- void do_flip();
- bool should_quit() const { return should_quit_; }
- gbm_device* device() const { return dev_; }
- gbm_surface* surface() const { return surface_; }
- unsigned int mode_width() const
- {
- if (mode_) {
- return mode_->hdisplay;
- }
- return 0;
- }
- unsigned int mode_height() const
- {
- if (mode_) {
- return mode_->vdisplay;
- }
- return 0;
- }
-};
-
-/**
- * Canvas for direct rendering with EGL.
- */
-class CanvasDRM: public Canvas
-{
-public:
- CanvasDRM(int width, int height) :
- Canvas(width, height) {}
- ~CanvasDRM();
-
- virtual bool init();
- virtual bool reset();
- virtual void visible(bool visible);
- virtual void clear();
- virtual void update();
- virtual void print_info();
- virtual Pixel read_pixel(int x, int y);
- virtual void write_to_file(std::string &filename);
- virtual bool should_quit();
- virtual void resize(int width, int height);
-
-protected:
- virtual bool make_current();
- virtual bool reset_context();
- virtual void swap_buffers();
- virtual bool supports_gl2();
-
-private:
- DRMState drm_;
- EGLState egl_;
-
- void resize_no_viewport(int width, int height);
- void init_gl_extensions();
-};
-
-#endif
=== added file 'src/canvas-generic.cpp'
@@ -0,0 +1,442 @@
+/*
+ * Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alexandros Frantzis
+ */
+#include "canvas-generic.h"
+#include "native-state.h"
+#include "gl-state.h"
+#include "log.h"
+#include "options.h"
+#include "util.h"
+
+#include <fstream>
+#include <sstream>
+
+/******************
+ * Public methods *
+ ******************/
+
+bool
+CanvasGeneric::init()
+{
+ if (!native_state_.init_display())
+ return false;
+
+ gl_state_.init_display(native_state_.display(), visual_config_);
+
+ return reset();
+}
+
+bool
+CanvasGeneric::reset()
+{
+ release_fbo();
+
+ if (!gl_state_.reset())
+ return false;
+
+ if (!resize_no_viewport(width_, height_))
+ return false;
+
+ if (!do_make_current())
+ return false;
+
+ if (!supports_gl2()) {
+ Log::error("Glmark2 needs OpenGL(ES) version >= 2.0 to run"
+ " (but version string is: '%s')!\n",
+ glGetString(GL_VERSION));
+ return false;
+ }
+
+ glViewport(0, 0, width_, height_);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ clear();
+
+ return true;
+}
+
+void
+CanvasGeneric::visible(bool visible)
+{
+ if (visible && !offscreen_)
+ native_state_.visible(visible);
+}
+
+void
+CanvasGeneric::clear()
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+#if USE_GL
+ glClearDepth(1.0f);
+#elif USE_GLESv2
+ glClearDepthf(1.0f);
+#endif
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void
+CanvasGeneric::update()
+{
+ Options::FrameEnd m = Options::frame_end;
+
+ if (m == Options::FrameEndDefault) {
+ if (offscreen_)
+ m = Options::FrameEndFinish;
+ else
+ m = Options::FrameEndSwap;
+ }
+
+ switch(m) {
+ case Options::FrameEndSwap:
+ gl_state_.swap();
+ native_state_.flip();
+ break;
+ case Options::FrameEndFinish:
+ glFinish();
+ break;
+ case Options::FrameEndReadPixels:
+ read_pixel(width_ / 2, height_ / 2);
+ break;
+ case Options::FrameEndNone:
+ default:
+ break;
+ }
+}
+
+void
+CanvasGeneric::print_info()
+{
+ do_make_current();
+
+ std::stringstream ss;
+
+ ss << " OpenGL Information" << std::endl;
+ ss << " GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
+ ss << " GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
+ ss << " GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
+
+ Log::info("%s", ss.str().c_str());
+}
+
+Canvas::Pixel
+CanvasGeneric::read_pixel(int x, int y)
+{
+ uint8_t pixel[4];
+
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+
+ return Canvas::Pixel(pixel[0], pixel[1], pixel[2], pixel[3]);
+}
+
+void
+CanvasGeneric::write_to_file(std::string &filename)
+{
+ char *pixels = new char[width_ * height_ * 4];
+
+ for (int i = 0; i < height_; i++) {
+ glReadPixels(0, i, width_, 1, GL_RGBA, GL_UNSIGNED_BYTE,
+ &pixels[(height_ - i - 1) * width_ * 4]);
+ }
+
+ std::ofstream output (filename.c_str(), std::ios::out | std::ios::binary);
+ output.write(pixels, 4 * width_ * height_);
+
+ delete [] pixels;
+}
+
+bool
+CanvasGeneric::should_quit()
+{
+ return native_state_.should_quit();
+}
+
+void
+CanvasGeneric::resize(int width, int height)
+{
+ resize_no_viewport(width, height);
+ glViewport(0, 0, width_, height_);
+}
+
+unsigned int
+CanvasGeneric::fbo()
+{
+ return fbo_;
+}
+
+
+/*******************
+ * Private methods *
+ *******************/
+
+bool
+CanvasGeneric::supports_gl2()
+{
+ std::string gl_version_str(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+ int gl_major(0);
+
+ size_t point_pos(gl_version_str.find('.'));
+
+ if (point_pos != std::string::npos) {
+ point_pos--;
+
+ size_t start_pos(gl_version_str.rfind(' ', point_pos));
+ if (start_pos == std::string::npos)
+ start_pos = 0;
+ else
+ start_pos++;
+
+ gl_major = Util::fromString<int>(
+ gl_version_str.substr(start_pos, point_pos - start_pos + 1)
+ );
+ }
+
+ return gl_major >= 2;
+}
+
+bool
+CanvasGeneric::resize_no_viewport(int width, int height)
+{
+ bool request_fullscreen = (width == -1 && height == -1);
+
+ int vid;
+ if (!gl_state_.gotNativeConfig(vid))
+ {
+ Log::error("Error: Couldn't get GL visual config!\n");
+ return false;
+ }
+
+ NativeState::WindowProperties properties(width, height,
+ request_fullscreen, vid);
+ NativeState::WindowProperties cur_properties;
+
+ native_state_.window(cur_properties);
+
+ if ((cur_properties.fullscreen == properties.fullscreen &&
+ cur_properties.width > 0 && cur_properties.height > 0) ||
+ (cur_properties.width == properties.width &&
+ cur_properties.height == properties.height))
+ {
+ return true;
+ }
+
+ if (!native_state_.create_window(properties))
+ {
+ Log::error("Error: Couldn't create native window!\n");
+ return false;
+ }
+
+ native_window_ = native_state_.window(cur_properties);
+
+ width_ = cur_properties.width;
+ height_ = cur_properties.height;
+
+ if (color_renderbuffer_) {
+ glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_);
+ glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_,
+ width_, height_);
+ }
+
+ if (depth_renderbuffer_) {
+ glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_);
+ glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_,
+ width_, height_);
+ }
+
+ projection_ = LibMatrix::Mat4::perspective(60.0, width_ / static_cast<float>(height_),
+ 1.0, 1024.0);
+
+ return true;
+}
+
+bool
+CanvasGeneric::do_make_current()
+{
+ gl_state_.init_surface(native_window_);
+
+ if (!gl_state_.valid()) {
+ Log::error("CanvasGeneric: Invalid EGL state\n");
+ return false;
+ }
+
+ gl_state_.init_gl_extensions();
+
+ if (offscreen_) {
+ if (!ensure_fbo())
+ return false;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ }
+
+ return true;
+}
+
+bool
+CanvasGeneric::ensure_gl_formats()
+{
+ if (gl_color_format_ && gl_depth_format_)
+ return true;
+
+ GLVisualConfig vc;
+ gl_state_.getVisualConfig(vc);
+
+ gl_color_format_ = 0;
+ gl_depth_format_ = 0;
+
+ bool supports_rgba8(false);
+ bool supports_rgb8(false);
+ bool supports_depth24(false);
+ bool supports_depth32(false);
+
+#if USE_GLESv2
+ if (GLExtensions::support("GL_ARM_rgba8"))
+ supports_rgba8 = true;
+
+ if (GLExtensions::support("GL_OES_rgb8_rgba8")) {
+ supports_rgba8 = true;
+ supports_rgb8 = true;
+ }
+
+ if (GLExtensions::support("GL_OES_depth24"))
+ supports_depth24 = true;
+
+ if (GLExtensions::support("GL_OES_depth32"))
+ supports_depth32 = true;
+#elif USE_GL
+ supports_rgba8 = true;
+ supports_rgb8 = true;
+ supports_depth24 = true;
+ supports_depth32 = true;
+#endif
+
+ if (vc.buffer == 32) {
+ if (supports_rgba8)
+ gl_color_format_ = GL_RGBA8;
+ else
+ gl_color_format_ = GL_RGBA4;
+ }
+ else if (vc.buffer == 24) {
+ if (supports_rgb8)
+ gl_color_format_ = GL_RGB8;
+ else
+ gl_color_format_ = GL_RGB565;
+ }
+ else if (vc.buffer == 16) {
+ if (vc.red == 4 && vc.green == 4 &&
+ vc.blue == 4 && vc.alpha == 4)
+ {
+ gl_color_format_ = GL_RGBA4;
+ }
+ else if (vc.red == 5 && vc.green == 5 &&
+ vc.blue == 5 && vc.alpha == 1)
+ {
+ gl_color_format_ = GL_RGB5_A1;
+ }
+ else if (vc.red == 5 && vc.green == 6 &&
+ vc.blue == 5 && vc.alpha == 0)
+ {
+ gl_color_format_ = GL_RGB565;
+ }
+ }
+
+ if (vc.depth == 32 && supports_depth32)
+ gl_depth_format_ = GL_DEPTH_COMPONENT32;
+ else if (vc.depth >= 24 && supports_depth24)
+ gl_depth_format_ = GL_DEPTH_COMPONENT24;
+ else if (vc.depth == 16)
+ gl_depth_format_ = GL_DEPTH_COMPONENT16;
+
+ Log::debug("Selected Renderbuffer ColorFormat: %s DepthFormat: %s\n",
+ get_gl_format_str(gl_color_format_),
+ get_gl_format_str(gl_depth_format_));
+
+ return (gl_color_format_ && gl_depth_format_);
+}
+
+bool
+CanvasGeneric::ensure_fbo()
+{
+ if (!fbo_) {
+ if (!ensure_gl_formats())
+ return false;
+
+ /* Create a texture for the color attachment */
+ glGenRenderbuffers(1, &color_renderbuffer_);
+ glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_);
+ glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_,
+ width_, height_);
+
+ /* Create a renderbuffer for the depth attachment */
+ glGenRenderbuffers(1, &depth_renderbuffer_);
+ glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_);
+ glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_,
+ width_, height_);
+
+ /* Create a FBO and set it up */
+ glGenFramebuffers(1, &fbo_);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, color_renderbuffer_);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depth_renderbuffer_);
+ }
+
+ return true;
+}
+
+void
+CanvasGeneric::release_fbo()
+{
+ glDeleteFramebuffers(1, &fbo_);
+ glDeleteRenderbuffers(1, &color_renderbuffer_);
+ glDeleteRenderbuffers(1, &depth_renderbuffer_);
+ fbo_ = 0;
+ color_renderbuffer_ = 0;
+ depth_renderbuffer_ = 0;
+
+ gl_color_format_ = 0;
+ gl_depth_format_ = 0;
+}
+
+const char *
+CanvasGeneric::get_gl_format_str(GLenum f)
+{
+ const char *str;
+
+ switch(f) {
+ case GL_RGBA8: str = "GL_RGBA8"; break;
+ case GL_RGB8: str = "GL_RGB8"; break;
+ case GL_RGBA4: str = "GL_RGBA4"; break;
+ case GL_RGB5_A1: str = "GL_RGB5_A1"; break;
+ case GL_RGB565: str = "GL_RGB565"; break;
+ case GL_DEPTH_COMPONENT16: str = "GL_DEPTH_COMPONENT16"; break;
+ case GL_DEPTH_COMPONENT24: str = "GL_DEPTH_COMPONENT24"; break;
+ case GL_DEPTH_COMPONENT32: str = "GL_DEPTH_COMPONENT32"; break;
+ case GL_NONE: str = "GL_NONE"; break;
+ default: str = "Unknown"; break;
+ }
+
+ return str;
+}
=== added file 'src/canvas-generic.h'
@@ -0,0 +1,75 @@
+/*
+ * Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alexandros Frantzis
+ */
+#ifndef GLMARK2_CANVAS_GENERIC_H_
+#define GLMARK2_CANVAS_GENERIC_H_
+
+#include "canvas.h"
+
+class GLState;
+class NativeState;
+
+/**
+ * Canvas for rendering with GL to an X11 window.
+ */
+class CanvasGeneric : public Canvas
+{
+public:
+ CanvasGeneric(NativeState& native_state, GLState& gl_state,
+ int width, int height)
+ : Canvas(width, height),
+ native_state_(native_state), gl_state_(gl_state),
+ gl_color_format_(0), gl_depth_format_(0),
+ color_renderbuffer_(0), depth_renderbuffer_(0), fbo_(0) {}
+
+ bool init();
+ bool reset();
+ void visible(bool visible);
+ void clear();
+ void update();
+ void print_info();
+ Pixel read_pixel(int x, int y);
+ void write_to_file(std::string &filename);
+ bool should_quit();
+ void resize(int width, int height);
+ unsigned int fbo();
+
+private:
+ bool supports_gl2();
+ bool resize_no_viewport(int width, int height);
+ bool do_make_current();
+ bool ensure_gl_formats();
+ bool ensure_fbo();
+ void release_fbo();
+ const char *get_gl_format_str(GLenum f);
+
+ NativeState& native_state_;
+ GLState& gl_state_;
+ void* native_window_;
+ GLenum gl_color_format_;
+ GLenum gl_depth_format_;
+ GLuint color_renderbuffer_;
+ GLuint depth_renderbuffer_;
+ GLuint fbo_;
+};
+
+#endif /* GLMARK2_CANVAS_GENERIC_H_ */
=== removed file 'src/canvas-x11-egl.cpp'
@@ -1,117 +0,0 @@
-/*
- * Copyright Š 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexandros Frantzis (glmark2)
- */
-#include "canvas-x11-egl.h"
-#include "log.h"
-#include "options.h"
-
-#include <fstream>
-#include <sstream>
-#include <climits>
-
-/*********************
- * Protected methods *
- *********************/
-
-bool
-CanvasX11EGL::init_gl_winsys()
-{
- egl_.init_display(xdpy_, visual_config_);
- return true;
-}
-
-XVisualInfo *
-CanvasX11EGL::get_xvisualinfo()
-{
- XVisualInfo vis_tmpl;
- XVisualInfo *vis_info;
- int num_visuals;
- EGLint vid;
-
- if (!egl_.gotNativeConfig(vid))
- {
- Log::error("Failed to get a native-renderable EGLConfig\n");
- return 0;
- }
-
- /* The X window visual must match the EGL config */
- vis_tmpl.visualid = vid;
- vis_info = XGetVisualInfo(xdpy_, VisualIDMask, &vis_tmpl,
- &num_visuals);
- if (!vis_info) {
- Log::error("couldn't get X visual\n");
- return 0;
- }
-
- return vis_info;
-}
-
-bool
-CanvasX11EGL::make_current()
-{
- egl_.init_surface(xwin_);
- if (!egl_.valid()) {
- Log::error("CanvasX11EGL: Invalid EGL state\n");
- return false;
- }
-
- init_gl_extensions();
-
- return true;
-}
-
-void
-CanvasX11EGL::swap_buffers()
-{
- egl_.swap();
-}
-
-void
-CanvasX11EGL::get_glvisualconfig(GLVisualConfig &visual_config)
-{
- egl_.getVisualConfig(visual_config);
-}
-
-/*******************
- * Private methods *
- *******************/
-
-bool
-CanvasX11EGL::reset_context()
-{
- return egl_.reset();
-}
-
-void
-CanvasX11EGL::init_gl_extensions()
-{
-#if USE_GLESv2
- if (GLExtensions::support("GL_OES_mapbuffer")) {
- GLExtensions::MapBuffer =
- reinterpret_cast<PFNGLMAPBUFFEROESPROC>(eglGetProcAddress("glMapBufferOES"));
- GLExtensions::UnmapBuffer =
- reinterpret_cast<PFNGLUNMAPBUFFEROESPROC>(eglGetProcAddress("glUnmapBufferOES"));
- }
-#elif USE_GL
- GLExtensions::MapBuffer = glMapBuffer;
- GLExtensions::UnmapBuffer = glUnmapBuffer;
-#endif
-}
=== removed file 'src/canvas-x11.cpp'
@@ -1,526 +0,0 @@
-/*
- * Copyright Š 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexandros Frantzis (glmark2)
- * Jesse Barker
- */
-#include "canvas-x11.h"
-#include "log.h"
-#include "options.h"
-#include "util.h"
-
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <fstream>
-#include <sstream>
-
-/******************
- * Public methods *
- ******************/
-bool
-CanvasX11::reset()
-{
- release_fbo();
-
- if (!reset_context())
- return false;
-
- if (!do_make_current())
- return false;
-
- if (!supports_gl2()) {
- Log::error("Glmark2 needs OpenGL(ES) version >= 2.0 to run"
- " (but version string is: '%s')!\n",
- glGetString(GL_VERSION));
- return false;
- }
-
- glViewport(0, 0, width_, height_);
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
-
- clear();
-
- return true;
-}
-
-bool
-CanvasX11::init()
-{
- xdpy_ = XOpenDisplay(NULL);
- if (!xdpy_)
- return false;
-
- if (!init_gl_winsys())
- return false;
-
- resize_no_viewport(width_, height_);
-
- if (!xwin_)
- return false;
-
- return reset();
-}
-
-void
-CanvasX11::visible(bool visible)
-{
- if (visible && !offscreen_)
- XMapWindow(xdpy_, xwin_);
-}
-
-void
-CanvasX11::clear()
-{
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-#if USE_GL
- glClearDepth(1.0f);
-#elif USE_GLESv2
- glClearDepthf(1.0f);
-#endif
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void
-CanvasX11::update()
-{
- Options::FrameEnd m = Options::frame_end;
-
- if (m == Options::FrameEndDefault) {
- if (offscreen_)
- m = Options::FrameEndFinish;
- else
- m = Options::FrameEndSwap;
- }
-
- switch(m) {
- case Options::FrameEndSwap:
- swap_buffers();
- break;
- case Options::FrameEndFinish:
- glFinish();
- break;
- case Options::FrameEndReadPixels:
- read_pixel(width_ / 2, height_ / 2);
- break;
- case Options::FrameEndNone:
- default:
- break;
- }
-}
-
-void
-CanvasX11::print_info()
-{
- do_make_current();
-
- std::stringstream ss;
-
- ss << " OpenGL Information" << std::endl;
- ss << " GL_VENDOR: " << glGetString(GL_VENDOR) << std::endl;
- ss << " GL_RENDERER: " << glGetString(GL_RENDERER) << std::endl;
- ss << " GL_VERSION: " << glGetString(GL_VERSION) << std::endl;
-
- Log::info("%s", ss.str().c_str());
-}
-
-Canvas::Pixel
-CanvasX11::read_pixel(int x, int y)
-{
- uint8_t pixel[4];
-
- glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
-
- return Canvas::Pixel(pixel[0], pixel[1], pixel[2], pixel[3]);
-}
-
-void
-CanvasX11::write_to_file(std::string &filename)
-{
- char *pixels = new char[width_ * height_ * 4];
-
- for (int i = 0; i < height_; i++) {
- glReadPixels(0, i, width_, 1, GL_RGBA, GL_UNSIGNED_BYTE,
- &pixels[(height_ - i - 1) * width_ * 4]);
- }
-
- std::ofstream output (filename.c_str(), std::ios::out | std::ios::binary);
- output.write(pixels, 4 * width_ * height_);
-
- delete [] pixels;
-}
-
-bool
-CanvasX11::should_quit()
-{
- XEvent event;
-
- if (!XPending(xdpy_))
- return false;
-
- XNextEvent(xdpy_, &event);
-
- if (event.type == KeyPress) {
- if (XLookupKeysym(&event.xkey, 0) == XK_Escape)
- return true;
- }
- else if (event.type == ClientMessage) {
- /* Window Delete event from window manager */
- return true;
- }
-
- return false;
-}
-
-void
-CanvasX11::resize(int width, int height)
-{
- resize_no_viewport(width, height);
- glViewport(0, 0, width_, height_);
-}
-
-unsigned int
-CanvasX11::fbo()
-{
- return fbo_;
-}
-
-bool
-CanvasX11::supports_gl2()
-{
- std::string gl_version_str(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
- int gl_major(0);
-
- size_t point_pos(gl_version_str.find('.'));
-
- if (point_pos != std::string::npos) {
- point_pos--;
-
- size_t start_pos(gl_version_str.rfind(' ', point_pos));
- if (start_pos == std::string::npos)
- start_pos = 0;
- else
- start_pos++;
-
- gl_major = Util::fromString<int>(
- gl_version_str.substr(start_pos, point_pos - start_pos + 1)
- );
- }
-
- return gl_major >= 2;
-}
-
-/*******************
- * Private methods *
- *******************/
-
-bool
-CanvasX11::ensure_x_window()
-{
- static const char *win_name("glmark2 "GLMARK_VERSION);
-
- if (xwin_)
- return true;
-
- if (!xdpy_) {
- Log::error("Error: X11 Display has not been initialized!\n");
- return false;
- }
-
- XVisualInfo *vis_info = get_xvisualinfo();
- if (!vis_info) {
- Log::error("Error: Could not get a valid XVisualInfo!\n");
- return false;
- }
-
- Log::debug("Creating XWindow W: %d H: %d VisualID: 0x%x\n",
- width_, height_, vis_info->visualid);
-
- /* window attributes */
- XSetWindowAttributes attr;
- unsigned long mask;
- Window root = RootWindow(xdpy_, DefaultScreen(xdpy_));
-
- attr.background_pixel = 0;
- attr.border_pixel = 0;
- attr.colormap = XCreateColormap(xdpy_, root, vis_info->visual, AllocNone);
- attr.event_mask = KeyPressMask;
- mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
-
- xwin_ = XCreateWindow(xdpy_, root, 0, 0, width_, height_,
- 0, vis_info->depth, InputOutput,
- vis_info->visual, mask, &attr);
-
- XFree(vis_info);
-
- if (!xwin_) {
- Log::error("Error: XCreateWindow() failed!\n");
- return false;
- }
-
- /* set hints and properties */
- if (fullscreen_) {
- Atom atom = XInternAtom(xdpy_, "_NET_WM_STATE_FULLSCREEN", True);
- XChangeProperty(xdpy_, xwin_,
- XInternAtom(xdpy_, "_NET_WM_STATE", True),
- XA_ATOM, 32, PropModeReplace,
- reinterpret_cast<unsigned char*>(&atom), 1);
- }
- else {
- XSizeHints sizehints;
- sizehints.min_width = width_;
- sizehints.min_height = height_;
- sizehints.max_width = width_;
- sizehints.max_height = height_;
- sizehints.flags = PMaxSize | PMinSize;
-
- XSetWMProperties(xdpy_, xwin_, NULL, NULL,
- NULL, 0, &sizehints, NULL, NULL);
- }
-
- /* Set the window name */
- XStoreName(xdpy_ , xwin_, win_name);
-
- /* Gracefully handle Window Delete event from window manager */
- Atom wmDelete = XInternAtom(xdpy_, "WM_DELETE_WINDOW", True);
- XSetWMProtocols(xdpy_, xwin_, &wmDelete, 1);
-
- return true;
-}
-
-void
-CanvasX11::resize_no_viewport(int width, int height)
-{
- bool request_fullscreen = (width == -1 || height == -1);
-
- /* Recreate an existing window only if it has actually been resized */
- if (xwin_) {
- if (width_ != width || height_ != height ||
- fullscreen_ != request_fullscreen)
- {
- XDestroyWindow(xdpy_, xwin_);
- xwin_ = 0;
- }
- else
- {
- return;
- }
- }
-
- fullscreen_ = request_fullscreen;
-
- if (fullscreen_) {
- /* Get the screen (root window) size */
- XWindowAttributes window_attr;
- XGetWindowAttributes(xdpy_, RootWindow(xdpy_, DefaultScreen(xdpy_)),
- &window_attr);
- width_ = window_attr.width;
- height_ = window_attr.height;
- }
- else {
- width_ = width;
- height_ = height;
- }
-
- if (!ensure_x_window())
- Log::error("Error: Couldn't create X Window!\n");
-
- if (color_renderbuffer_) {
- glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_);
- glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_,
- width_, height_);
- }
-
- if (depth_renderbuffer_) {
- glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_);
- glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_,
- width_, height_);
- }
-
- projection_ = LibMatrix::Mat4::perspective(60.0, width_ / static_cast<float>(height_),
- 1.0, 1024.0);
-}
-
-bool
-CanvasX11::do_make_current()
-{
- if (!make_current())
- return false;
-
- if (offscreen_) {
- if (!ensure_fbo())
- return false;
-
- glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
- }
-
- return true;
-}
-
-bool
-CanvasX11::ensure_gl_formats()
-{
- if (gl_color_format_ && gl_depth_format_)
- return true;
-
- GLVisualConfig vc;
- get_glvisualconfig(vc);
-
- gl_color_format_ = 0;
- gl_depth_format_ = 0;
-
- bool supports_rgba8(false);
- bool supports_rgb8(false);
- bool supports_depth24(false);
- bool supports_depth32(false);
-
-#if USE_GLESv2
- if (GLExtensions::support("GL_ARM_rgba8"))
- supports_rgba8 = true;
-
- if (GLExtensions::support("GL_OES_rgb8_rgba8")) {
- supports_rgba8 = true;
- supports_rgb8 = true;
- }
-
- if (GLExtensions::support("GL_OES_depth24"))
- supports_depth24 = true;
-
- if (GLExtensions::support("GL_OES_depth32"))
- supports_depth32 = true;
-#elif USE_GL
- supports_rgba8 = true;
- supports_rgb8 = true;
- supports_depth24 = true;
- supports_depth32 = true;
-#endif
-
- if (vc.buffer == 32) {
- if (supports_rgba8)
- gl_color_format_ = GL_RGBA8;
- else
- gl_color_format_ = GL_RGBA4;
- }
- else if (vc.buffer == 24) {
- if (supports_rgb8)
- gl_color_format_ = GL_RGB8;
- else
- gl_color_format_ = GL_RGB565;
- }
- else if (vc.buffer == 16) {
- if (vc.red == 4 && vc.green == 4 &&
- vc.blue == 4 && vc.alpha == 4)
- {
- gl_color_format_ = GL_RGBA4;
- }
- else if (vc.red == 5 && vc.green == 5 &&
- vc.blue == 5 && vc.alpha == 1)
- {
- gl_color_format_ = GL_RGB5_A1;
- }
- else if (vc.red == 5 && vc.green == 6 &&
- vc.blue == 5 && vc.alpha == 0)
- {
- gl_color_format_ = GL_RGB565;
- }
- }
-
- if (vc.depth == 32 && supports_depth32)
- gl_depth_format_ = GL_DEPTH_COMPONENT32;
- else if (vc.depth >= 24 && supports_depth24)
- gl_depth_format_ = GL_DEPTH_COMPONENT24;
- else if (vc.depth == 16)
- gl_depth_format_ = GL_DEPTH_COMPONENT16;
-
- Log::debug("Selected Renderbuffer ColorFormat: %s DepthFormat: %s\n",
- get_gl_format_str(gl_color_format_),
- get_gl_format_str(gl_depth_format_));
-
- return (gl_color_format_ && gl_depth_format_);
-}
-
-bool
-CanvasX11::ensure_fbo()
-{
- if (!fbo_) {
- if (!ensure_gl_formats())
- return false;
-
- /* Create a texture for the color attachment */
- glGenRenderbuffers(1, &color_renderbuffer_);
- glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer_);
- glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format_,
- width_, height_);
-
- /* Create a renderbuffer for the depth attachment */
- glGenRenderbuffers(1, &depth_renderbuffer_);
- glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer_);
- glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format_,
- width_, height_);
-
- /* Create a FBO and set it up */
- glGenFramebuffers(1, &fbo_);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, color_renderbuffer_);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, depth_renderbuffer_);
- }
-
- return true;
-}
-
-void
-CanvasX11::release_fbo()
-{
- glDeleteFramebuffers(1, &fbo_);
- glDeleteRenderbuffers(1, &color_renderbuffer_);
- glDeleteRenderbuffers(1, &depth_renderbuffer_);
- fbo_ = 0;
- color_renderbuffer_ = 0;
- depth_renderbuffer_ = 0;
-
- gl_color_format_ = 0;
- gl_depth_format_ = 0;
-}
-
-const char *
-CanvasX11::get_gl_format_str(GLenum f)
-{
- const char *str;
-
- switch(f) {
- case GL_RGBA8: str = "GL_RGBA8"; break;
- case GL_RGB8: str = "GL_RGB8"; break;
- case GL_RGBA4: str = "GL_RGBA4"; break;
- case GL_RGB5_A1: str = "GL_RGB5_A1"; break;
- case GL_RGB565: str = "GL_RGB565"; break;
- case GL_DEPTH_COMPONENT16: str = "GL_DEPTH_COMPONENT16"; break;
- case GL_DEPTH_COMPONENT24: str = "GL_DEPTH_COMPONENT24"; break;
- case GL_DEPTH_COMPONENT32: str = "GL_DEPTH_COMPONENT32"; break;
- case GL_NONE: str = "GL_NONE"; break;
- default: str = "Unknown"; break;
- }
-
- return str;
-}
-
=== removed file 'src/canvas-x11.h'
@@ -1,141 +0,0 @@
-/*
- * Copyright Š 2010-2011 Linaro Limited
- *
- * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
- *
- * glmark2 is free software: you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version.
- *
- * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * glmark2. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Alexandros Frantzis (glmark2)
- */
-#ifndef GLMARK2_CANVAS_X11_H_
-#define GLMARK2_CANVAS_X11_H_
-
-#include "canvas.h"
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-/**
- * Canvas for rendering with GL to an X11 window.
- */
-class CanvasX11 : public Canvas
-{
-public:
- ~CanvasX11() {}
-
- virtual bool init();
- virtual bool reset();
- virtual void visible(bool visible);
- virtual void clear();
- virtual void update();
- virtual void print_info();
- virtual Pixel read_pixel(int x, int y);
- virtual void write_to_file(std::string &filename);
- virtual bool should_quit();
- virtual void resize(int width, int height);
- virtual unsigned int fbo();
-
-protected:
- CanvasX11(int width, int height) :
- Canvas(width, height), xwin_(0), xdpy_(0), fullscreen_(false),
- gl_color_format_(0), gl_depth_format_(0),
- color_renderbuffer_(0), depth_renderbuffer_(0), fbo_(0) {}
-
- /**
- * Gets the XVisualInfo to use for creating the X window with.
- *
- * The caller should XFree() the returned XVisualInfo when done.
- *
- * This method should be implemented in derived classes.
- *
- * @return the XVisualInfo
- */
- virtual XVisualInfo *get_xvisualinfo() = 0;
-
- /**
- * Initializes window system interfaces for GL rendering.
- *
- * This method should be implemented in derived classes.
- *
- * @return whether the operation succeeded
- */
- virtual bool init_gl_winsys() = 0;
-
- /**
- * Makes the canvas the current target for GL rendering.
- *
- * This method should be implemented in derived classes.
- *
- * @return whether the operation succeeded
- */
- virtual bool make_current() = 0;
-
- /**
- * Resets the underlying GL context for rendering.
- *
- * This method should be implemented in derived classes.
- *
- * @return whether the operation succeeded
- */
- virtual bool reset_context() = 0;
-
- /**
- * Swaps the GL buffers (assuming double buffering is used).
- *
- * This method should be implemented in derived classes.
- *
- * @return whether the operation succeeded
- */
- virtual void swap_buffers() = 0;
-
- /**
- * Gets information about the GL visual used for this canvas.
- *
- * This method should be implemented in derived classes.
- */
- virtual void get_glvisualconfig(GLVisualConfig &visual_config) = 0;
-
- /**
- * Whether the current implementation supports GL(ES) 2.0.
- *
- * @return true if it supports GL(ES) 2.0, false otherwise
- */
- bool supports_gl2();
-
-
- /** The X window associated with this canvas. */
- Window xwin_;
- /** The X display associated with this canvas. */
- Display *xdpy_;
-
-private:
- void resize_no_viewport(int width, int height);
- bool ensure_x_window();
- bool do_make_current();
- bool ensure_gl_formats();
- bool ensure_fbo();
- void release_fbo();
-
- const char *get_gl_format_str(GLenum f);
-
- bool fullscreen_;
- GLenum gl_color_format_;
- GLenum gl_depth_format_;
- GLuint color_renderbuffer_;
- GLuint depth_renderbuffer_;
- GLuint fbo_;
-};
-
-#endif
-
=== renamed file 'src/egl-state.cpp' => 'src/gl-state-egl.cpp'
@@ -19,16 +19,22 @@
// Authors:
// Jesse Barker
//
-#include "egl-state.h"
+#include "gl-state-egl.h"
#include "log.h"
#include "options.h"
+#include "gl-headers.h"
#include "limits.h"
+#include "gl-headers.h"
#include <iomanip>
#include <sstream>
using std::vector;
using std::string;
+/****************************
+ * EGLConfig public methods *
+ ****************************/
+
EglConfig::EglConfig(EGLDisplay dpy, EGLConfig config) :
handle_(config),
bufferSize_(0),
@@ -185,8 +191,8 @@
if (!eglGetConfigAttrib(dpy, handle_, EGL_SAMPLES, &samples_))
{
badAttribVec.push_back("EGL_SAMPLES");
- }
- }
+ }
+ }
if (!eglGetConfigAttrib(dpy, handle_, EGL_TRANSPARENT_TYPE, &xparentType_))
{
badAttribVec.push_back("EGL_TRANSPARENT_TYPE");
@@ -277,18 +283,21 @@
Log::debug("%s\n", s.str().c_str());
}
+/*****************************
+ * GLStateEGL public methods *
+ ****************************/
bool
-EGLState::init_display(EGLNativeDisplayType native_display, GLVisualConfig& visual_config)
+GLStateEGL::init_display(void* native_display, GLVisualConfig& visual_config)
{
- native_display_ = native_display;
- visual_config_ = visual_config;
+ native_display_ = reinterpret_cast<EGLNativeDisplayType>(native_display);
+ requested_visual_config_ = visual_config;
return gotValidDisplay();
}
bool
-EGLState::init_surface(EGLNativeWindowType native_window)
+GLStateEGL::init_surface(void* native_window)
{
native_window_ = reinterpret_cast<EGLNativeWindowType>(native_window);
@@ -296,13 +305,112 @@
}
void
-EGLState::swap()
+GLStateEGL::init_gl_extensions()
+{
+#if USE_GLESv2
+ if (GLExtensions::support("GL_OES_mapbuffer")) {
+ GLExtensions::MapBuffer =
+ reinterpret_cast<PFNGLMAPBUFFEROESPROC>(eglGetProcAddress("glMapBufferOES"));
+ GLExtensions::UnmapBuffer =
+ reinterpret_cast<PFNGLUNMAPBUFFEROESPROC>(eglGetProcAddress("glUnmapBufferOES"));
+ }
+#elif USE_GL
+ GLExtensions::MapBuffer = glMapBuffer;
+ GLExtensions::UnmapBuffer = glUnmapBuffer;
+#endif
+}
+
+bool
+GLStateEGL::valid()
+{
+ if (!gotValidDisplay())
+ return false;
+
+ if (!gotValidConfig())
+ return false;
+
+ if (!gotValidSurface())
+ return false;
+
+ if (!gotValidContext())
+ return false;
+
+ if (egl_context_ == eglGetCurrentContext())
+ return true;
+
+ if (!eglMakeCurrent(egl_display_, egl_surface_, egl_surface_, egl_context_)) {
+ Log::error("eglMakeCurrent failed with error: 0x%x\n", eglGetError());
+ return false;
+ }
+
+ if (!eglSwapInterval(egl_display_, 0)) {
+ Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n");
+ }
+
+ init_gl_extensions();
+
+ return true;
+}
+
+bool
+GLStateEGL::reset()
+{
+ if (!gotValidDisplay()) {
+ return false;
+ }
+
+ if (!egl_context_) {
+ return true;
+ }
+
+ if (EGL_FALSE == eglDestroyContext(egl_display_, egl_context_)) {
+ Log::debug("eglDestroyContext failed with error: 0x%x\n", eglGetError());
+ }
+
+ egl_context_ = 0;
+
+ return true;
+}
+
+void
+GLStateEGL::swap()
{
eglSwapBuffers(egl_display_, egl_surface_);
}
bool
-EGLState::gotValidDisplay()
+GLStateEGL::gotNativeConfig(int& vid)
+{
+ if (!gotValidConfig())
+ return false;
+
+ EGLint native_id;
+ if (!eglGetConfigAttrib(egl_display_, egl_config_, EGL_NATIVE_VISUAL_ID,
+ &native_id))
+ {
+ Log::debug("Failed to get native visual id for EGLConfig 0x%x\n", egl_config_);
+ return false;
+ }
+
+ vid = native_id;
+ return true;
+}
+
+void
+GLStateEGL::getVisualConfig(GLVisualConfig& vc)
+{
+ if (!gotValidConfig())
+ return;
+
+ get_glvisualconfig(egl_config_, vc);
+}
+
+/******************************
+ * GLStateEGL private methods *
+ *****************************/
+
+bool
+GLStateEGL::gotValidDisplay()
{
if (egl_display_)
return true;
@@ -334,7 +442,7 @@
}
void
-EGLState::get_glvisualconfig(EGLConfig config, GLVisualConfig& visual_config)
+GLStateEGL::get_glvisualconfig(EGLConfig config, GLVisualConfig& visual_config)
{
eglGetConfigAttrib(egl_display_, config, EGL_BUFFER_SIZE, &visual_config.buffer);
eglGetConfigAttrib(egl_display_, config, EGL_RED_SIZE, &visual_config.red);
@@ -346,7 +454,7 @@
}
EGLConfig
-EGLState::select_best_config(std::vector<EGLConfig>& configs)
+GLStateEGL::select_best_config(std::vector<EGLConfig>& configs)
{
int best_score(INT_MIN);
EGLConfig best_config(0);
@@ -365,7 +473,7 @@
get_glvisualconfig(config, vc);
- score = vc.match_score(visual_config_);
+ score = vc.match_score(requested_visual_config_);
if (score > best_score) {
best_score = score;
@@ -377,7 +485,7 @@
}
bool
-EGLState::gotValidConfig()
+GLStateEGL::gotValidConfig()
{
if (egl_config_)
return true;
@@ -386,12 +494,12 @@
return false;
const EGLint config_attribs[] = {
- EGL_RED_SIZE, visual_config_.red,
- EGL_GREEN_SIZE, visual_config_.green,
- EGL_BLUE_SIZE, visual_config_.blue,
- EGL_ALPHA_SIZE, visual_config_.alpha,
- EGL_DEPTH_SIZE, visual_config_.depth,
- EGL_STENCIL_SIZE, visual_config_.stencil,
+ EGL_RED_SIZE, requested_visual_config_.red,
+ EGL_GREEN_SIZE, requested_visual_config_.green,
+ EGL_BLUE_SIZE, requested_visual_config_.blue,
+ EGL_ALPHA_SIZE, requested_visual_config_.alpha,
+ EGL_DEPTH_SIZE, requested_visual_config_.depth,
+ EGL_STENCIL_SIZE, requested_visual_config_.stencil,
#if USE_GLESv2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#elif USE_GL
@@ -436,7 +544,7 @@
if (*configIt == egl_config_) {
best_config_ = cfg;
}
- }
+ }
// Print out the config information, and let the user know the decision
// about the "best" one with respect to the options.
@@ -459,7 +567,7 @@
}
bool
-EGLState::gotValidSurface()
+GLStateEGL::gotValidSurface()
{
if (egl_surface_)
return true;
@@ -480,7 +588,7 @@
}
bool
-EGLState::gotValidContext()
+GLStateEGL::gotValidContext()
{
if (egl_context_)
return true;
@@ -509,70 +617,3 @@
return true;
}
-bool
-EGLState::valid()
-{
- if (!gotValidDisplay())
- return false;
-
- if (!gotValidConfig())
- return false;
-
- if (!gotValidSurface())
- return false;
-
- if (!gotValidContext())
- return false;
-
- if (egl_context_ == eglGetCurrentContext())
- return true;
-
- if (!eglMakeCurrent(egl_display_, egl_surface_, egl_surface_, egl_context_)) {
- Log::error("eglMakeCurrent failed with error: 0x%x\n", eglGetError());
- return false;
- }
-
- if (!eglSwapInterval(egl_display_, 0)) {
- Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n");
- }
-
- return true;
-}
-
-bool
-EGLState::gotNativeConfig(int& vid)
-{
- if (!gotValidConfig())
- return false;
-
- EGLint native_id;
- if (!eglGetConfigAttrib(egl_display_, egl_config_, EGL_NATIVE_VISUAL_ID,
- &native_id))
- {
- Log::debug("Failed to get native visual id for EGLConfig 0x%x\n", egl_config_);
- return false;
- }
-
- vid = native_id;
- return true;
-}
-
-bool
-EGLState::reset()
-{
- if (!gotValidDisplay()) {
- return false;
- }
-
- if (!egl_context_) {
- return true;
- }
-
- if (EGL_FALSE == eglDestroyContext(egl_display_, egl_context_)) {
- Log::debug("eglDestroyContext failed with error: 0x%x\n", eglGetError());
- }
-
- egl_context_ = 0;
-
- return true;
-}
=== renamed file 'src/egl-state.h' => 'src/gl-state-egl.h'
@@ -19,11 +19,12 @@
// Authors:
// Jesse Barker
//
-#ifndef EGL_STATE_H_
-#define EGL_STATE_H_
+#ifndef GLMARK2_GL_STATE_EGL_H_
+#define GLMARK2_GL_STATE_EGL_H_
#include <vector>
#include <EGL/egl.h>
+#include "gl-state.h"
#include "gl-visual-config.h"
class EglConfig
@@ -113,7 +114,7 @@
EGLint configID() const { return configID_; }
};
-class EGLState
+class GLStateEGL : public GLState
{
EGLNativeDisplayType native_display_;
EGLNativeWindowType native_window_;
@@ -121,7 +122,7 @@
EGLConfig egl_config_;
EGLContext egl_context_;
EGLSurface egl_surface_;
- GLVisualConfig visual_config_;
+ GLVisualConfig requested_visual_config_;
EglConfig best_config_;
bool gotValidDisplay();
bool gotValidConfig();
@@ -130,22 +131,23 @@
void get_glvisualconfig(EGLConfig config, GLVisualConfig& visual_config);
EGLConfig select_best_config(std::vector<EGLConfig>& configs);
public:
- EGLState() :
+ GLStateEGL() :
native_display_(0),
native_window_(0),
egl_display_(0),
egl_config_(0),
egl_context_(0),
egl_surface_(0) {}
- ~EGLState() {}
+
+ bool init_display(void* native_display, GLVisualConfig& config_pref);
+ bool init_surface(void* native_window);
+ void init_gl_extensions();
bool valid();
- bool init_display(EGLNativeDisplayType native_display, GLVisualConfig& config_pref);
- bool init_surface(EGLNativeWindowType native_window);
bool reset();
void swap();
// Performs a config search, returning a native visual ID on success
bool gotNativeConfig(int& vid);
- void getVisualConfig(GLVisualConfig& vc) { vc = visual_config_; }
+ void getVisualConfig(GLVisualConfig& vc);
};
-#endif // EGL_STATE_H_
+#endif // GLMARK2_GL_STATE_EGL_H_
=== renamed file 'src/canvas-x11-glx.cpp' => 'src/gl-state-glx.cpp'
@@ -1,5 +1,6 @@
/*
* Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
@@ -17,37 +18,55 @@
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
- * Alexandros Frantzis (glmark2)
+ * Alexandros Frantzis
*/
-#include "canvas-x11-glx.h"
+#include "gl-state-glx.h"
#include "log.h"
#include "options.h"
-#include <string>
#include <climits>
-static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT_;
-static PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA_;
-static PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESA_;
-
-/*********************
- * Protected methods *
- *********************/
-
-XVisualInfo *
-CanvasX11GLX::get_xvisualinfo()
+namespace
+{
+PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT_;
+PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA_;
+PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESA_;
+}
+
+/******************
+ * Public methods *
+ ******************/
+
+bool
+GLStateGLX::init_display(void* native_display, GLVisualConfig& visual_config)
+{
+ xdpy_ = reinterpret_cast<Display*>(native_display);
+ requested_visual_config_ = visual_config;
+
+ return (xdpy_ != 0);
+}
+
+bool
+GLStateGLX::init_surface(void* native_window)
+{
+ xwin_ = reinterpret_cast<Window>(native_window);
+
+ return (xwin_ != 0);
+}
+
+void
+GLStateGLX::init_gl_extensions()
+{
+ GLExtensions::MapBuffer = glMapBuffer;
+ GLExtensions::UnmapBuffer = glUnmapBuffer;
+}
+
+bool
+GLStateGLX::valid()
{
if (!ensure_glx_fbconfig())
- return 0;
-
- XVisualInfo *vis_info = glXGetVisualFromFBConfig(xdpy_, glx_fbconfig_ );
-
- return vis_info;
-}
-
-bool
-CanvasX11GLX::make_current()
-{
+ return false;
+
if (!ensure_glx_context())
return false;
@@ -61,6 +80,8 @@
return false;
}
+ init_gl_extensions();
+
unsigned int desired_swap(0);
unsigned int actual_swap(-1);
if (glXSwapIntervalEXT_) {
@@ -82,13 +103,49 @@
return true;
}
-void
-CanvasX11GLX::get_glvisualconfig(GLVisualConfig &visual_config)
+
+bool
+GLStateGLX::reset()
+{
+ if (glx_context_)
+ {
+ glXDestroyContext(xdpy_, glx_context_);
+ glx_context_ = 0;
+ }
+
+ return true;
+}
+
+void
+GLStateGLX::swap()
+{
+ glXSwapBuffers(xdpy_, xwin_);
+}
+
+bool
+GLStateGLX::gotNativeConfig(int& vid)
+{
+ if (!ensure_glx_fbconfig())
+ return false;
+
+ int native_id;
+ if (glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_VISUAL_ID, &native_id) != Success)
+ {
+ Log::debug("Failed to get native visual id for GLXFBConfig 0x%x\n", glx_fbconfig_);
+ return false;
+ }
+
+ vid = native_id;
+ return true;
+}
+
+void
+GLStateGLX::getVisualConfig(GLVisualConfig& vc)
{
if (!ensure_glx_fbconfig())
return;
- get_glvisualconfig_glx(glx_fbconfig_, visual_config);
+ get_glvisualconfig_glx(glx_fbconfig_, vc);
}
/*******************
@@ -96,7 +153,7 @@
*******************/
bool
-CanvasX11GLX::check_glx_version()
+GLStateGLX::check_glx_version()
{
int glx_major, glx_minor;
@@ -111,7 +168,7 @@
}
void
-CanvasX11GLX::init_extensions()
+GLStateGLX::init_extensions()
{
/*
* Parse the extensions we care about from the extension string.
@@ -159,20 +216,20 @@
}
bool
-CanvasX11GLX::ensure_glx_fbconfig()
+GLStateGLX::ensure_glx_fbconfig()
{
static int attribs[] = {
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
- GLX_RED_SIZE, visual_config_.red,
- GLX_GREEN_SIZE, visual_config_.green,
- GLX_BLUE_SIZE, visual_config_.blue,
- GLX_ALPHA_SIZE, visual_config_.alpha,
- GLX_DEPTH_SIZE, visual_config_.depth,
- GLX_STENCIL_SIZE, visual_config_.stencil,
- GLX_BUFFER_SIZE, visual_config_.buffer,
+ GLX_RED_SIZE, requested_visual_config_.red,
+ GLX_GREEN_SIZE, requested_visual_config_.green,
+ GLX_BLUE_SIZE, requested_visual_config_.blue,
+ GLX_ALPHA_SIZE, requested_visual_config_.alpha,
+ GLX_DEPTH_SIZE, requested_visual_config_.depth,
+ GLX_STENCIL_SIZE, requested_visual_config_.stencil,
+ GLX_BUFFER_SIZE, requested_visual_config_.buffer,
GLX_DOUBLEBUFFER, True,
None
};
@@ -227,24 +284,8 @@
return true;
}
-void
-CanvasX11GLX::init_gl_extensions()
-{
- GLExtensions::MapBuffer = glMapBuffer;
- GLExtensions::UnmapBuffer = glUnmapBuffer;
-}
-
-bool
-CanvasX11GLX::reset_context()
-{
- glXDestroyContext(xdpy_, glx_context_);
- glx_context_ = 0;
-
- return true;
-}
-
-bool
-CanvasX11GLX::ensure_glx_context()
+bool
+GLStateGLX::ensure_glx_context()
{
if (glx_context_)
return true;
@@ -259,13 +300,12 @@
return false;
}
- init_gl_extensions();
return true;
}
void
-CanvasX11GLX::get_glvisualconfig_glx(const GLXFBConfig config, GLVisualConfig &visual_config)
+GLStateGLX::get_glvisualconfig_glx(const GLXFBConfig config, GLVisualConfig &visual_config)
{
glXGetFBConfigAttrib(xdpy_, config, GLX_BUFFER_SIZE, &visual_config.buffer);
glXGetFBConfigAttrib(xdpy_, config, GLX_RED_SIZE, &visual_config.red);
@@ -277,7 +317,7 @@
}
GLXFBConfig
-CanvasX11GLX::select_best_config(std::vector<GLXFBConfig> configs)
+GLStateGLX::select_best_config(std::vector<GLXFBConfig> configs)
{
int best_score(INT_MIN);
GLXFBConfig best_config(0);
@@ -296,7 +336,7 @@
get_glvisualconfig_glx(config, vc);
- score = vc.match_score(visual_config_);
+ score = vc.match_score(requested_visual_config_);
if (score > best_score) {
best_score = score;
=== renamed file 'src/canvas-x11-glx.h' => 'src/gl-state-glx.h'
@@ -1,5 +1,6 @@
/*
* Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
@@ -17,49 +18,50 @@
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
- * Alexandros Frantzis (glmark2)
+ * Alexandros Frantzis
*/
-#ifndef GLMARK2_CANVAS_X11_GLX_H_
-#define GLMARK2_CANVAS_X11_GLX_H_
-
-#include "canvas-x11.h"
-
+#ifndef GLMARK2_GL_STATE_GLX_H_
+#define GLMARK2_GL_STATE_GLX_H_
+
+#include "gl-state.h"
+#include "gl-visual-config.h"
+#include "gl-headers.h"
+
+#include <vector>
+
+#include <X11/Xlib.h>
#define GLX_GLXEXT_PROTOTYPES
#include <GL/glx.h>
#include <GL/glxext.h>
-#include <vector>
-/**
- * Canvas for rendering to an X11 window using GLX.
- */
-class CanvasX11GLX : public CanvasX11
+class GLStateGLX : public GLState
{
public:
- CanvasX11GLX(int width, int height) :
- CanvasX11(width, height), glx_fbconfig_(0), glx_context_(0) {}
- ~CanvasX11GLX() {}
+ GLStateGLX()
+ : xdpy_(0), xwin_(0), glx_fbconfig_(0), glx_context_(0) {}
-protected:
- XVisualInfo *get_xvisualinfo();
- bool make_current();
- bool reset_context();
- void swap_buffers() { glXSwapBuffers(xdpy_, xwin_); }
- void get_glvisualconfig(GLVisualConfig &visual_config);
- bool init_gl_winsys() { return true; }
+ bool valid();
+ bool init_display(void* native_display, GLVisualConfig& config_pref);
+ bool init_surface(void* native_window);
+ void init_gl_extensions();
+ bool reset();
+ void swap();
+ bool gotNativeConfig(int& vid);
+ void getVisualConfig(GLVisualConfig& vc);
private:
bool check_glx_version();
void init_extensions();
bool ensure_glx_fbconfig();
bool ensure_glx_context();
- void init_gl_extensions();
void get_glvisualconfig_glx(GLXFBConfig config, GLVisualConfig &visual_config);
GLXFBConfig select_best_config(std::vector<GLXFBConfig> configs);
+ Display* xdpy_;
+ Window xwin_;
GLXFBConfig glx_fbconfig_;
GLXContext glx_context_;
-
+ GLVisualConfig requested_visual_config_;
};
-#endif
-
+#endif /* GLMARK2_GL_STATE_GLX_H_ */
=== added file 'src/gl-state.h'
@@ -0,0 +1,42 @@
+/*
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alexandros Frantzis
+ */
+#ifndef GLMARK2_GL_STATE_H_
+#define GLMARK2_GL_STATE_H_
+
+class GLVisualConfig;
+
+class GLState
+{
+public:
+ virtual ~GLState() {}
+
+ virtual bool init_display(void *native_display, GLVisualConfig& config_pref) = 0;
+ virtual bool init_surface(void *native_window) = 0;
+ virtual void init_gl_extensions() = 0;
+ virtual bool valid() = 0;
+ virtual bool reset() = 0;
+ virtual void swap() = 0;
+ virtual bool gotNativeConfig(int& vid) = 0;
+ virtual void getVisualConfig(GLVisualConfig& vc) = 0;
+};
+
+#endif /* GLMARK2_GL_STATE_H_ */
=== modified file 'src/main.cpp'
@@ -35,12 +35,17 @@
#include <iostream>
#include <fstream>
+#include "canvas-generic.h"
+
#if USE_DRM
-#include "canvas-drm.h"
+#include "native-state-drm.h"
+#include "gl-state-egl.h"
#elif USE_GL
-#include "canvas-x11-glx.h"
+#include "native-state-x11.h"
+#include "gl-state-glx.h"
#elif USE_GLESv2
-#include "canvas-x11-egl.h"
+#include "native-state-x11.h"
+#include "gl-state-egl.h"
#endif
using std::vector;
@@ -183,13 +188,18 @@
// Create the canvas
#if USE_DRM
- CanvasDRM canvas(Options::size.first, Options::size.second);
+ NativeStateDRM native_state;
+ GLStateEGL gl_state;
#elif USE_GL
- CanvasX11GLX canvas(Options::size.first, Options::size.second);
+ NativeStateX11 native_state;
+ GLStateGLX gl_state;
#elif USE_GLESv2
- CanvasX11EGL canvas(Options::size.first, Options::size.second);
+ NativeStateX11 native_state;
+ GLStateEGL gl_state;
#endif
+ CanvasGeneric canvas(native_state, gl_state, Options::size.first, Options::size.second);
+
canvas.offscreen(Options::offscreen);
canvas.visual_config(Options::visual_config);
=== added file 'src/native-state-drm.cpp'
@@ -0,0 +1,355 @@
+/*
+ * Copyright Š 2012 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Simon Que
+ * Jesse Barker
+ * Alexandros Frantzis
+ */
+#include "native-state-drm.h"
+#include "log.h"
+#include <csignal>
+
+/******************
+ * Public methods *
+ ******************/
+
+bool
+NativeStateDRM::init_display()
+{
+ if (!dev_)
+ init();
+
+ return (dev_ != 0);
+}
+
+void*
+NativeStateDRM::display()
+{
+ return (void*)dev_;
+}
+
+bool
+NativeStateDRM::create_window(WindowProperties const& /*properties*/)
+{
+ if (!dev_) {
+ Log::error("Error: DRM device has not been initialized!\n");
+ return false;
+ }
+
+ return true;
+}
+
+void*
+NativeStateDRM::window(WindowProperties& properties)
+{
+ properties = WindowProperties(mode_->hdisplay,
+ mode_->vdisplay,
+ true, 0);
+ return (void*)surface_;
+}
+
+void
+NativeStateDRM::visible(bool /*visible*/)
+{
+}
+
+bool
+NativeStateDRM::should_quit()
+{
+ return should_quit_;
+}
+
+void
+NativeStateDRM::flip()
+{
+ gbm_bo* next = gbm_surface_lock_front_buffer(surface_);
+ fb_ = fb_get_from_bo(next);
+ unsigned int waiting(1);
+
+ if (!crtc_set_) {
+ int status = drmModeSetCrtc(fd_, encoder_->crtc_id, fb_->fb_id, 0, 0,
+ &connector_->connector_id, 1, mode_);
+ if (status >= 0) {
+ crtc_set_ = true;
+ bo_ = next;
+ }
+ else {
+ Log::error("Failed to set crtc: %d\n", status);
+ }
+ return;
+ }
+
+ int status = drmModePageFlip(fd_, encoder_->crtc_id, fb_->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, &waiting);
+ if (status < 0) {
+ Log::error("Failed to enqueue page flip: %d\n", status);
+ return;
+ }
+
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(fd_, &fds);
+ drmEventContext evCtx;
+ evCtx.version = DRM_EVENT_CONTEXT_VERSION;
+ evCtx.page_flip_handler = page_flip_handler;
+
+ while (waiting) {
+ status = select(fd_ + 1, &fds, 0, 0, 0);
+ if (status < 0) {
+ // Most of the time, select() will return an error because the
+ // user pressed Ctrl-C. So, only print out a message in debug
+ // mode, and just check for the likely condition and release
+ // the current buffer object before getting out.
+ Log::debug("Error in select\n");
+ if (should_quit()) {
+ gbm_surface_release_buffer(surface_, bo_);
+ bo_ = next;
+ }
+ return;
+ }
+ drmHandleEvent(fd_, &evCtx);
+ }
+
+ gbm_surface_release_buffer(surface_, bo_);
+ bo_ = next;
+}
+
+/*******************
+ * Private methods *
+ *******************/
+
+void
+NativeStateDRM::fb_destroy_callback(gbm_bo* bo, void* data)
+{
+ DRMFBState* fb = reinterpret_cast<DRMFBState*>(data);
+ if (fb && fb->fb_id) {
+ drmModeRmFB(fb->fd, fb->fb_id);
+ }
+ delete fb;
+ gbm_device* dev = gbm_bo_get_device(bo);
+ Log::debug("Got GBM device handle %p from buffer object\n", dev);
+}
+
+NativeStateDRM::DRMFBState*
+NativeStateDRM::fb_get_from_bo(gbm_bo* bo)
+{
+ DRMFBState* fb = reinterpret_cast<DRMFBState*>(gbm_bo_get_user_data(bo));
+ if (fb) {
+ return fb;
+ }
+
+ unsigned int width = gbm_bo_get_width(bo);
+ unsigned int height = gbm_bo_get_height(bo);
+ unsigned int stride = gbm_bo_get_stride(bo);
+ unsigned int handle = gbm_bo_get_handle(bo).u32;
+ unsigned int fb_id(0);
+ int status = drmModeAddFB(fd_, width, height, 24, 32, stride, handle, &fb_id);
+ if (status < 0) {
+ Log::error("Failed to create FB: %d\n", status);
+ return 0;
+ }
+
+ fb = new DRMFBState();
+ fb->fd = fd_;
+ fb->bo = bo;
+ fb->fb_id = fb_id;
+
+ gbm_bo_set_user_data(bo, fb, fb_destroy_callback);
+ return fb;
+}
+
+bool
+NativeStateDRM::init_gbm()
+{
+ dev_ = gbm_create_device(fd_);
+ if (!dev_) {
+ Log::error("Failed to create GBM device\n");
+ return false;
+ }
+
+ surface_ = gbm_surface_create(dev_, mode_->hdisplay, mode_->vdisplay,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ if (!surface_) {
+ Log::error("Failed to create GBM surface\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool
+NativeStateDRM::init()
+{
+ // TODO: Replace this with something that explicitly probes for the loaded
+ // driver (udev?).
+ static const char* drm_modules[] = {
+ "i915",
+ "nouveau",
+ "radeon",
+ "vmgfx",
+ "omapdrm",
+ "exynos"
+ };
+
+ unsigned int num_modules(sizeof(drm_modules)/sizeof(drm_modules[0]));
+ for (unsigned int m = 0; m < num_modules; m++) {
+ fd_ = drmOpen(drm_modules[m], 0);
+ if (fd_ < 0) {
+ Log::debug("Failed to open DRM module '%s'\n", drm_modules[m]);
+ continue;
+ }
+ Log::debug("Opened DRM module '%s'\n", drm_modules[m]);
+ break;
+ }
+
+ if (fd_ < 0) {
+ Log::error("Failed to find a suitable DRM device\n");
+ return false;
+ }
+
+ resources_ = drmModeGetResources(fd_);
+ if (!resources_) {
+ Log::error("drmModeGetResources failed\n");
+ return false;
+ }
+
+ // Find a connected connector
+ for (int c = 0; c < resources_->count_connectors; c++) {
+ connector_ = drmModeGetConnector(fd_, resources_->connectors[c]);
+ if (DRM_MODE_CONNECTED == connector_->connection) {
+ break;
+ }
+ drmModeFreeConnector(connector_);
+ connector_ = 0;
+ }
+
+ if (!connector_) {
+ Log::error("Failed to find a suitable connector\n");
+ return false;
+ }
+
+ // Find the best resolution (we will always operate full-screen).
+ unsigned int bestArea(0);
+ for (int m = 0; m < connector_->count_modes; m++) {
+ drmModeModeInfo* curMode = &connector_->modes[m];
+ unsigned int curArea = curMode->hdisplay * curMode->vdisplay;
+ if (curArea > bestArea) {
+ mode_ = curMode;
+ bestArea = curArea;
+ }
+ }
+
+ if (!mode_) {
+ Log::error("Failed to find a suitable mode\n");
+ return false;
+ }
+
+ // Find a suitable encoder
+ for (int e = 0; e < resources_->count_encoders; e++) {
+ encoder_ = drmModeGetEncoder(fd_, resources_->encoders[e]);
+ if (encoder_ && encoder_->encoder_id == connector_->encoder_id) {
+ break;
+ }
+ drmModeFreeEncoder(encoder_);
+ encoder_ = 0;
+ }
+
+ if (!encoder_) {
+ Log::error("Failed to find a suitable encoder\n");
+ return false;
+ }
+
+ if (!init_gbm()) {
+ return false;
+ }
+
+ crtc_ = drmModeGetCrtc(fd_, encoder_->crtc_id);
+ if (!crtc_) {
+ Log::error("Failed to get current CRTC\n");
+ return false;
+ }
+
+ signal(SIGINT, &NativeStateDRM::quit_handler);
+
+ return true;
+}
+
+bool NativeStateDRM::should_quit_ = false;
+
+void
+NativeStateDRM::quit_handler(int signo)
+{
+ Log::debug("Got SIGINT (%d).\n", signo);
+ should_quit_ = true;
+}
+
+void
+NativeStateDRM::page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void* data)
+{
+ unsigned int* waiting = reinterpret_cast<unsigned int*>(data);
+ *waiting = 0;
+ // Deal with unused parameters
+ static_cast<void>(fd);
+ static_cast<void>(frame);
+ static_cast<void>(sec);
+ static_cast<void>(usec);
+}
+
+void
+NativeStateDRM::cleanup()
+{
+ // Restore CRTC state if necessary
+ if (crtc_) {
+ int status = drmModeSetCrtc(fd_, crtc_->crtc_id, crtc_->buffer_id,
+ crtc_->x, crtc_->y, &connector_->connector_id,
+ 1, &crtc_->mode);
+ if (status < 0) {
+ Log::error("Failed to restore original CRTC: %d\n", status);
+ }
+ drmModeFreeCrtc(crtc_);
+ crtc_ = 0;
+ }
+ if (surface_) {
+ gbm_surface_destroy(surface_);
+ surface_ = 0;
+ }
+ if (dev_) {
+ gbm_device_destroy(dev_);
+ dev_ = 0;
+ }
+ if (connector_) {
+ drmModeFreeConnector(connector_);
+ connector_ = 0;
+ }
+ if (encoder_) {
+ drmModeFreeEncoder(encoder_);
+ encoder_ = 0;
+ }
+ if (resources_) {
+ drmModeFreeResources(resources_);
+ resources_ = 0;
+ }
+ if (fd_ > 0) {
+ drmClose(fd_);
+ }
+ fd_ = 0;
+ mode_ = 0;
+}
=== added file 'src/native-state-drm.h'
@@ -0,0 +1,91 @@
+/*
+ * Copyright Š 2012 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Simon Que
+ * Jesse Barker
+ * Alexandros Frantzis
+ */
+#ifndef GLMARK2_NATIVE_STATE_DRM_H_
+#define GLMARK2_NATIVE_STATE_DRM_H_
+
+#include "native-state.h"
+#include <cstring>
+#include <gbm.h>
+#include <drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+class NativeStateDRM : public NativeState
+{
+public:
+ NativeStateDRM() :
+ fd_(0),
+ resources_(0),
+ connector_(0),
+ encoder_(0),
+ mode_(0),
+ dev_(0),
+ surface_(0),
+ bo_(0),
+ fb_(0),
+ crtc_set_(false) {}
+ ~NativeStateDRM() { cleanup(); }
+
+ bool init_display();
+ void* display();
+ bool create_window(WindowProperties const& properties);
+ void* window(WindowProperties& properties);
+ void visible(bool v);
+ bool should_quit();
+ void flip();
+
+private:
+ struct DRMFBState
+ {
+ int fd;
+ gbm_bo* bo;
+ uint32_t fb_id;
+ };
+
+ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void* data);
+ static void fb_destroy_callback(gbm_bo* bo, void* data);
+ static void quit_handler(int signum);
+ static bool should_quit_;
+
+ DRMFBState* fb_get_from_bo(gbm_bo* bo);
+ bool init_gbm();
+ bool init();
+ void cleanup();
+
+ int fd_;
+ drmModeRes* resources_;
+ drmModeConnector* connector_;
+ drmModeEncoder* encoder_;
+ drmModeCrtcPtr crtc_;
+ drmModeModeInfo* mode_;
+ gbm_device* dev_;
+ gbm_surface* surface_;
+ gbm_bo* bo_;
+ DRMFBState* fb_;
+ bool crtc_set_;
+};
+
+#endif /* GLMARK2_NATIVE_STATE_DRM_H_ */
=== added file 'src/native-state-x11.cpp'
@@ -0,0 +1,205 @@
+/*
+ * Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alexandros Frantzis
+ */
+#include "native-state-x11.h"
+#include "log.h"
+
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+/******************
+ * Public methods *
+ ******************/
+
+NativeStateX11::~NativeStateX11()
+{
+ if (xdpy_)
+ {
+ if (xwin_)
+ XDestroyWindow(xdpy_, xwin_);
+
+ XCloseDisplay(xdpy_);
+ }
+}
+
+bool
+NativeStateX11::init_display()
+{
+ if (!xdpy_)
+ xdpy_ = XOpenDisplay(NULL);
+
+ return (xdpy_ != 0);
+}
+
+void*
+NativeStateX11::display()
+{
+ return (void*)xdpy_;
+}
+
+bool
+NativeStateX11::create_window(WindowProperties const& properties)
+{
+ static const char *win_name("glmark2 "GLMARK_VERSION);
+
+ if (!xdpy_) {
+ Log::error("Error: X11 Display has not been initialized!\n");
+ return false;
+ }
+
+ /* Recreate an existing window only if it has actually been resized */
+ if (xwin_) {
+ if (properties_.fullscreen != properties.fullscreen ||
+ (properties.fullscreen == false &&
+ (properties_.width != properties.width ||
+ properties_.height != properties.height)))
+ {
+ XDestroyWindow(xdpy_, xwin_);
+ xwin_ = 0;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ /* Set desired attributes */
+ properties_.fullscreen = properties.fullscreen;
+ properties_.visual_id = properties.visual_id;
+
+ if (properties_.fullscreen) {
+ /* Get the screen (root window) size */
+ XWindowAttributes window_attr;
+ XGetWindowAttributes(xdpy_, RootWindow(xdpy_, DefaultScreen(xdpy_)),
+ &window_attr);
+ properties_.width = window_attr.width;
+ properties_.height = window_attr.height;
+ }
+ else {
+ properties_.width = properties.width;
+ properties_.height = properties.height;
+ }
+
+ XVisualInfo vis_tmpl;
+ XVisualInfo *vis_info = 0;
+ int num_visuals;
+
+ /* The X window visual must match the supplied visual id */
+ vis_tmpl.visualid = properties_.visual_id;
+ vis_info = XGetVisualInfo(xdpy_, VisualIDMask, &vis_tmpl,
+ &num_visuals);
+ if (!vis_info) {
+ Log::error("Error: Could not get a valid XVisualInfo!\n");
+ return false;
+ }
+
+ Log::debug("Creating XWindow W: %d H: %d VisualID: 0x%x\n",
+ properties_.width, properties_.height, vis_info->visualid);
+
+ /* window attributes */
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root = RootWindow(xdpy_, DefaultScreen(xdpy_));
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(xdpy_, root, vis_info->visual, AllocNone);
+ attr.event_mask = KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ xwin_ = XCreateWindow(xdpy_, root, 0, 0, properties_.width, properties_.height,
+ 0, vis_info->depth, InputOutput,
+ vis_info->visual, mask, &attr);
+
+ XFree(vis_info);
+
+ if (!xwin_) {
+ Log::error("Error: XCreateWindow() failed!\n");
+ return false;
+ }
+
+ /* set hints and properties */
+ if (properties_.fullscreen) {
+ Atom atom = XInternAtom(xdpy_, "_NET_WM_STATE_FULLSCREEN", True);
+ XChangeProperty(xdpy_, xwin_,
+ XInternAtom(xdpy_, "_NET_WM_STATE", True),
+ XA_ATOM, 32, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&atom), 1);
+ }
+ else {
+ XSizeHints sizehints;
+ sizehints.min_width = properties_.width;
+ sizehints.min_height = properties_.height;
+ sizehints.max_width = properties_.width;
+ sizehints.max_height = properties_.height;
+ sizehints.flags = PMaxSize | PMinSize;
+
+ XSetWMProperties(xdpy_, xwin_, NULL, NULL,
+ NULL, 0, &sizehints, NULL, NULL);
+ }
+
+ /* Set the window name */
+ XStoreName(xdpy_ , xwin_, win_name);
+
+ /* Gracefully handle Window Delete event from window manager */
+ Atom wmDelete = XInternAtom(xdpy_, "WM_DELETE_WINDOW", True);
+ XSetWMProtocols(xdpy_, xwin_, &wmDelete, 1);
+
+ return true;
+}
+
+void*
+NativeStateX11::window(WindowProperties& properties)
+{
+ properties = properties_;
+ return (void*)xwin_;
+}
+
+void
+NativeStateX11::visible(bool visible)
+{
+ if (visible)
+ XMapWindow(xdpy_, xwin_);
+}
+
+bool
+NativeStateX11::should_quit()
+{
+ XEvent event;
+
+ if (!XPending(xdpy_))
+ return false;
+
+ XNextEvent(xdpy_, &event);
+
+ if (event.type == KeyPress) {
+ if (XLookupKeysym(&event.xkey, 0) == XK_Escape)
+ return true;
+ }
+ else if (event.type == ClientMessage) {
+ /* Window Delete event from window manager */
+ return true;
+ }
+
+ return false;
+}
=== renamed file 'src/canvas-x11-egl.h' => 'src/native-state-x11.h'
@@ -1,5 +1,6 @@
/*
* Copyright Š 2010-2011 Linaro Limited
+ * Copyright Š 2013 Canonical Ltd
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
@@ -17,36 +18,34 @@
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
- * Alexandros Frantzis (glmark2)
- * Jesse Barker
- */
-#ifndef GLMARK2_CANVAS_X11_EGL_H_
-#define GLMARK2_CANVAS_X11_EGL_H_
-
-#include "canvas-x11.h"
-#include "egl-state.h"
-
-/**
- * Canvas for rendering to an X11 window using EGL.
- */
-class CanvasX11EGL : public CanvasX11
+ * Alexandros Frantzis
+ */
+#ifndef GLMARK2_NATIVE_STATE_X11_H_
+#define GLMARK2_NATIVE_STATE_X11_H_
+
+#include "native-state.h"
+#include <X11/Xlib.h>
+
+class NativeStateX11 : public NativeState
{
public:
- CanvasX11EGL(int width, int height) :
- CanvasX11(width, height) {}
- ~CanvasX11EGL() {}
+ NativeStateX11() : xdpy_(0), xwin_(0), properties_() {}
+ ~NativeStateX11();
-protected:
- XVisualInfo *get_xvisualinfo();
- bool make_current();
- bool reset_context();
- void swap_buffers();
- void get_glvisualconfig(GLVisualConfig &visual_config);
- bool init_gl_winsys();
+ bool init_display();
+ void* display();
+ bool create_window(WindowProperties const& properties);
+ void* window(WindowProperties& properties);
+ void visible(bool v);
+ bool should_quit();
+ void flip() { }
private:
- void init_gl_extensions();
- EGLState egl_;
+ /** The X display associated with this canvas. */
+ Display* xdpy_;
+ /** The X window associated with this canvas. */
+ Window xwin_;
+ WindowProperties properties_;
};
-#endif
+#endif /* GLMARK2_NATIVE_STATE_X11_H_ */
=== added file 'src/native-state.h'
@@ -0,0 +1,68 @@
+/*
+ * Copyright Š 2013 Canonical Ltd
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Alexandros Frantzis
+ */
+#ifndef GLMARK2_NATIVE_STATE_H_
+#define GLMARK2_NATIVE_STATE_H_
+
+class NativeState
+{
+public:
+ struct WindowProperties
+ {
+ WindowProperties(int w, int h, bool f, int v)
+ : width(w), height(h), fullscreen(f), visual_id(v) {}
+ WindowProperties()
+ : width(0), height(0), fullscreen(false), visual_id(0) {}
+
+ int width;
+ int height;
+ bool fullscreen;
+ int visual_id;
+ };
+
+ virtual ~NativeState() {}
+
+ /* Initializes the native display */
+ virtual bool init_display() = 0;
+
+ /* Gets the native display */
+ virtual void* display() = 0;
+
+ /* Creates (or recreates) the native window */
+ virtual bool create_window(WindowProperties const& properties) = 0;
+
+ /*
+ * Gets the native window and its properties.
+ * The dimensions may be different than the ones requested.
+ */
+ virtual void* window(WindowProperties& properties) = 0;
+
+ /* Sets the visibility of the native window */
+ virtual void visible(bool v) = 0;
+
+ /* Whether the user has requested an exit */
+ virtual bool should_quit() = 0;
+
+ /* Flips the display */
+ virtual void flip() = 0;
+};
+
+#endif /* GLMARK2_NATIVE_STATE_H_ */
=== modified file 'src/wscript_build'
@@ -1,11 +1,12 @@
all_sources = bld.path.ant_glob('*.cpp scene-ideas/*.cc scene-terrain/*.cpp')
common_sources = [f for f in all_sources if f.name.find('canvas-') == -1 and
f.name.find('android') == -1 and
- f.name.find('egl-') == -1]
-gl_sources = ['canvas-x11.cpp', 'canvas-x11-glx.cpp']
-glesv2_sources = ['canvas-x11.cpp', 'canvas-x11-egl.cpp', 'egl-state.cpp']
-gl_drm_sources = ['canvas-drm.cpp', 'egl-state.cpp']
-glesv2_drm_sources = ['canvas-drm.cpp', 'egl-state.cpp']
+ f.name.find('native-state-') == -1 and
+ f.name.find('gl-state-') == -1]
+gl_sources = ['canvas-generic.cpp', 'native-state-x11.cpp', 'gl-state-glx.cpp']
+glesv2_sources = ['canvas-generic.cpp', 'native-state-x11.cpp', 'gl-state-egl.cpp']
+gl_drm_sources = ['canvas-generic.cpp', 'native-state-drm.cpp', 'gl-state-egl.cpp']
+glesv2_drm_sources = ['canvas-generic.cpp', 'native-state-drm.cpp', 'gl-state-egl.cpp']
libmatrix_sources = [f for f in bld.path.ant_glob('libmatrix/*.cc')
if not f.name.endswith('test.cc')]
includes = ['.', 'scene-ideas', 'scene-terrain']