From patchwork Mon Mar 4 19:06:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 15222 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 6C03323E00 for ; Mon, 4 Mar 2013 19:15:54 +0000 (UTC) Received: from mail-ve0-f177.google.com (mail-ve0-f177.google.com [209.85.128.177]) by fiordland.canonical.com (Postfix) with ESMTP id CC769A19ACC for ; Mon, 4 Mar 2013 19:15:52 +0000 (UTC) Received: by mail-ve0-f177.google.com with SMTP id m1so4975693ves.8 for ; Mon, 04 Mar 2013 11:15:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:content-type:mime-version:x-launchpad-project :x-launchpad-branch:x-launchpad-message-rationale :x-launchpad-branch-revision-number:x-launchpad-notification-type:to :from:subject:message-id:date:reply-to:sender:errors-to:precedence :x-generated-by:x-launchpad-hash:x-gm-message-state; bh=z65MfcldKhk6VnAIGvX597sO9I3peS24MPMuVHMZnYo=; b=BOnqhHj+TUUAglXiaJBRRjeR6bF5K2A9M5i4e0DxI30Tg1TFBp10tTYzdeTO6z3PGs BpniDhaRxSFVWFKShHsi6puhwKEC10AGi35CbLfNoQu/1yZTjIeRBdfChdGFMfT1dd5x LW8dWUCypuTZlrDtAR0X13kTlvxRWZMhq61jrtrktqc16nBekN3s+vpQ2Lf+F4BqgUA5 8wkM8WkQZhSqCADuXRID1SnXWyenDpvOrlfV0jNQKtzLXHpZ9paaKHqYS867n8l+Zntb xJf8frtS+beEKPA/ZjM9MEBTDExrZq5bMojueVyZgJHqkLpCsslm15Z6EoUv4ZFdwjSF IZuw== X-Received: by 10.52.177.163 with SMTP id cr3mr7269219vdc.94.1362424552258; Mon, 04 Mar 2013 11:15:52 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.127.98 with SMTP id nf2csp74148veb; Mon, 4 Mar 2013 11:15:50 -0800 (PST) X-Received: by 10.194.6.2 with SMTP id w2mr34260860wjw.10.1362424549814; Mon, 04 Mar 2013 11:15:49 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id m8si9568318wje.256.2013.03.04.11.15.49 (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 04 Mar 2013 11:15:49 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1UCarT-0003Cu-IJ for ; Mon, 04 Mar 2013 19:15:47 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 94AE0E031E for ; Mon, 4 Mar 2013 19:06:13 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 261 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 261: CanvasGeneric: Replace custom Canvases with a customizable generic Canvas Message-Id: <20130304190613.27026.16499.launchpad@ackee.canonical.com> Date: Mon, 04 Mar 2013 19:06:13 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="16514"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 25a87d3da7b131c44906dc83758991638379d987 X-Gm-Message-State: ALoCoQlEu2vCPQ1hMpiqC06hXUxrFjcrzRyg2AL42NiHfxtOGByt30l1yWFrulXW3nzyiaaRzx5/ Merge authors: Alexandros Frantzis (afrantzis) Related merge proposals: https://code.launchpad.net/~glmark2-dev/glmark2/canvas-generic/+merge/151271 proposed by: Alexandros Frantzis (afrantzis) review: Approve - Jesse Barker (jesse-barker) ------------------------------------------------------------ revno: 261 [merge] committer: Alexandros Frantzis branch nick: trunk timestamp: Mon 2013-03-04 21:02:58 +0200 message: CanvasGeneric: Replace custom Canvases with a customizable generic Canvas The generic Canvas is customized by initializing it with a NativeState (X11,DRM...) and a GLState (EGL,GLX). This separation of concerns makes it easier to support new display systems. removed: src/canvas-drm.cpp src/canvas-drm.h src/canvas-x11-egl.cpp src/canvas-x11.cpp src/canvas-x11.h added: src/canvas-generic.cpp src/canvas-generic.h src/gl-state.h src/native-state-drm.cpp src/native-state-drm.h src/native-state-x11.cpp src/native-state.h renamed: src/canvas-x11-egl.h => src/native-state-x11.h src/canvas-x11-glx.cpp => src/gl-state-glx.cpp src/canvas-x11-glx.h => src/gl-state-glx.h src/egl-state.cpp => src/gl-state-egl.cpp src/egl-state.h => src/gl-state-egl.h modified: android/jni/Android.mk android/jni/Android.ndk.mk src/main.cpp src/wscript_build src/native-state-x11.h src/gl-state-glx.cpp src/gl-state-glx.h src/gl-state-egl.cpp src/gl-state-egl.h --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === modified file 'android/jni/Android.mk' --- android/jni/Android.mk 2012-12-18 19:44:34 +0000 +++ android/jni/Android.mk 2013-03-01 15:22:03 +0000 @@ -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' --- android/jni/Android.ndk.mk 2012-12-18 19:44:34 +0000 +++ android/jni/Android.ndk.mk 2013-03-01 15:22:03 +0000 @@ -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' --- src/canvas-drm.cpp 2012-12-17 22:48:52 +0000 +++ src/canvas-drm.cpp 1970-01-01 00:00:00 +0000 @@ -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 . -// -// Authors: -// Simon Que -// Jesse Barker -// -#include "canvas-drm.h" -#include "log.h" -#include "options.h" -#include "util.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -/****************** - * 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(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(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(data); - *waiting = 0; - // Deal with unused parameters - static_cast(fd); - static_cast(frame); - static_cast(sec); - static_cast(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(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( - 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(glGetString(GL_EXTENSIONS)); - if (exts) - extString = exts; - - if (extString.find("GL_OES_mapbuffer") != std::string::npos) { - GLExtensions::MapBuffer = reinterpret_cast( - eglGetProcAddress("glMapBufferOES")); - GLExtensions::UnmapBuffer = reinterpret_cast( - 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(height_), - 1.0, 1024.0); -} === removed file 'src/canvas-drm.h' --- src/canvas-drm.h 2012-12-17 19:11:54 +0000 +++ src/canvas-drm.h 1970-01-01 00:00:00 +0000 @@ -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 . -// -// Authors: -// Simon Que -// Jesse Barker -// -#ifndef GLMARK2_CANVAS_DRM_H_ -#define GLMARK2_CANVAS_DRM_H_ - -#include -#include -#include -#include -#include - -#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' --- src/canvas-generic.cpp 1970-01-01 00:00:00 +0000 +++ src/canvas-generic.cpp 2013-03-01 14:48:21 +0000 @@ -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 . + * + * 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 +#include + +/****************** + * 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(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( + 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(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' --- src/canvas-generic.h 1970-01-01 00:00:00 +0000 +++ src/canvas-generic.h 2013-03-01 14:48:21 +0000 @@ -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 . + * + * 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' --- src/canvas-x11-egl.cpp 2012-12-12 19:45:49 +0000 +++ src/canvas-x11-egl.cpp 1970-01-01 00:00:00 +0000 @@ -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 . - * - * Authors: - * Alexandros Frantzis (glmark2) - */ -#include "canvas-x11-egl.h" -#include "log.h" -#include "options.h" - -#include -#include -#include - -/********************* - * 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(eglGetProcAddress("glMapBufferOES")); - GLExtensions::UnmapBuffer = - reinterpret_cast(eglGetProcAddress("glUnmapBufferOES")); - } -#elif USE_GL - GLExtensions::MapBuffer = glMapBuffer; - GLExtensions::UnmapBuffer = glUnmapBuffer; -#endif -} === removed file 'src/canvas-x11.cpp' --- src/canvas-x11.cpp 2012-11-13 16:56:32 +0000 +++ src/canvas-x11.cpp 1970-01-01 00:00:00 +0000 @@ -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 . - * - * Authors: - * Alexandros Frantzis (glmark2) - * Jesse Barker - */ -#include "canvas-x11.h" -#include "log.h" -#include "options.h" -#include "util.h" - -#include -#include -#include -#include - -/****************** - * 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(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( - 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(&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(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' --- src/canvas-x11.h 2012-11-13 16:56:32 +0000 +++ src/canvas-x11.h 1970-01-01 00:00:00 +0000 @@ -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 . - * - * Authors: - * Alexandros Frantzis (glmark2) - */ -#ifndef GLMARK2_CANVAS_X11_H_ -#define GLMARK2_CANVAS_X11_H_ - -#include "canvas.h" -#include -#include - -/** - * 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' --- src/egl-state.cpp 2012-12-05 23:50:25 +0000 +++ src/gl-state-egl.cpp 2013-03-03 10:18:39 +0000 @@ -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 #include 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(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(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(eglGetProcAddress("glMapBufferOES")); + GLExtensions::UnmapBuffer = + reinterpret_cast(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& configs) +GLStateEGL::select_best_config(std::vector& 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' --- src/egl-state.h 2012-12-05 22:19:12 +0000 +++ src/gl-state-egl.h 2013-03-01 14:58:03 +0000 @@ -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 #include +#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& 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' --- src/canvas-x11-glx.cpp 2012-12-06 17:54:57 +0000 +++ src/gl-state-glx.cpp 2013-03-03 10:18:39 +0000 @@ -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 . * * Authors: - * Alexandros Frantzis (glmark2) + * Alexandros Frantzis */ -#include "canvas-x11-glx.h" +#include "gl-state-glx.h" #include "log.h" #include "options.h" -#include #include -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(native_display); + requested_visual_config_ = visual_config; + + return (xdpy_ != 0); +} + +bool +GLStateGLX::init_surface(void* native_window) +{ + xwin_ = reinterpret_cast(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 configs) +GLStateGLX::select_best_config(std::vector 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' --- src/canvas-x11-glx.h 2012-11-13 16:56:32 +0000 +++ src/gl-state-glx.h 2013-03-01 14:58:03 +0000 @@ -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 . * * 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 + +#include #define GLX_GLXEXT_PROTOTYPES #include #include -#include -/** - * 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 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' --- src/gl-state.h 1970-01-01 00:00:00 +0000 +++ src/gl-state.h 2013-03-01 14:58:03 +0000 @@ -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 . + * + * 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' --- src/main.cpp 2012-12-18 15:42:46 +0000 +++ src/main.cpp 2013-03-01 14:57:51 +0000 @@ -35,12 +35,17 @@ #include #include +#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' --- src/native-state-drm.cpp 1970-01-01 00:00:00 +0000 +++ src/native-state-drm.cpp 2013-03-04 18:52:20 +0000 @@ -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 . + * + * Authors: + * Simon Que + * Jesse Barker + * Alexandros Frantzis + */ +#include "native-state-drm.h" +#include "log.h" +#include + +/****************** + * 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(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(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(data); + *waiting = 0; + // Deal with unused parameters + static_cast(fd); + static_cast(frame); + static_cast(sec); + static_cast(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' --- src/native-state-drm.h 1970-01-01 00:00:00 +0000 +++ src/native-state-drm.h 2013-03-04 18:52:20 +0000 @@ -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 . + * + * Authors: + * Simon Que + * Jesse Barker + * Alexandros Frantzis + */ +#ifndef GLMARK2_NATIVE_STATE_DRM_H_ +#define GLMARK2_NATIVE_STATE_DRM_H_ + +#include "native-state.h" +#include +#include +#include +#include +#include + +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' --- src/native-state-x11.cpp 1970-01-01 00:00:00 +0000 +++ src/native-state-x11.cpp 2013-03-01 14:48:17 +0000 @@ -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 . + * + * Authors: + * Alexandros Frantzis + */ +#include "native-state-x11.h" +#include "log.h" + +#include +#include +#include + +/****************** + * 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(&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' --- src/canvas-x11-egl.h 2012-11-13 16:56:32 +0000 +++ src/native-state-x11.h 2013-03-01 14:48:17 +0000 @@ -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 . * * 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 + +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' --- src/native-state.h 1970-01-01 00:00:00 +0000 +++ src/native-state.h 2013-03-01 14:48:17 +0000 @@ -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 . + * + * 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' --- src/wscript_build 2012-12-06 21:29:19 +0000 +++ src/wscript_build 2013-03-01 14:57:51 +0000 @@ -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']