From patchwork Tue Dec 18 15:45:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jesse Barker X-Patchwork-Id: 13642 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 47D8023E2A for ; Tue, 18 Dec 2012 15:45:24 +0000 (UTC) Received: from mail-ie0-f176.google.com (mail-ie0-f176.google.com [209.85.223.176]) by fiordland.canonical.com (Postfix) with ESMTP id A2896A19BD5 for ; Tue, 18 Dec 2012 15:45:23 +0000 (UTC) Received: by mail-ie0-f176.google.com with SMTP id 13so1062828iea.21 for ; Tue, 18 Dec 2012 07:45:23 -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=kX0NaHWC1GH5NlA5TBjJt9VorseCmcJDmaHbZs/9Rzo=; b=G9lxkasBbl3xz6Tnly4YlyNTh+fr76eOnc2WxLetr6nOc3BcLiFRxaejIJZqgVzfux j88MX6BZ6SGKTxD5SWAaXKdCeuAJGH6MCTQYbv37qLDXW5cg376I4XT0uphDFJORceNf 3QsanrsGKVirByCJZXWARndTkyz6ylpj3d+JGxw2iF3ZlAPPyZJcEVZ+iuqPxDegwOfN K8v/s1oO25mRxOT6JS+L8yoKo+VqQSg1lpTZ68JBHCPk0CSv+i2JX4TmljXouR9Q+rvW ZAWRIJsCUtppc6lJDH66kFWJ7xqV2TAjEFvlTJH3jecHQQxP9XDI9V2AyeupnaYdbYYR WQeA== X-Received: by 10.50.91.195 with SMTP id cg3mr3304225igb.57.1355845523043; Tue, 18 Dec 2012 07:45:23 -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.50.67.148 with SMTP id n20csp150210igt; Tue, 18 Dec 2012 07:45:22 -0800 (PST) X-Received: by 10.194.7.104 with SMTP id i8mr5368900wja.27.1355845521492; Tue, 18 Dec 2012 07:45:21 -0800 (PST) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id uk5si3059613wjc.38.2012.12.18.07.45.20 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 18 Dec 2012 07:45:21 -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 1TkzM6-0005YF-A9 for ; Tue, 18 Dec 2012 15:45:18 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 24A99E0288 for ; Tue, 18 Dec 2012 15:45:18 +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: 257 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 257: Merge of lp:~glmark2-dev/glmark2/canvas-drm-rebranch Message-Id: <20121218154518.12819.83747.launchpad@ackee.canonical.com> Date: Tue, 18 Dec 2012 15:45:18 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="16372"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 80cc41eb0cec10b4556695bf61a878624a242f4c X-Gm-Message-State: ALoCoQn4VNB1saERqJkFACSZ+j9oH7WJZaK5qmuH2EQlSU4dih4whZjoNlRDRyw5/68cGWnDfKCB Merge authors: Jesse Barker (jesse-barker) Related merge proposals: https://code.launchpad.net/~glmark2-dev/glmark2/canvas-drm-rebranch/+merge/138605 proposed by: Jesse Barker (jesse-barker) review: Approve - Alexandros Frantzis (afrantzis) review: Resubmit - Jesse Barker (jesse-barker) ------------------------------------------------------------ revno: 257 [merge] committer: Jesse Barker branch nick: trunk timestamp: Tue 2012-12-18 07:42:46 -0800 message: Merge of lp:~glmark2-dev/glmark2/canvas-drm-rebranch Adds CanvasDRM, which uses GBM and KMS APIs to manage surfaces and modesetting, respectively. Allows glmark2 to run on a console and take over the framebuffer directly (no window/display manager). added: src/canvas-drm.cpp src/canvas-drm.h modified: INSTALL src/main.cpp src/wscript_build wscript --- 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 'INSTALL' --- INSTALL 2011-01-25 15:07:17 +0000 +++ INSTALL 2012-12-06 21:29:19 +0000 @@ -2,7 +2,7 @@ To configure glmark2 use: -$ ./waf configure [--enable-gl --enable-glesv2 --data-path=DATA_PATH --prefix=PREFIX] +$ ./waf configure [--enable-gl --enable-glesv2 --enable-gl-drm --enable-glesv2-drm --data-path=DATA_PATH --prefix=PREFIX] To build use: === added file 'src/canvas-drm.cpp' --- src/canvas-drm.cpp 1970-01-01 00:00:00 +0000 +++ src/canvas-drm.cpp 2012-12-17 22:48:52 +0000 @@ -0,0 +1,587 @@ +// +// 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); +} === added file 'src/canvas-drm.h' --- src/canvas-drm.h 1970-01-01 00:00:00 +0000 +++ src/canvas-drm.h 2012-12-17 19:11:54 +0000 @@ -0,0 +1,132 @@ +// +// 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 === modified file 'src/main.cpp' --- src/main.cpp 2012-12-07 19:57:44 +0000 +++ src/main.cpp 2012-12-18 15:42:46 +0000 @@ -35,7 +35,9 @@ #include #include -#if USE_GL +#if USE_DRM +#include "canvas-drm.h" +#elif USE_GL #include "canvas-x11-glx.h" #elif USE_GLESv2 #include "canvas-x11-egl.h" @@ -180,7 +182,9 @@ } // Create the canvas -#if USE_GL +#if USE_DRM + CanvasDRM canvas(Options::size.first, Options::size.second); +#elif USE_GL CanvasX11GLX canvas(Options::size.first, Options::size.second); #elif USE_GLESv2 CanvasX11EGL canvas(Options::size.first, Options::size.second); === modified file 'src/wscript_build' --- src/wscript_build 2012-11-13 16:53:41 +0000 +++ src/wscript_build 2012-12-06 21:29:19 +0000 @@ -4,6 +4,8 @@ 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'] libmatrix_sources = [f for f in bld.path.ant_glob('libmatrix/*.cc') if not f.name.endswith('test.cc')] includes = ['.', 'scene-ideas', 'scene-terrain'] @@ -47,3 +49,44 @@ includes = includes, defines = ['USE_GLESv2', 'USE_EXCEPTIONS'] ) + +if bld.env.USE_GL_DRM: + bld( + features = ['cxx', 'cxxstlib'], + source = libmatrix_sources, + target = 'matrix-drm', + lib = ['m'], + includes = ['.'], + export_includes = 'libmatrix', + defines = ['USE_DRM', '__GBM__', 'USE_GL', 'USE_EXCEPTIONS'] + ) + bld( + features = ['cxx', 'cprogram'], + source = common_sources + gl_drm_sources, + target = 'glmark2-drm', + use = ['egl', 'gl', 'matrix-drm', 'libpng12', 'drm', 'gbm'], + lib = ['m', 'jpeg', 'dl'], + includes = includes, + defines = ['USE_DRM', '__GBM__', 'USE_GL'] + ) + +if bld.env.USE_GLESv2_DRM: + bld( + features = ['cxx', 'cxxstlib'], + source = libmatrix_sources, + target = 'matrix-es2-drm', + lib = ['m'], + includes = ['.'], + export_includes = 'libmatrix', + defines = ['USE_DRM', '__GBM__', 'USE_GLESv2', 'USE_EXCEPTIONS'] + ) + bld( + features = ['cxx', 'cprogram'], + source = common_sources + glesv2_drm_sources, + target = 'glmark2-es2-drm', + use = ['egl', 'glesv2', 'matrix-es2-drm', 'libpng12', 'drm', + 'gbm'], + lib = ['m', 'jpeg', 'dl'], + includes = includes, + defines = ['USE_DRM', '__GBM__', 'USE_GLESv2'] + ) === modified file 'wscript' --- wscript 2012-11-26 19:29:33 +0000 +++ wscript 2012-12-06 21:29:19 +0000 @@ -20,6 +20,11 @@ default = False, help='build using OpenGL 2.0') opt.add_option('--enable-glesv2', action='store_true', dest = 'glesv2', default = False, help='build using OpenGL ES 2.0') + opt.add_option('--enable-gl-drm', action='store_true', dest = 'gl_drm', + default = False, help='build using OpenGL 2.0 without X') + opt.add_option('--enable-glesv2-drm', action='store_true', + dest = 'glesv2_drm', + default = False, help='build using OpenGL ES 2.0 without X') opt.add_option('--no-debug', action='store_false', dest = 'debug', default = True, help='disable compiler debug information') opt.add_option('--no-opt', action='store_false', dest = 'opt', @@ -30,8 +35,10 @@ help='path to additional data (models, shaders, textures)') def configure(ctx): - if not Options.options.gl and not Options.options.glesv2: - ctx.fatal("You must configure using at least one of --enable-gl, --enable-glesv2") + if not Options.options.gl and not Options.options.glesv2 and \ + not Options.options.gl_drm and not Options.options.glesv2_drm: + ctx.fatal("You must configure using at least one of --enable-gl, " + + "--enable-glesv2, --enable-gl-drm, --enable-glesv2-drm") ctx.check_tool('gnu_dirs') ctx.check_tool('compiler_cc') @@ -54,15 +61,22 @@ uselib = uselib, mandatory = True) # Check required packages - req_pkgs = [('x11', 'x11'), ('libpng12', 'libpng12')] + req_pkgs = [('libpng12', 'libpng12')] for (pkg, uselib) in req_pkgs: ctx.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs', mandatory = True) # Check optional packages - opt_pkgs = [('gl', 'gl', Options.options.gl), - ('egl', 'egl', Options.options.glesv2), - ('glesv2', 'glesv2', Options.options.glesv2)] + opt_pkgs = [('x11', 'x11', Options.options.gl or Options.options.glesv2), + ('gl', 'gl', Options.options.gl or Options.options.gl_drm), + ('egl', 'egl', Options.options.glesv2 or + Options.options.glesv2_drm), + ('glesv2', 'glesv2', Options.options.glesv2 or + Options.options.glesv2_drm), + ('libdrm','drm', Options.options.gl_drm or + Options.options.glesv2_drm), + ('gbm','gbm', Options.options.gl_drm or + Options.options.glesv2_drm)] for (pkg, uselib, mandatory) in opt_pkgs: ctx.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs', mandatory = mandatory) @@ -94,6 +108,8 @@ ctx.env.USE_GL = Options.options.gl ctx.env.USE_GLESv2 = Options.options.glesv2 + ctx.env.USE_GL_DRM = Options.options.gl_drm + ctx.env.USE_GLESv2_DRM = Options.options.glesv2_drm ctx.msg("Prefix", ctx.env.PREFIX, color = 'PINK') ctx.msg("Data path", data_path, color = 'PINK') @@ -101,9 +117,13 @@ color = 'PINK'); if ctx.env.HAVE_EXTRAS: ctx.msg("Extras path", Options.options.extras_path, color = 'PINK') - ctx.msg("Building GL2 version", "Yes" if ctx.env.USE_GL else "No", - color = 'PINK') - ctx.msg("Building GLESv2 version", "Yes" if ctx.env.USE_GLESv2 else "No", + ctx.msg("Building X11 GL2 version", "Yes" if ctx.env.USE_GL else "No", + color = 'PINK') + ctx.msg("Building X11 GLESv2 version", "Yes" if ctx.env.USE_GLESv2 else "No", + color = 'PINK') + ctx.msg("Building DRM GL2 version", "Yes" if ctx.env.USE_GL_DRM else "No", + color = 'PINK') + ctx.msg("Building DRM GLESv2 version", "Yes" if ctx.env.USE_GLESv2_DRM else "No", color = 'PINK') def build(ctx):