<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file implements the ViewGLContext and PbufferGLContext classes.

#include <dlfcn.h>
#include <GL/glew.h>
#include <GL/glxew.h>
#include <GL/glx.h>
#include <GL/osmew.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "app/x11_util.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "app/gfx/gl/gl_context.h"
#include "app/gfx/gl/gl_context_osmesa.h"

namespace gfx {

typedef GLXContext GLContextHandle;
typedef GLXPbuffer PbufferHandle;

// This class is a wrapper around a GL context that renders directly to a
// window.
class ViewGLContext : public GLContext {
 public:
  explicit ViewGLContext(gfx::PluginWindowHandle window)
      : window_(window),
        context_(NULL) {
    DCHECK(window);
  }

  // Initializes the GL context.
  bool Initialize(bool multisampled);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  gfx::PluginWindowHandle window_;
  GLContextHandle context_;

  DISALLOW_COPY_AND_ASSIGN(ViewGLContext);
};

// This class is a wrapper around a GL context used for offscreen rendering.
// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful
// rendering.
class PbufferGLContext : public GLContext {
 public:
  explicit PbufferGLContext()
      : context_(NULL),
        pbuffer_(0) {
  }

  // Initializes the GL context.
  bool Initialize(void* shared_handle);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  GLContextHandle context_;
  PbufferHandle pbuffer_;

  DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
};

// Backup context if Pbuffers (GLX 1.3) aren't supported. May run slower...
class PixmapGLContext : public GLContext {
 public:
  explicit PixmapGLContext()
      : context_(NULL),
        pixmap_(0),
        glx_pixmap_(0) {
  }

  // Initializes the GL context.
  bool Initialize(void* shared_handle);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  GLContextHandle context_;
  Pixmap pixmap_;
  GLXPixmap glx_pixmap_;

  DISALLOW_COPY_AND_ASSIGN(PixmapGLContext);
};

// scoped_ptr functor for XFree(). Use as follows:
//   scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
// where "XVisualInfo" is any X type that is freed with XFree.
class ScopedPtrXFree {
 public:
  void operator()(void* x) const {
    ::XFree(x);
  }
};

// Some versions of NVIDIA's GL libGL.so include a broken version of
// dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically
// load it, and use glew to dynamically resolve symbols.
// See http://code.google.com/p/chromium/issues/detail?id=16800

static bool InitializeOneOff() {
  static bool initialized = false;
  if (initialized)
    return true;

  osmewInit();
  if (!OSMesaCreateContext) {
    void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
    if (!handle) {
      LOG(ERROR) << "Could not find libGL.so.1";
      return false;
    }

    // Initializes context-independent parts of GLEW
    if (glxewInit() != GLEW_OK) {
      LOG(ERROR) << "glxewInit failed";
      return false;
    }
    // glxewContextInit really only needs a display connection to
    // complete, and we don't want to have to create an OpenGL context
    // just to get access to GLX 1.3 entry points to create pbuffers.
    // We therefore added a glxewContextInitWithDisplay entry point.
    Display* display = x11_util::GetXDisplay();
    if (glxewContextInitWithDisplay(display) != GLEW_OK) {
      LOG(ERROR) << "glxewContextInit failed";
      return false;
    }
  }

  initialized = true;
  return true;
}

bool ViewGLContext::Initialize(bool multisampled) {
  if (multisampled) {
    LOG(WARNING) << "Multisampling not implemented.";
  }

  Display* display = x11_util::GetXDisplay();
  XWindowAttributes attributes;
  XGetWindowAttributes(display, window_, &attributes);
  XVisualInfo visual_info_template;
  visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
  int visual_info_count = 0;
  scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
      XGetVisualInfo(display, VisualIDMask,
                     &visual_info_template,
                     &visual_info_count));
  DCHECK(visual_info_list.get());
  DCHECK_GT(visual_info_count, 0);
  context_ = NULL;
  for (int i = 0; i < visual_info_count; ++i) {
    context_ = glXCreateContext(display, visual_info_list.get() + i, 0, True);
    if (context_)
      break;
  }
  if (!context_) {
    LOG(ERROR) << "Couldn't create GL context.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void ViewGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);

  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }
}

bool ViewGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }

  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, window_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = 0;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool ViewGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == window_ &&
      glXGetCurrentContext() == context_;
}

bool ViewGLContext::IsOffscreen() {
  return false;
}

void ViewGLContext::SwapBuffers() {
  Display* display = x11_util::GetXDisplay();
  glXSwapBuffers(display, window_);
}

gfx::Size ViewGLContext::GetSize() {
  XWindowAttributes attributes;
  Display* display = x11_util::GetXDisplay();
  XGetWindowAttributes(display, window_, &attributes);
  return gfx::Size(attributes.width, attributes.height);
}

void* ViewGLContext::GetHandle() {
  return context_;
}

GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
                                          bool multisampled) {
  if (!InitializeOneOff())
    return NULL;

  if (OSMesaCreateContext) {
    // TODO(apatrick): Support OSMesa rendering to a window on Linux.
    NOTREACHED() << "OSMesa rendering to a window is not yet implemented.";
    return NULL;
  } else {
    scoped_ptr<ViewGLContext> context(new ViewGLContext(window));

    if (!context->Initialize(multisampled))
      return NULL;

    return context.release();
  }
}

bool PbufferGLContext::Initialize(void* shared_handle) {
  if (!glXChooseFBConfig ||
      !glXCreateNewContext ||
      !glXCreatePbuffer ||
      !glXDestroyPbuffer) {
    LOG(ERROR) << "Pbuffer support not available.";
    return false;
  }

  static const int config_attributes[] = {
    GLX_DRAWABLE_TYPE,
    GLX_PBUFFER_BIT,
    GLX_RENDER_TYPE,
    GLX_RGBA_BIT,
    GLX_DOUBLEBUFFER,
    0,
    0
  };

  Display* display = x11_util::GetXDisplay();

  int nelements = 0;
  // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
  scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
      glXChooseFBConfig(display, 0, config_attributes, &nelements));
  if (!config.get()) {
    LOG(ERROR) << "glXChooseFBConfig failed.";
    return false;
  }
  if (!nelements) {
    LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
    return false;
  }
  context_ = glXCreateNewContext(display,
                                 config.get()[0],
                                 GLX_RGBA_TYPE,
                                 static_cast<GLContextHandle>(shared_handle),
                                 True);
  if (!context_) {
    LOG(ERROR) << "glXCreateNewContext failed.";
    return false;
  }
  static const int pbuffer_attributes[] = {
    GLX_PBUFFER_WIDTH,
    1,
    GLX_PBUFFER_HEIGHT,
    1,
    0
  };
  pbuffer_ = glXCreatePbuffer(display,
                              config.get()[0], pbuffer_attributes);
  if (!pbuffer_) {
    Destroy();
    LOG(ERROR) << "glXCreatePbuffer failed.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void PbufferGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);
  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }

  if (pbuffer_) {
    glXDestroyPbuffer(display, pbuffer_);
    pbuffer_ = 0;
  }
}

bool PbufferGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }
  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, pbuffer_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = NULL;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool PbufferGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == pbuffer_ &&
      glXGetCurrentContext() == context_;
}

bool PbufferGLContext::IsOffscreen() {
  return true;
}

void PbufferGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
}

gfx::Size PbufferGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this pbuffer.";
  return gfx::Size(1, 1);
}

void* PbufferGLContext::GetHandle() {
  return context_;
}

bool PixmapGLContext::Initialize(void* shared_handle) {
  LOG(INFO) << "GL context: using pixmaps.";
  if (!glXChooseVisual ||
      !glXCreateGLXPixmap ||
      !glXDestroyGLXPixmap) {
    LOG(ERROR) << "Pixmap support not available.";
    return false;
  }

  static int attributes[] = {
    GLX_RGBA,
    0
  };

  Display* display = x11_util::GetXDisplay();
  int screen = DefaultScreen(display);

  scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info(
      glXChooseVisual(display, screen, attributes));

  if (!visual_info.get()) {
    LOG(ERROR) << "glXChooseVisual failed.";
    return false;
  }
  context_ = glXCreateContext(display, visual_info.get(),
                              static_cast<GLContextHandle>(shared_handle),
                              True);
  if (!context_) {
    LOG(ERROR) << "glXCreateContext failed.";
    return false;
  }

  pixmap_ = XCreatePixmap(display, RootWindow(display, screen), 1, 1,
                          visual_info->depth);
  if (!pixmap_) {
    LOG(ERROR) << "XCreatePixmap failed.";
    return false;
  }

  glx_pixmap_ = glXCreateGLXPixmap(display, visual_info.get(), pixmap_);
  if (!glx_pixmap_) {
    LOG(ERROR) << "XCreatePixmap failed.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void PixmapGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);
  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }

  if (glx_pixmap_) {
    glXDestroyGLXPixmap(display, glx_pixmap_);
    glx_pixmap_ = 0;
  }

  if (pixmap_) {
    XFreePixmap(display, pixmap_);
    pixmap_ = 0;
  }
}

bool PixmapGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }
  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, glx_pixmap_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = NULL;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool PixmapGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == glx_pixmap_ &&
      glXGetCurrentContext() == context_;
}

bool PixmapGLContext::IsOffscreen() {
  return true;
}

void PixmapGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a pixmap.";
}

gfx::Size PixmapGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this pixmap.";
  return gfx::Size(1, 1);
}

void* PixmapGLContext::GetHandle() {
  return context_;
}

GLContext* GLContext::CreateOffscreenGLContext(void* shared_handle) {
  if (!InitializeOneOff())
    return NULL;

  if (OSMesaCreateContext) {
    scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext);

    if (!context->Initialize(shared_handle))
      return NULL;

    return context.release();
  } else {
    scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
    if (context->Initialize(shared_handle))
      return context.release();

    scoped_ptr<PixmapGLContext> context_pixmap(new PixmapGLContext);
    if (context_pixmap->Initialize(shared_handle))
      return context_pixmap.release();

    return NULL;
  }
}

}  // namespace gfx
<commit_msg>Added warning if GLX version is less than 1.3. Pbuffers need GLX 1.3 and the pixmap fallback for 1.2 does not work on all systems. TEST=try BUG=none<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file implements the ViewGLContext and PbufferGLContext classes.

#include <dlfcn.h>
#include <GL/glew.h>
#include <GL/glxew.h>
#include <GL/glx.h>
#include <GL/osmew.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "app/x11_util.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "app/gfx/gl/gl_context.h"
#include "app/gfx/gl/gl_context_osmesa.h"

namespace gfx {

typedef GLXContext GLContextHandle;
typedef GLXPbuffer PbufferHandle;

// This class is a wrapper around a GL context that renders directly to a
// window.
class ViewGLContext : public GLContext {
 public:
  explicit ViewGLContext(gfx::PluginWindowHandle window)
      : window_(window),
        context_(NULL) {
    DCHECK(window);
  }

  // Initializes the GL context.
  bool Initialize(bool multisampled);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  gfx::PluginWindowHandle window_;
  GLContextHandle context_;

  DISALLOW_COPY_AND_ASSIGN(ViewGLContext);
};

// This class is a wrapper around a GL context used for offscreen rendering.
// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful
// rendering.
class PbufferGLContext : public GLContext {
 public:
  explicit PbufferGLContext()
      : context_(NULL),
        pbuffer_(0) {
  }

  // Initializes the GL context.
  bool Initialize(void* shared_handle);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  GLContextHandle context_;
  PbufferHandle pbuffer_;

  DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
};

// Backup context if Pbuffers (GLX 1.3) aren't supported. May run slower...
class PixmapGLContext : public GLContext {
 public:
  explicit PixmapGLContext()
      : context_(NULL),
        pixmap_(0),
        glx_pixmap_(0) {
  }

  // Initializes the GL context.
  bool Initialize(void* shared_handle);

  virtual void Destroy();
  virtual bool MakeCurrent();
  virtual bool IsCurrent();
  virtual bool IsOffscreen();
  virtual void SwapBuffers();
  virtual gfx::Size GetSize();
  virtual void* GetHandle();

 private:
  GLContextHandle context_;
  Pixmap pixmap_;
  GLXPixmap glx_pixmap_;

  DISALLOW_COPY_AND_ASSIGN(PixmapGLContext);
};

// scoped_ptr functor for XFree(). Use as follows:
//   scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
// where "XVisualInfo" is any X type that is freed with XFree.
class ScopedPtrXFree {
 public:
  void operator()(void* x) const {
    ::XFree(x);
  }
};

// Some versions of NVIDIA's GL libGL.so include a broken version of
// dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically
// load it, and use glew to dynamically resolve symbols.
// See http://code.google.com/p/chromium/issues/detail?id=16800

static bool InitializeOneOff() {
  static bool initialized = false;
  if (initialized)
    return true;

  osmewInit();
  if (!OSMesaCreateContext) {
    void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
    if (!handle) {
      LOG(ERROR) << "Could not find libGL.so.1";
      return false;
    }

    // Initializes context-independent parts of GLEW
    if (glxewInit() != GLEW_OK) {
      LOG(ERROR) << "glxewInit failed";
      return false;
    }
    // glxewContextInit really only needs a display connection to
    // complete, and we don't want to have to create an OpenGL context
    // just to get access to GLX 1.3 entry points to create pbuffers.
    // We therefore added a glxewContextInitWithDisplay entry point.
    Display* display = x11_util::GetXDisplay();
    if (glxewContextInitWithDisplay(display) != GLEW_OK) {
      LOG(ERROR) << "glxewContextInit failed";
      return false;
    }

    int major, minor;
    if (!glXQueryVersion(display, &major, &minor)) {
      LOG(ERROR) << "glxQueryVersion failed";
      return false;
    }

    if (major == 1 && minor < 3) {
      LOG(WARNING) << "GLX 1.3 or later is recommended.";
    }
  }

  initialized = true;
  return true;
}

bool ViewGLContext::Initialize(bool multisampled) {
  if (multisampled) {
    LOG(WARNING) << "Multisampling not implemented.";
  }

  Display* display = x11_util::GetXDisplay();
  XWindowAttributes attributes;
  XGetWindowAttributes(display, window_, &attributes);
  XVisualInfo visual_info_template;
  visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
  int visual_info_count = 0;
  scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
      XGetVisualInfo(display, VisualIDMask,
                     &visual_info_template,
                     &visual_info_count));
  DCHECK(visual_info_list.get());
  DCHECK_GT(visual_info_count, 0);
  context_ = NULL;
  for (int i = 0; i < visual_info_count; ++i) {
    context_ = glXCreateContext(display, visual_info_list.get() + i, 0, True);
    if (context_)
      break;
  }
  if (!context_) {
    LOG(ERROR) << "Couldn't create GL context.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void ViewGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);

  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }
}

bool ViewGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }

  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, window_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = 0;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool ViewGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == window_ &&
      glXGetCurrentContext() == context_;
}

bool ViewGLContext::IsOffscreen() {
  return false;
}

void ViewGLContext::SwapBuffers() {
  Display* display = x11_util::GetXDisplay();
  glXSwapBuffers(display, window_);
}

gfx::Size ViewGLContext::GetSize() {
  XWindowAttributes attributes;
  Display* display = x11_util::GetXDisplay();
  XGetWindowAttributes(display, window_, &attributes);
  return gfx::Size(attributes.width, attributes.height);
}

void* ViewGLContext::GetHandle() {
  return context_;
}

GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
                                          bool multisampled) {
  if (!InitializeOneOff())
    return NULL;

  if (OSMesaCreateContext) {
    // TODO(apatrick): Support OSMesa rendering to a window on Linux.
    NOTREACHED() << "OSMesa rendering to a window is not yet implemented.";
    return NULL;
  } else {
    scoped_ptr<ViewGLContext> context(new ViewGLContext(window));

    if (!context->Initialize(multisampled))
      return NULL;

    return context.release();
  }
}

bool PbufferGLContext::Initialize(void* shared_handle) {
  if (!glXChooseFBConfig ||
      !glXCreateNewContext ||
      !glXCreatePbuffer ||
      !glXDestroyPbuffer) {
    LOG(ERROR) << "Pbuffer support not available.";
    return false;
  }

  static const int config_attributes[] = {
    GLX_DRAWABLE_TYPE,
    GLX_PBUFFER_BIT,
    GLX_RENDER_TYPE,
    GLX_RGBA_BIT,
    GLX_DOUBLEBUFFER,
    0,
    0
  };

  Display* display = x11_util::GetXDisplay();

  int nelements = 0;
  // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
  scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
      glXChooseFBConfig(display, 0, config_attributes, &nelements));
  if (!config.get()) {
    LOG(ERROR) << "glXChooseFBConfig failed.";
    return false;
  }
  if (!nelements) {
    LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
    return false;
  }
  context_ = glXCreateNewContext(display,
                                 config.get()[0],
                                 GLX_RGBA_TYPE,
                                 static_cast<GLContextHandle>(shared_handle),
                                 True);
  if (!context_) {
    LOG(ERROR) << "glXCreateNewContext failed.";
    return false;
  }
  static const int pbuffer_attributes[] = {
    GLX_PBUFFER_WIDTH,
    1,
    GLX_PBUFFER_HEIGHT,
    1,
    0
  };
  pbuffer_ = glXCreatePbuffer(display,
                              config.get()[0], pbuffer_attributes);
  if (!pbuffer_) {
    Destroy();
    LOG(ERROR) << "glXCreatePbuffer failed.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void PbufferGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);
  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }

  if (pbuffer_) {
    glXDestroyPbuffer(display, pbuffer_);
    pbuffer_ = 0;
  }
}

bool PbufferGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }
  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, pbuffer_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = NULL;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool PbufferGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == pbuffer_ &&
      glXGetCurrentContext() == context_;
}

bool PbufferGLContext::IsOffscreen() {
  return true;
}

void PbufferGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
}

gfx::Size PbufferGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this pbuffer.";
  return gfx::Size(1, 1);
}

void* PbufferGLContext::GetHandle() {
  return context_;
}

bool PixmapGLContext::Initialize(void* shared_handle) {
  LOG(INFO) << "GL context: using pixmaps.";
  if (!glXChooseVisual ||
      !glXCreateGLXPixmap ||
      !glXDestroyGLXPixmap) {
    LOG(ERROR) << "Pixmap support not available.";
    return false;
  }

  static int attributes[] = {
    GLX_RGBA,
    0
  };

  Display* display = x11_util::GetXDisplay();
  int screen = DefaultScreen(display);

  scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info(
      glXChooseVisual(display, screen, attributes));

  if (!visual_info.get()) {
    LOG(ERROR) << "glXChooseVisual failed.";
    return false;
  }
  context_ = glXCreateContext(display, visual_info.get(),
                              static_cast<GLContextHandle>(shared_handle),
                              True);
  if (!context_) {
    LOG(ERROR) << "glXCreateContext failed.";
    return false;
  }

  pixmap_ = XCreatePixmap(display, RootWindow(display, screen), 1, 1,
                          visual_info->depth);
  if (!pixmap_) {
    LOG(ERROR) << "XCreatePixmap failed.";
    return false;
  }

  glx_pixmap_ = glXCreateGLXPixmap(display, visual_info.get(), pixmap_);
  if (!glx_pixmap_) {
    LOG(ERROR) << "XCreatePixmap failed.";
    return false;
  }

  if (!MakeCurrent()) {
    Destroy();
    LOG(ERROR) << "Couldn't make context current for initialization.";
    return false;
  }

  if (!InitializeGLEW()) {
    Destroy();
    return false;
  }

  if (!InitializeCommon()) {
    Destroy();
    return false;
  }

  return true;
}

void PixmapGLContext::Destroy() {
  Display* display = x11_util::GetXDisplay();
  Bool result = glXMakeCurrent(display, 0, 0);
  // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
  // we have pending draws on an invalid window - which shouldn't be the case
  // here.
  DCHECK(result);
  if (context_) {
    glXDestroyContext(display, context_);
    context_ = NULL;
  }

  if (glx_pixmap_) {
    glXDestroyGLXPixmap(display, glx_pixmap_);
    glx_pixmap_ = 0;
  }

  if (pixmap_) {
    XFreePixmap(display, pixmap_);
    pixmap_ = 0;
  }
}

bool PixmapGLContext::MakeCurrent() {
  if (IsCurrent()) {
    return true;
  }
  Display* display = x11_util::GetXDisplay();
  if (glXMakeCurrent(display, glx_pixmap_, context_) != True) {
    glXDestroyContext(display, context_);
    context_ = NULL;
    LOG(ERROR) << "Couldn't make context current.";
    return false;
  }

  return true;
}

bool PixmapGLContext::IsCurrent() {
  return glXGetCurrentDrawable() == glx_pixmap_ &&
      glXGetCurrentContext() == context_;
}

bool PixmapGLContext::IsOffscreen() {
  return true;
}

void PixmapGLContext::SwapBuffers() {
  NOTREACHED() << "Attempted to call SwapBuffers on a pixmap.";
}

gfx::Size PixmapGLContext::GetSize() {
  NOTREACHED() << "Should not be requesting size of this pixmap.";
  return gfx::Size(1, 1);
}

void* PixmapGLContext::GetHandle() {
  return context_;
}

GLContext* GLContext::CreateOffscreenGLContext(void* shared_handle) {
  if (!InitializeOneOff())
    return NULL;

  if (OSMesaCreateContext) {
    scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext);

    if (!context->Initialize(shared_handle))
      return NULL;

    return context.release();
  } else {
    scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
    if (context->Initialize(shared_handle))
      return context.release();

    scoped_ptr<PixmapGLContext> context_pixmap(new PixmapGLContext);
    if (context_pixmap->Initialize(shared_handle))
      return context_pixmap.release();

    return NULL;
  }
}

}  // namespace gfx
<|endoftext|>


<commit_before>/*
 *  templatelistview.cpp  -  widget showing list of alarm templates
 *  Program:  kalarm
 *  (C) 2004, 2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "kalarm.h"

#include <klocale.h>
#include <kdebug.h>

#include "alarmcalendar.h"
#include "functions.h"
#include "templatelistview.moc"

/*=============================================================================
=  Class: TemplateListView
=  Displays the list of outstanding alarms.
=============================================================================*/
QValueList<EventListViewBase*>  TemplateListView::mInstanceList;

TemplateListView::TemplateListView(bool includeCmdAlarms, const QString& whatsThisText, QWidget* parent, const char* name)
	: EventListViewBase(parent, name),
	  mWhatsThisText(whatsThisText),
	  mIconColumn(0),
	  mNameColumn(1),
	  mExcludeCmdAlarms(!includeCmdAlarms)
{
	addColumn(QString::null);          // icon column
	addLastColumn(i18n("Name"));
	setSorting(mNameColumn);           // sort initially by name
	setColumnAlignment(mIconColumn, Qt::AlignHCenter);
	setColumnWidthMode(mIconColumn, QListView::Maximum);

	mInstanceList.append(this);
}

TemplateListView::~TemplateListView()
{
	mInstanceList.remove(this);
}

/******************************************************************************
*  Add all the templates to the list.
*/
void TemplateListView::populate()
{
	QPtrList<KAEvent> templates = KAlarm::templateList();
	for (QPtrList<KAEvent>::ConstIterator it = templates.begin();  it != templates.end();  ++it)
		addEntry(**it);
}

/******************************************************************************
*  Create a new list item for addEntry().
*/
EventListViewItemBase* TemplateListView::createItem(const KAEvent& event)
{
	return new TemplateListViewItem(this, event);
}

/******************************************************************************
*  Returns the QWhatsThis text for a specified column.
*/
QString TemplateListView::whatsThisText(int column) const
{
	if (column == mIconColumn)
		return i18n("Alarm type");
	if (column == mNameColumn)
		return i18n("Name of the alarm template");
	return mWhatsThisText;
}

/*=============================================================================
=  Class: TemplateListViewItem
=  Contains the details of one alarm for display in the TemplateListView.
=============================================================================*/

TemplateListViewItem::TemplateListViewItem(TemplateListView* parent, const KAEvent& event)
	: EventListViewItemBase(parent, event)
{
	setLastColumnText();     // set the template name column text

	int index;
	switch (event.action())
	{
		case KAAlarm::FILE:     index = 2;  break;
		case KAAlarm::COMMAND:  index = 3;  break;
		case KAAlarm::EMAIL:    index = 4;  break;
		case KAAlarm::MESSAGE:
		default:                index = 1;  break;
	}
	mIconOrder.sprintf("%01u", index);
	setPixmap(templateListView()->iconColumn(), *eventIcon());
}

/******************************************************************************
*  Return the alarm summary text.
*/
QString TemplateListViewItem::lastColumnText() const
{
	return event().templateName();
}

/******************************************************************************
*  Return the column sort order for one item in the list.
*/
QString TemplateListViewItem::key(int column, bool) const
{
	TemplateListView* listView = templateListView();
	if (column == listView->iconColumn())
		return mIconOrder;
	return text(column).lower();
}

<commit_msg>Backwards compatibility<commit_after>/*
 *  templatelistview.cpp  -  widget showing list of alarm templates
 *  Program:  kalarm
 *  (C) 2004, 2005 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "kalarm.h"

#include <klocale.h>
#include <kdebug.h>

#include "alarmcalendar.h"
#include "functions.h"
#include "templatelistview.moc"

/*=============================================================================
=  Class: TemplateListView
=  Displays the list of outstanding alarms.
=============================================================================*/
QValueList<EventListViewBase*>  TemplateListView::mInstanceList;

TemplateListView::TemplateListView(bool includeCmdAlarms, const QString& whatsThisText, QWidget* parent, const char* name)
	: EventListViewBase(parent, name),
	  mWhatsThisText(whatsThisText),
	  mIconColumn(0),
	  mNameColumn(1),
	  mExcludeCmdAlarms(!includeCmdAlarms)
{
	addColumn(QString::null);          // icon column
	addLastColumn(i18n("Name"));
	setSorting(mNameColumn);           // sort initially by name
	setColumnAlignment(mIconColumn, Qt::AlignHCenter);
	setColumnWidthMode(mIconColumn, QListView::Maximum);

	mInstanceList.append(this);
}

TemplateListView::~TemplateListView()
{
	mInstanceList.remove(this);
}

/******************************************************************************
*  Add all the templates to the list.
*/
void TemplateListView::populate()
{
	QPtrList<KAEvent> templates = KAlarm::templateList();
	for (KAEvent* e = templates.first();  e;  e = templates.next())
		addEntry(*e);
}

/******************************************************************************
*  Create a new list item for addEntry().
*/
EventListViewItemBase* TemplateListView::createItem(const KAEvent& event)
{
	return new TemplateListViewItem(this, event);
}

/******************************************************************************
*  Returns the QWhatsThis text for a specified column.
*/
QString TemplateListView::whatsThisText(int column) const
{
	if (column == mIconColumn)
		return i18n("Alarm type");
	if (column == mNameColumn)
		return i18n("Name of the alarm template");
	return mWhatsThisText;
}

/*=============================================================================
=  Class: TemplateListViewItem
=  Contains the details of one alarm for display in the TemplateListView.
=============================================================================*/

TemplateListViewItem::TemplateListViewItem(TemplateListView* parent, const KAEvent& event)
	: EventListViewItemBase(parent, event)
{
	setLastColumnText();     // set the template name column text

	int index;
	switch (event.action())
	{
		case KAAlarm::FILE:     index = 2;  break;
		case KAAlarm::COMMAND:  index = 3;  break;
		case KAAlarm::EMAIL:    index = 4;  break;
		case KAAlarm::MESSAGE:
		default:                index = 1;  break;
	}
	mIconOrder.sprintf("%01u", index);
	setPixmap(templateListView()->iconColumn(), *eventIcon());
}

/******************************************************************************
*  Return the alarm summary text.
*/
QString TemplateListViewItem::lastColumnText() const
{
	return event().templateName();
}

/******************************************************************************
*  Return the column sort order for one item in the list.
*/
QString TemplateListViewItem::key(int column, bool) const
{
	TemplateListView* listView = templateListView();
	if (column == listView->iconColumn())
		return mIconOrder;
	return text(column).lower();
}

<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <qi/log.hpp>
#include <qi/os.hpp>
#include <cerrno>

#ifdef _WIN32
#include <winsock2.h> // for socket
#include <WS2tcpip.h> // for socklen_t
#else
#include <arpa/inet.h>
#endif

#include "transportserver.hpp"
#include "transportsocket.hpp"
#include "transportserverasio_p.hpp"

qiLogCategory("qimessaging.transportserver");

namespace qi
{
  TransportServer::TransportServer()
  {
  }

  TransportServer::~TransportServer()
  {
    close();
  }

  qi::Future<void> TransportServer::listen(const qi::Url &url, qi::EventLoop* ctx)
  {
    TransportServerImpl* impl = nullptr;

    if (url.protocol() == "tcp")
    {
      impl = new TransportServerAsioPrivate(this, ctx);
    }
    else if (url.protocol() == "tcps")
    {
      impl = new TransportServerAsioPrivate(this, ctx);
    }
    else
    {
      const char* s = "Unrecognized protocol to create the TransportServer.";
      qiLogError() << s;
      return qi::makeFutureError<void>(s);
    }
    TransportServerImplPtr implPtr(impl);
    {
      boost::mutex::scoped_lock l(_implMutex);
      _impl.push_back(implPtr);
    }
    return impl->listen(url);
  }

  bool TransportServer::setIdentity(const std::string& key, const std::string& crt)
  {
    struct ::stat status;
    if (qi::os::stat(key.c_str(), &status) != 0)
    {
      qiLogError() << "stat:" << key << ": "
                                                 << strerror(errno);
      return false;
    }

    if (qi::os::stat(crt.c_str(), &status) != 0)
    {
      qiLogError() << "stat:" << crt << ": "
                                                 << strerror(errno);
      return false;
    }

    _identityCertificate = crt;
    _identityKey = key;

    return true;
  }

  std::vector<qi::Url> TransportServer::endpoints() const
  {
    std::vector<qi::Url> r;
    boost::mutex::scoped_lock l(_implMutex);
    for (std::vector<TransportServerImplPtr>::const_iterator it = _impl.begin();
         it != _impl.end();
         it++)
    {
      boost::mutex::scoped_lock l((*it)->_endpointsMutex);
      r.insert(r.end(), (*it)->_endpoints.begin(), (*it)->_endpoints.end());
    }

    return r;
  }

  void TransportServer::close() {
    boost::mutex::scoped_lock l(_implMutex);
    for (std::vector<TransportServerImplPtr>::const_iterator it = _impl.begin();
         it != _impl.end();
         it++)
    {
      (*it)->close(); // this will delete _impl
    }

    _impl.clear();
  }

}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<commit_msg>Messaging: improve error log in Session::setIdentity<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include <string>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <qi/log.hpp>
#include <qi/os.hpp>
#include <cerrno>

#ifdef _WIN32
#include <winsock2.h> // for socket
#include <WS2tcpip.h> // for socklen_t
#else
#include <arpa/inet.h>
#endif

#include "transportserver.hpp"
#include "transportsocket.hpp"
#include "transportserverasio_p.hpp"

qiLogCategory("qimessaging.transportserver");

namespace qi
{
  TransportServer::TransportServer()
  {
  }

  TransportServer::~TransportServer()
  {
    close();
  }

  qi::Future<void> TransportServer::listen(const qi::Url &url, qi::EventLoop* ctx)
  {
    TransportServerImpl* impl = nullptr;

    if (url.protocol() == "tcp")
    {
      impl = new TransportServerAsioPrivate(this, ctx);
    }
    else if (url.protocol() == "tcps")
    {
      impl = new TransportServerAsioPrivate(this, ctx);
    }
    else
    {
      const char* s = "Unrecognized protocol to create the TransportServer.";
      qiLogError() << s;
      return qi::makeFutureError<void>(s);
    }
    TransportServerImplPtr implPtr(impl);
    {
      boost::mutex::scoped_lock l(_implMutex);
      _impl.push_back(implPtr);
    }
    return impl->listen(url);
  }

  bool TransportServer::setIdentity(const std::string& key, const std::string& crt)
  {
    struct ::stat status;
    if (qi::os::stat(key.c_str(), &status) != 0)
    {
      qiLogError() << "stat of \"" << key << "\": " << strerror(errno);
      return false;
    }

    if (qi::os::stat(crt.c_str(), &status) != 0)
    {
      qiLogError() << "stat of \"" << crt << "\": " << strerror(errno);
      return false;
    }

    _identityCertificate = crt;
    _identityKey = key;

    return true;
  }

  std::vector<qi::Url> TransportServer::endpoints() const
  {
    std::vector<qi::Url> r;
    boost::mutex::scoped_lock l(_implMutex);
    for (std::vector<TransportServerImplPtr>::const_iterator it = _impl.begin();
         it != _impl.end();
         it++)
    {
      boost::mutex::scoped_lock l((*it)->_endpointsMutex);
      r.insert(r.end(), (*it)->_endpoints.begin(), (*it)->_endpoints.end());
    }

    return r;
  }

  void TransportServer::close() {
    boost::mutex::scoped_lock l(_implMutex);
    for (std::vector<TransportServerImplPtr>::const_iterator it = _impl.begin();
         it != _impl.end();
         it++)
    {
      (*it)->close(); // this will delete _impl
    }

    _impl.clear();
  }

}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<|endoftext|>


<commit_before><commit_msg>Repara lipsa_n_patrat #YOLO<commit_after><|endoftext|>


<commit_before>#include <phypp.hpp>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        print("usage: median_sub <directory>");
        return 0;
    }

    std::string dir = file::directorize(argv[1]);
    vec1s files = dir+file::list_files(dir+"sci_reconstructed*-sci.fits");

    for (auto oname : files) {
        std::string newfile = file::get_basename(oname);
        file::copy(oname, newfile);
        fits::image fimg(newfile);
        for (uint_t i : range(1, fimg.hdu_count())) {
            fimg.reach_hdu(i);
            if (fimg.axis_count() != 3) continue;

            vec3d cube;
            fimg.read(cube);
            for (uint_t l : range(cube.dims[0])) {
                cube(l,_,_) -= median(cube(l,_,_));
            }

            fimg.update(cube);
        }
    }

    return 0;
}
<commit_msg>Can now mask regions to exclude when median subtracting the cube<commit_after>#include <phypp.hpp>

int phypp_main(int argc, char* argv[]) {
    if (argc < 2) {
        print("usage: median_sub <directory> <mask_catalog>");
        return 0;
    }

    std::string dir = file::directorize(argv[1]);
    vec1s files = dir+file::list_files(dir+"sci_reconstructed*-sci.fits");

    vec1d ra, dec, size;
    if (argc > 2) {
        vec1s id;
        file::read_table(argv[2], file::find_skip(argv[2]), id, ra, dec, size);
    }

    auto ksigma = [](vec1d data) {
        double v = median(data);
        double m = 1.48*median(abs(data - v));
        vec1u idg = where(abs(data - v) < 7*m);
        return mean(data[idg]);
    };

    for (auto oname : files) {
        std::string newfile = file::get_basename(oname);
        file::copy(oname, newfile);
        fits::image fimg(newfile);
        for (uint_t i : range(1, fimg.hdu_count())) {
            fimg.reach_hdu(i);
            if (fimg.axis_count() != 3) continue;

            vec3d cube;
            fimg.read(cube);

            uint_t ny = cube.dims[1];
            uint_t nx = cube.dims[2];

            vec2b mask = replicate(true, ny, nx);

            // Mask nearby sources from the provided catalog (if any)
            if (!ra.empty()) {
                fits::wcs astro(fimg.read_header());
                vec1d x, y;
                fits::ad2xy(astro, ra, dec, x, y);
                x -= 1.0; y -= 1.0;
                double aspix;
                fits::get_pixel_size(astro, aspix);
                vec1d r = size/aspix;

                vec2d ix = generate_img(mask.dims, [](int_t,    int_t tx) { return tx; });
                vec2d iy = generate_img(mask.dims, [](int_t ty, int_t)    { return ty; });

                for (uint_t s : range(ra)) {
                    mask = mask && sqr(x[s] - ix) + sqr(y[s] - iy) > sqr(r[s]);
                }
            }

            // Mask borders
            mask(0,_) = mask(ny-1,_) = mask(_,0) = mask(_,nx-1) = false;

            // Subtract whole IFU
            vec1u idg = where(mask);
            for (uint_t l : range(cube.dims[0])) {
                cube(l,_,_) -= ksigma(cube(l,_,_)[idg]);
            }

            fimg.update(cube);
        }
    }

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>Make the fnvHash noexcept<commit_after><|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file load_mon.cpp
 *
 * @author Jonathan Challinger <jonathan@3drobotics.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <poll.h>

#include <px4_config.h>

#include <drivers/drv_hrt.h>

#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/cpuload.h>

#include <uORB/uORB.h>
#include <uORB/topics/cpuload.h>

#define LOAD_MON_INTERVAL_SEC 1.0f
#define LOAD_MON_INTERVAL_US (LOAD_MON_INTERVAL_SEC*1.0e6f)

extern "C" __EXPORT int load_mon_main(int argc, char *argv[]);
int load_mon_thread(int argc, char *argv[]);

static const char *module_name = "load_mon";
static bool thread_should_exit = false;		/**< daemon exit flag */
static bool thread_running = false;		/**< daemon status flag */
static int daemon_task;				/**< Handle of daemon task / thread */

extern struct system_load_s system_load;
struct cpuload_s cpuload;
static orb_advert_t cpuload_publish_handle = nullptr;

/**
 * Mainloop of load_mon.
 */
int load_mon_thread(int argc, char *argv[])
{
	warnx("[%s] starting\n", module_name);
	thread_running = true;

	hrt_abstime last_idle_time = system_load.tasks[0].total_runtime;

	while (!thread_should_exit) {
		usleep(LOAD_MON_INTERVAL_US);

		/* compute system load */
		uint64_t interval_idletime = system_load.tasks[0].total_runtime - last_idle_time;
		last_idle_time = system_load.tasks[0].total_runtime;

		cpuload.timestamp = hrt_absolute_time();
		cpuload.load = 1.0f - (float)interval_idletime / LOAD_MON_INTERVAL_US;

		if (cpuload_publish_handle == nullptr) {
			cpuload_publish_handle = orb_advertise(ORB_ID(cpuload), &cpuload);
		} else {
			orb_publish(ORB_ID(cpuload), cpuload_publish_handle, &cpuload);
		}
	}

	warnx("[%s] exiting.\n", module_name);

	thread_running = false;

	return 0;
}

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		warnx("%s\n", reason);
	}

	warnx("usage: %s {start|stop|status} [-p <additional params>]\n\n", module_name);
}

/**
 * The daemon app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int load_mon_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (thread_running) {
			warnx("daemon already running\n");
			/* this is not an error */
			return 0;
		}

		thread_should_exit = false;
		daemon_task = px4_task_spawn_cmd(module_name,
						 SCHED_DEFAULT,
						 SCHED_PRIORITY_DEFAULT,
						 2000,
						 load_mon_thread,
						 (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
		return 0;
	}

	if (!strcmp(argv[1], "stop")) {
		thread_should_exit = true;
		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (thread_running) {
			warnx("\trunning\n");
		} else {
			warnx("\tnot started\n");
		}

		return 0;
	}

	usage("unrecognized command");
	return 1;
}

<commit_msg>load_mon: use work queue instead of a whole task<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2012-2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file load_mon.cpp
 *
 * @author Jonathan Challinger <jonathan@3drobotics.com>
 * @author Julian Oes <julian@oes.ch
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <px4_config.h>
#include <px4_workqueue.h>

#include <drivers/drv_hrt.h>

#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <systemlib/cpuload.h>

#include <uORB/uORB.h>
#include <uORB/topics/cpuload.h>

extern struct system_load_s system_load;

namespace load_mon
{

extern "C" __EXPORT int load_mon_main(int argc, char *argv[]);

// Run it at 1 Hz.
const unsigned LOAD_MON_INTERVAL_US = 1000000;

class LoadMon
{
public:
	LoadMon();
	~LoadMon();

	/* Start the load monitoring
	 *
	 * @return 0 if successfull, -1 on error. */
	int start();

	/* Stop the load monitoring */
	void stop();

	/* Trampoline for the work queue. */
	static void cycle_trampoline(void *arg);

	bool isRunning() { return _taskIsRunning; }

private:
	/* Do a compute and schedule the next cycle. */
	void _cycle();

	/* Do a calculation of the CPU load and publish it. */
	void _compute();

	bool _taskShouldExit;
	bool _taskIsRunning;
	struct work_s _work;

	struct cpuload_s _cpuload;
	orb_advert_t _cpuload_pub;
	hrt_abstime _last_idle_time;
};

LoadMon::LoadMon() :
	_taskShouldExit(false),
	_taskIsRunning(false),
	_work{},
	_cpuload{},
	_cpuload_pub(nullptr),
	_last_idle_time(0)
{}

LoadMon::~LoadMon()
{
	work_cancel(HPWORK, &_work);
	_taskIsRunning = false;
}

int LoadMon::start()
{
	/* Schedule a cycle to start things. */
	return work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this, 0);
}

void LoadMon::stop()
{
	_taskShouldExit = true;
}

void
LoadMon::cycle_trampoline(void *arg)
{
	LoadMon *dev = reinterpret_cast<LoadMon *>(arg);

	dev->_cycle();
}

void LoadMon::_cycle()
{
	_taskIsRunning = true;

	_compute();

	if (!_taskShouldExit) {
		work_queue(HPWORK, &_work, (worker_t)&LoadMon::cycle_trampoline, this,
			   USEC2TICK(LOAD_MON_INTERVAL_US));
	}
}

void LoadMon::_compute()
{
	if (_last_idle_time == 0) {
		/* Just get the time in the first iteration */
		_last_idle_time = system_load.tasks[0].total_runtime;
		return;
	}

	/* compute system load */
	const hrt_abstime interval_idletime = system_load.tasks[0].total_runtime - _last_idle_time;
	_last_idle_time = system_load.tasks[0].total_runtime;

	_cpuload.timestamp = hrt_absolute_time();
	_cpuload.load = 1.0f - (float)interval_idletime / (float)LOAD_MON_INTERVAL_US;

	if (_cpuload_pub == nullptr) {
		_cpuload_pub = orb_advertise(ORB_ID(cpuload), &_cpuload);

	} else {
		orb_publish(ORB_ID(cpuload), _cpuload_pub, &_cpuload);
	}
}

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_INFO("usage: load_mon {start|stop|status}");
}

static LoadMon *load_mon = nullptr;

/**
 * The daemon app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int load_mon_main(int argc, char *argv[])
{
	if (argc < 2) {
		usage("missing command");
		return 1;
	}

	if (!strcmp(argv[1], "start")) {

		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_WARN("already running");
			/* this is not an error */
			return 0;
		}

		load_mon = new LoadMon();

		// Check if alloc worked.
		if (load_mon == nullptr) {
			PX4_ERR("alloc failed");
			return -1;
		}

		int ret = load_mon->start();

		if (ret != 0) {
			PX4_ERR("start failed");
		}

		return 0;
	}

	if (!strcmp(argv[1], "stop")) {

		if (load_mon == nullptr || load_mon->isRunning()) {
			PX4_WARN("not running");
			/* this is not an error */
			return 0;
		}

		load_mon->stop();

		// Wait for task to die
		int i = 0;

		do {
			/* wait up to 3s */
			usleep(100000);

		} while (load_mon->isRunning() && ++i < 30);

		delete load_mon;
		load_mon = nullptr;

		return 0;
	}

	if (!strcmp(argv[1], "status")) {
		if (load_mon != nullptr && load_mon->isRunning()) {
			PX4_INFO("running");

		} else {
			PX4_INFO("not running\n");
		}

		return 0;
	}

	usage("unrecognized command");
	return 1;
}

} // namespace load_mon
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EventMap.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2006-12-04 08:12:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _XMLOFF_EVENTMAP_HXX
#include "EventMap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

XMLTransformerEventMapEntry aTransformerEventMap[] =
{
    { XML_NAMESPACE_DOM,    "select",   "on-select" },
    { XML_NAMESPACE_OFFICE, "insert-start", "on-insert-start" },
    { XML_NAMESPACE_OFFICE, "insert-done",  "on-insert-done" },
    { XML_NAMESPACE_OFFICE, "mail-merge",   "on-mail-merge" },
    { XML_NAMESPACE_OFFICE, "alpha-char-input", "on-alpha-char-input" },
    { XML_NAMESPACE_OFFICE, "non-alpha-char-input", "on-non-alpha-char-input" },
    { XML_NAMESPACE_DOM,    "resize",   "on-resize" },
    { XML_NAMESPACE_OFFICE, "move", "on-move" },
    { XML_NAMESPACE_OFFICE, "page-count-change", "on-page-count-change" },
    { XML_NAMESPACE_DOM,    "mouseover",    "on-mouse-over" },
    { XML_NAMESPACE_DOM,    "click",    "on-click" },
    { XML_NAMESPACE_DOM,    "mouseout", "on-mouse-out" },
    { XML_NAMESPACE_OFFICE, "load-error",   "on-load-error" },
    { XML_NAMESPACE_OFFICE, "load-cancel",  "on-load-cancel" },
    { XML_NAMESPACE_OFFICE, "load-done",    "on-load-done" },
    { XML_NAMESPACE_DOM,    "load", "on-load" },
    { XML_NAMESPACE_DOM,    "unload",   "on-unload" },
    { XML_NAMESPACE_OFFICE, "start-app",    "on-start-app" },
    { XML_NAMESPACE_OFFICE, "close-app",    "on-close-app" },
    { XML_NAMESPACE_OFFICE, "new",  "on-new" },
    { XML_NAMESPACE_OFFICE, "save", "on-save" },
    { XML_NAMESPACE_OFFICE, "save-as",  "on-save-as" },
    { XML_NAMESPACE_DOM,    "DOMFocusIn",   "on-focus" },
    { XML_NAMESPACE_DOM,    "DOMFocusOut",  "on-unfocus" },
    { XML_NAMESPACE_OFFICE, "print",    "on-print" },
    { XML_NAMESPACE_DOM,    "error",    "on-error" },
    { XML_NAMESPACE_OFFICE, "load-finished",    "on-load-finished" },
    { XML_NAMESPACE_OFFICE, "save-finished",    "on-save-finished" },
    { XML_NAMESPACE_OFFICE, "modify-changed",   "on-modify-changed" },
    { XML_NAMESPACE_OFFICE, "prepare-unload",   "on-prepare-unload" },
    { XML_NAMESPACE_OFFICE, "new-mail", "on-new-mail" },
    { XML_NAMESPACE_OFFICE, "toggle-fullscreen",    "on-toggle-fullscreen" },
    { XML_NAMESPACE_OFFICE, "save-done",    "on-save-done" },
    { XML_NAMESPACE_OFFICE, "save-as-done", "on-save-as-done" },
    { XML_NAMESPACE_OFFICE, "create",    "on-create" },
    { XML_NAMESPACE_OFFICE, "save-as-failed",    "on-save-as-failed" },
    { XML_NAMESPACE_OFFICE, "save-failed",    "on-save-failed" },
    { XML_NAMESPACE_OFFICE, "copy-to-failed",    "on-copy-to-failed" },
    { XML_NAMESPACE_OFFICE, "title-changed",    "on-title-changed" },

    { XML_NAMESPACE_FORM,   "approveaction",    "on-approveaction" },
    { XML_NAMESPACE_FORM,   "performaction",    "on-performaction" },
    { XML_NAMESPACE_DOM,    "change",   "on-change" },
    { XML_NAMESPACE_FORM,   "textchange",   "on-textchange" },
    { XML_NAMESPACE_FORM,   "itemstatechange",  "on-itemstatechange" },
    { XML_NAMESPACE_DOM,    "keydown",  "on-keydown" },
    { XML_NAMESPACE_DOM,    "keyup",    "on-keyup" },
    { XML_NAMESPACE_FORM,   "mousedrag",    "on-mousedrag" },
    { XML_NAMESPACE_DOM,    "mousemove",    "on-mousemove" },
    { XML_NAMESPACE_DOM,    "mousedown",    "on-mousedown" },
    { XML_NAMESPACE_DOM,    "mouseup",  "on-mouseup" },
    { XML_NAMESPACE_FORM,   "approvereset", "on-approvereset" },
    { XML_NAMESPACE_DOM,    "reset",    "on-reset" },
    { XML_NAMESPACE_DOM,    "submit",   "on-submit" },
    { XML_NAMESPACE_FORM,   "approveupdate",    "on-approveupdate" },
    { XML_NAMESPACE_FORM,   "update",   "on-update" },
    { XML_NAMESPACE_FORM,   "startreload",  "on-startreload" },
    { XML_NAMESPACE_FORM,   "reload",   "on-reload" },
    { XML_NAMESPACE_FORM,   "startunload",  "on-startunload" },
    { XML_NAMESPACE_FORM,   "confirmdelete",    "on-confirmdelete" },
    { XML_NAMESPACE_FORM,   "approverowchange", "on-approverowchange" },
    { XML_NAMESPACE_FORM,   "rowchange",    "on-rowchange" },
    { XML_NAMESPACE_FORM,   "approvecursormove",    "on-approvecursormove" },
    { XML_NAMESPACE_FORM,   "cursormove",   "on-cursormove" },
    { XML_NAMESPACE_FORM,   "supplyparameter",  "on-supplyparameter" },
    { XML_NAMESPACE_FORM,   "adjust",   "on-adjust" },
    { 0, 0, 0 }
};

XMLTransformerEventMapEntry aFormTransformerEventMap[] =
{
    { XML_NAMESPACE_DOM,    "mouseover",    "on-mouseover" },
    { XML_NAMESPACE_DOM,    "mouseout", "on-mouseout" },
    { XML_NAMESPACE_DOM,    "DOMFocusOut",  "on-blur" },
    { 0, 0, 0 }
};
<commit_msg>INTEGRATION: CWS changefileheader (1.6.262); FILE MERGED 2008/04/01 13:05:45 thb 1.6.262.2: #i85898# Stripping all external header guards 2008/03/31 16:28:50 rt 1.6.262.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: EventMap.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "EventMap.hxx"
#include "xmlnmspe.hxx"

XMLTransformerEventMapEntry aTransformerEventMap[] =
{
    { XML_NAMESPACE_DOM,    "select",   "on-select" },
    { XML_NAMESPACE_OFFICE, "insert-start", "on-insert-start" },
    { XML_NAMESPACE_OFFICE, "insert-done",  "on-insert-done" },
    { XML_NAMESPACE_OFFICE, "mail-merge",   "on-mail-merge" },
    { XML_NAMESPACE_OFFICE, "alpha-char-input", "on-alpha-char-input" },
    { XML_NAMESPACE_OFFICE, "non-alpha-char-input", "on-non-alpha-char-input" },
    { XML_NAMESPACE_DOM,    "resize",   "on-resize" },
    { XML_NAMESPACE_OFFICE, "move", "on-move" },
    { XML_NAMESPACE_OFFICE, "page-count-change", "on-page-count-change" },
    { XML_NAMESPACE_DOM,    "mouseover",    "on-mouse-over" },
    { XML_NAMESPACE_DOM,    "click",    "on-click" },
    { XML_NAMESPACE_DOM,    "mouseout", "on-mouse-out" },
    { XML_NAMESPACE_OFFICE, "load-error",   "on-load-error" },
    { XML_NAMESPACE_OFFICE, "load-cancel",  "on-load-cancel" },
    { XML_NAMESPACE_OFFICE, "load-done",    "on-load-done" },
    { XML_NAMESPACE_DOM,    "load", "on-load" },
    { XML_NAMESPACE_DOM,    "unload",   "on-unload" },
    { XML_NAMESPACE_OFFICE, "start-app",    "on-start-app" },
    { XML_NAMESPACE_OFFICE, "close-app",    "on-close-app" },
    { XML_NAMESPACE_OFFICE, "new",  "on-new" },
    { XML_NAMESPACE_OFFICE, "save", "on-save" },
    { XML_NAMESPACE_OFFICE, "save-as",  "on-save-as" },
    { XML_NAMESPACE_DOM,    "DOMFocusIn",   "on-focus" },
    { XML_NAMESPACE_DOM,    "DOMFocusOut",  "on-unfocus" },
    { XML_NAMESPACE_OFFICE, "print",    "on-print" },
    { XML_NAMESPACE_DOM,    "error",    "on-error" },
    { XML_NAMESPACE_OFFICE, "load-finished",    "on-load-finished" },
    { XML_NAMESPACE_OFFICE, "save-finished",    "on-save-finished" },
    { XML_NAMESPACE_OFFICE, "modify-changed",   "on-modify-changed" },
    { XML_NAMESPACE_OFFICE, "prepare-unload",   "on-prepare-unload" },
    { XML_NAMESPACE_OFFICE, "new-mail", "on-new-mail" },
    { XML_NAMESPACE_OFFICE, "toggle-fullscreen",    "on-toggle-fullscreen" },
    { XML_NAMESPACE_OFFICE, "save-done",    "on-save-done" },
    { XML_NAMESPACE_OFFICE, "save-as-done", "on-save-as-done" },
    { XML_NAMESPACE_OFFICE, "create",    "on-create" },
    { XML_NAMESPACE_OFFICE, "save-as-failed",    "on-save-as-failed" },
    { XML_NAMESPACE_OFFICE, "save-failed",    "on-save-failed" },
    { XML_NAMESPACE_OFFICE, "copy-to-failed",    "on-copy-to-failed" },
    { XML_NAMESPACE_OFFICE, "title-changed",    "on-title-changed" },

    { XML_NAMESPACE_FORM,   "approveaction",    "on-approveaction" },
    { XML_NAMESPACE_FORM,   "performaction",    "on-performaction" },
    { XML_NAMESPACE_DOM,    "change",   "on-change" },
    { XML_NAMESPACE_FORM,   "textchange",   "on-textchange" },
    { XML_NAMESPACE_FORM,   "itemstatechange",  "on-itemstatechange" },
    { XML_NAMESPACE_DOM,    "keydown",  "on-keydown" },
    { XML_NAMESPACE_DOM,    "keyup",    "on-keyup" },
    { XML_NAMESPACE_FORM,   "mousedrag",    "on-mousedrag" },
    { XML_NAMESPACE_DOM,    "mousemove",    "on-mousemove" },
    { XML_NAMESPACE_DOM,    "mousedown",    "on-mousedown" },
    { XML_NAMESPACE_DOM,    "mouseup",  "on-mouseup" },
    { XML_NAMESPACE_FORM,   "approvereset", "on-approvereset" },
    { XML_NAMESPACE_DOM,    "reset",    "on-reset" },
    { XML_NAMESPACE_DOM,    "submit",   "on-submit" },
    { XML_NAMESPACE_FORM,   "approveupdate",    "on-approveupdate" },
    { XML_NAMESPACE_FORM,   "update",   "on-update" },
    { XML_NAMESPACE_FORM,   "startreload",  "on-startreload" },
    { XML_NAMESPACE_FORM,   "reload",   "on-reload" },
    { XML_NAMESPACE_FORM,   "startunload",  "on-startunload" },
    { XML_NAMESPACE_FORM,   "confirmdelete",    "on-confirmdelete" },
    { XML_NAMESPACE_FORM,   "approverowchange", "on-approverowchange" },
    { XML_NAMESPACE_FORM,   "rowchange",    "on-rowchange" },
    { XML_NAMESPACE_FORM,   "approvecursormove",    "on-approvecursormove" },
    { XML_NAMESPACE_FORM,   "cursormove",   "on-cursormove" },
    { XML_NAMESPACE_FORM,   "supplyparameter",  "on-supplyparameter" },
    { XML_NAMESPACE_FORM,   "adjust",   "on-adjust" },
    { 0, 0, 0 }
};

XMLTransformerEventMapEntry aFormTransformerEventMap[] =
{
    { XML_NAMESPACE_DOM,    "mouseover",    "on-mouseover" },
    { XML_NAMESPACE_DOM,    "mouseout", "on-mouseout" },
    { XML_NAMESPACE_DOM,    "DOMFocusOut",  "on-blur" },
    { 0, 0, 0 }
};
<|endoftext|>


<commit_before>#include "./mouse_dragging_controller.h"
#include <QMoveEvent>

void MouseDraggingController::setFrameTime(double frameTime)
{
  this->frameTime = frameTime;
}

void MouseDraggingController::startDragging()
{
  start = true;
}

void MouseDraggingController::updateDragging(QEvent *event)
{
  auto mousePosition = toEigen(static_cast<QMouseEvent *>(event)->pos());

  if (start)
  {
    start = false;
    lastMousePosition = mousePosition;
    return;
  }

  Eigen::Vector2f diff = mousePosition - lastMousePosition;

  update(diff);

  lastMousePosition = mousePosition;
}

<commit_msg>Minor: use right include.<commit_after>#include "./mouse_dragging_controller.h"
#include <QMouseEvent>

void MouseDraggingController::setFrameTime(double frameTime)
{
  this->frameTime = frameTime;
}

void MouseDraggingController::startDragging()
{
  start = true;
}

void MouseDraggingController::updateDragging(QEvent *event)
{
  auto mousePosition = toEigen(static_cast<QMouseEvent *>(event)->pos());

  if (start)
  {
    start = false;
    lastMousePosition = mousePosition;
    return;
  }

  Eigen::Vector2f diff = mousePosition - lastMousePosition;

  update(diff);

  lastMousePosition = mousePosition;
}

<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>

// defined in proc_clean.cc
extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);

static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity)
{
	if (signal.width != 1)
		return false;
	if (signal == ref)
		return true;

	for (auto &cell_it : mod->cells) {
		RTLIL::Cell *cell = cell_it.second;
		if (cell->type == "$reduce_or" && cell->connections["\\Y"] == signal)
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		if (cell->type == "$reduce_bool" && cell->connections["\\Y"] == signal)
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		if (cell->type == "$logic_not" && cell->connections["\\Y"] == signal) {
			polarity = !polarity;
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		}
		if (cell->type == "$not" && cell->connections["\\Y"] == signal) {
			polarity = !polarity;
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		}
		if ((cell->type == "$eq" || cell->type == "$eqx") && cell->connections["\\Y"] == signal) {
			if (cell->connections["\\A"].is_fully_const()) {
				if (!cell->connections["\\A"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\B"], ref, polarity);
			}
			if (cell->connections["\\B"].is_fully_const()) {
				if (!cell->connections["\\B"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\A"], ref, polarity);
			}
		}
		if ((cell->type == "$ne" || cell->type == "$nex") && cell->connections["\\Y"] == signal) {
			if (cell->connections["\\A"].is_fully_const()) {
				if (cell->connections["\\A"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\B"], ref, polarity);
			}
			if (cell->connections["\\B"].is_fully_const()) {
				if (cell->connections["\\B"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\A"], ref, polarity);
			}
		}
	}

	return false;
}

static void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::SigSpec &rval, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity, bool unknown)
{
	for (auto &action : cs->actions) {
		if (unknown)
			rspec.replace(action.first, RTLIL::SigSpec(RTLIL::State::Sm, action.second.width), &rval);
		else
			rspec.replace(action.first, action.second, &rval);
	}

	for (auto sw : cs->switches) {
		if (sw->signal.width == 0) {
			for (auto cs2 : sw->cases)
				apply_const(mod, rspec, rval, cs2, const_sig, polarity, unknown);
		}
		bool this_polarity = polarity;
		if (check_signal(mod, sw->signal, const_sig, this_polarity)) {
			for (auto cs2 : sw->cases) {
				for (auto comp : cs2->compare)
					if (comp == RTLIL::SigSpec(this_polarity, 1))
						goto matched_case;
				if (cs2->compare.size() == 0) {
			matched_case:
					apply_const(mod, rspec, rval, cs2, const_sig, polarity, false);
					break;
				}
			}
		} else {
			for (auto cs2 : sw->cases)
				apply_const(mod, rspec, rval, cs2, const_sig, polarity, true);
		}
	}
}

static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity)
{
	for (auto sw : cs->switches) {
		bool this_polarity = polarity;
		if (check_signal(mod, sw->signal, const_sig, this_polarity)) {
			bool found_rem_path = false;
			for (size_t i = 0; i < sw->cases.size(); i++) {
				RTLIL::CaseRule *cs2 = sw->cases[i];
				for (auto comp : cs2->compare)
					if (comp == RTLIL::SigSpec(this_polarity, 1))
						goto matched_case;
				if (found_rem_path) {
			matched_case:
					sw->cases.erase(sw->cases.begin() + (i--));
					delete cs2;
					continue;
				}
				found_rem_path = true;
				cs2->compare.clear();
			}
			sw->signal = RTLIL::SigSpec();
		} else {
			for (auto cs2 : sw->cases)
				eliminate_const(mod, cs2, const_sig, polarity);
		}
	}

	int dummy_count = 0;
	bool did_something = true;
	while (did_something) {
		did_something = false;
		proc_clean_case(cs, did_something, dummy_count, 1);
	}
}

static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
{
restart_proc_arst:
	if (proc->root_case.switches.size() != 1)
		return;

	RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;

	for (auto &sync : proc->syncs) {
		if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
			bool polarity = sync->type == RTLIL::SyncType::STp;
			if (check_signal(mod, root_sig, sync->signal, polarity)) {
				log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
				sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
				for (auto &action : sync->actions) {
					RTLIL::SigSpec rspec = action.second;
					RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.width);
					rspec.expand(), rval.expand();
					for (int i = 0; i < int(rspec.chunks.size()); i++)
						if (rspec.chunks[i].wire == NULL)
							rval.chunks[i] = rspec.chunks[i];
					rspec.optimize(), rval.optimize();
					RTLIL::SigSpec last_rval;
					for (int count = 0; rval != last_rval; count++) {
						last_rval = rval;
						apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
						assign_map.apply(rval);
						if (rval.is_fully_const())
							break;
						if (count > 100)
							log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
									log_signal(sync->signal), log_signal(rval), log_signal(action.first));
						rspec = rval;
					}
					if (rval.has_marked_bits())
						log_error("Async reset %s yields non-constant value %s for signal %s.\n",
								log_signal(sync->signal), log_signal(rval), log_signal(action.first));
					action.second = rval;
				}
				eliminate_const(mod, &proc->root_case, root_sig, polarity);
				goto restart_proc_arst;
			}
		}
	}
}

struct ProcArstPass : public Pass {
	ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    proc_arst [-global_arst [!]<netname>] [selection]\n");
		log("\n");
		log("This pass identifies asynchronous resets in the processes and converts them\n");
		log("to a different internal representation that is suitable for generating\n");
		log("flip-flop cells with asynchronous resets.\n");
		log("\n");
		log("    -global_arst [!]<netname>\n");
		log("        In modules that have a net with the given name, use this net as async\n");
		log("        reset for registers that have been assign initial values in their\n");
		log("        declaration ('reg foobar = constant_value;'). Use the '!' modifier for\n");
		log("        active low reset signals. Note: the frontend stores the default value\n");
		log("        in the 'init' attribute on the net.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::string global_arst;
		bool global_arst_neg = false;

		log_header("Executing PROC_ARST pass (detect async resets in processes).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-global_arst" && argidx+1 < args.size()) {
				global_arst = args[++argidx];
				if (!global_arst.empty() && global_arst[0] == '!') {
					global_arst_neg = true;
					global_arst = global_arst.substr(1);
				}
				global_arst = RTLIL::escape_id(global_arst);
				continue;
			}
			break;
		}

		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second)) {
				SigMap assign_map(mod_it.second);
				for (auto &proc_it : mod_it.second->processes) {
					if (!design->selected(mod_it.second, proc_it.second))
						continue;
					proc_arst(mod_it.second, proc_it.second, assign_map);
					if (global_arst.empty() || mod_it.second->wires.count(global_arst) == 0)
						continue;
					std::vector<RTLIL::SigSig> arst_actions;
					for (auto sync : proc_it.second->syncs)
						if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn)
							for (auto &act : sync->actions) {
								RTLIL::SigSpec arst_sig, arst_val;
								for (auto &chunk : act.first.chunks)
									if (chunk.wire && chunk.wire->attributes.count("\\init")) {
										RTLIL::SigSpec value = chunk.wire->attributes.at("\\init");
										value.extend(chunk.wire->width, false);
										arst_sig.append(chunk);
										arst_val.append(value.extract(chunk.offset, chunk.width));
									}
								if (arst_sig.width) {
									log("Added global reset to process %s: %s <- %s\n",
											proc_it.first.c_str(), log_signal(arst_sig), log_signal(arst_val));
									arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val));
								}
							}
					if (!arst_actions.empty()) {
						RTLIL::SyncRule *sync = new RTLIL::SyncRule;
						sync->type = global_arst_neg ? RTLIL::SyncType::ST0 : RTLIL::SyncType::ST1;
						sync->signal = mod_it.second->wires.at(global_arst);
						sync->actions = arst_actions;
						proc_it.second->syncs.push_back(sync);
					}
				}
			}
	}
} ProcArstPass;

<commit_msg>Added workaround for vhdl-style edge triggers from vhdl2verilog to proc_arst<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>

// defined in proc_clean.cc
extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);

static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSpec ref, bool &polarity)
{
	if (signal.width != 1)
		return false;
	if (signal == ref)
		return true;

	for (auto &cell_it : mod->cells) {
		RTLIL::Cell *cell = cell_it.second;
		if (cell->type == "$reduce_or" && cell->connections["\\Y"] == signal)
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		if (cell->type == "$reduce_bool" && cell->connections["\\Y"] == signal)
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		if (cell->type == "$logic_not" && cell->connections["\\Y"] == signal) {
			polarity = !polarity;
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		}
		if (cell->type == "$not" && cell->connections["\\Y"] == signal) {
			polarity = !polarity;
			return check_signal(mod, cell->connections["\\A"], ref, polarity);
		}
		if ((cell->type == "$eq" || cell->type == "$eqx") && cell->connections["\\Y"] == signal) {
			if (cell->connections["\\A"].is_fully_const()) {
				if (!cell->connections["\\A"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\B"], ref, polarity);
			}
			if (cell->connections["\\B"].is_fully_const()) {
				if (!cell->connections["\\B"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\A"], ref, polarity);
			}
		}
		if ((cell->type == "$ne" || cell->type == "$nex") && cell->connections["\\Y"] == signal) {
			if (cell->connections["\\A"].is_fully_const()) {
				if (cell->connections["\\A"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\B"], ref, polarity);
			}
			if (cell->connections["\\B"].is_fully_const()) {
				if (cell->connections["\\B"].as_bool())
					polarity = !polarity;
				return check_signal(mod, cell->connections["\\A"], ref, polarity);
			}
		}
	}

	return false;
}

static void apply_const(RTLIL::Module *mod, const RTLIL::SigSpec rspec, RTLIL::SigSpec &rval, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity, bool unknown)
{
	for (auto &action : cs->actions) {
		if (unknown)
			rspec.replace(action.first, RTLIL::SigSpec(RTLIL::State::Sm, action.second.width), &rval);
		else
			rspec.replace(action.first, action.second, &rval);
	}

	for (auto sw : cs->switches) {
		if (sw->signal.width == 0) {
			for (auto cs2 : sw->cases)
				apply_const(mod, rspec, rval, cs2, const_sig, polarity, unknown);
		}
		bool this_polarity = polarity;
		if (check_signal(mod, sw->signal, const_sig, this_polarity)) {
			for (auto cs2 : sw->cases) {
				for (auto comp : cs2->compare)
					if (comp == RTLIL::SigSpec(this_polarity, 1))
						goto matched_case;
				if (cs2->compare.size() == 0) {
			matched_case:
					apply_const(mod, rspec, rval, cs2, const_sig, polarity, false);
					break;
				}
			}
		} else {
			for (auto cs2 : sw->cases)
				apply_const(mod, rspec, rval, cs2, const_sig, polarity, true);
		}
	}
}

static void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec const_sig, bool polarity)
{
	for (auto sw : cs->switches) {
		bool this_polarity = polarity;
		if (check_signal(mod, sw->signal, const_sig, this_polarity)) {
			bool found_rem_path = false;
			for (size_t i = 0; i < sw->cases.size(); i++) {
				RTLIL::CaseRule *cs2 = sw->cases[i];
				for (auto comp : cs2->compare)
					if (comp == RTLIL::SigSpec(this_polarity, 1))
						goto matched_case;
				if (found_rem_path) {
			matched_case:
					sw->cases.erase(sw->cases.begin() + (i--));
					delete cs2;
					continue;
				}
				found_rem_path = true;
				cs2->compare.clear();
			}
			sw->signal = RTLIL::SigSpec();
		} else {
			for (auto cs2 : sw->cases)
				eliminate_const(mod, cs2, const_sig, polarity);
		}
	}

	int dummy_count = 0;
	bool did_something = true;
	while (did_something) {
		did_something = false;
		proc_clean_case(cs, did_something, dummy_count, 1);
	}
}

static void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
{
restart_proc_arst:
	if (proc->root_case.switches.size() != 1)
		return;

	RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;

	for (auto &sync : proc->syncs) {
		if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
			bool polarity = sync->type == RTLIL::SyncType::STp;
			if (check_signal(mod, root_sig, sync->signal, polarity)) {
				if (proc->syncs.size() == 1) {
					log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
				} else {
					log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
					sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
				}
				for (auto &action : sync->actions) {
					RTLIL::SigSpec rspec = action.second;
					RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.width);
					rspec.expand(), rval.expand();
					for (int i = 0; i < int(rspec.chunks.size()); i++)
						if (rspec.chunks[i].wire == NULL)
							rval.chunks[i] = rspec.chunks[i];
					rspec.optimize(), rval.optimize();
					RTLIL::SigSpec last_rval;
					for (int count = 0; rval != last_rval; count++) {
						last_rval = rval;
						apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
						assign_map.apply(rval);
						if (rval.is_fully_const())
							break;
						if (count > 100)
							log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
									log_signal(sync->signal), log_signal(rval), log_signal(action.first));
						rspec = rval;
					}
					if (rval.has_marked_bits())
						log_error("Async reset %s yields non-constant value %s for signal %s.\n",
								log_signal(sync->signal), log_signal(rval), log_signal(action.first));
					action.second = rval;
				}
				eliminate_const(mod, &proc->root_case, root_sig, polarity);
				goto restart_proc_arst;
			}
		}
	}
}

struct ProcArstPass : public Pass {
	ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { }
	virtual void help()
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    proc_arst [-global_arst [!]<netname>] [selection]\n");
		log("\n");
		log("This pass identifies asynchronous resets in the processes and converts them\n");
		log("to a different internal representation that is suitable for generating\n");
		log("flip-flop cells with asynchronous resets.\n");
		log("\n");
		log("    -global_arst [!]<netname>\n");
		log("        In modules that have a net with the given name, use this net as async\n");
		log("        reset for registers that have been assign initial values in their\n");
		log("        declaration ('reg foobar = constant_value;'). Use the '!' modifier for\n");
		log("        active low reset signals. Note: the frontend stores the default value\n");
		log("        in the 'init' attribute on the net.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
	{
		std::string global_arst;
		bool global_arst_neg = false;

		log_header("Executing PROC_ARST pass (detect async resets in processes).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-global_arst" && argidx+1 < args.size()) {
				global_arst = args[++argidx];
				if (!global_arst.empty() && global_arst[0] == '!') {
					global_arst_neg = true;
					global_arst = global_arst.substr(1);
				}
				global_arst = RTLIL::escape_id(global_arst);
				continue;
			}
			break;
		}

		extra_args(args, argidx, design);

		for (auto &mod_it : design->modules)
			if (design->selected(mod_it.second)) {
				SigMap assign_map(mod_it.second);
				for (auto &proc_it : mod_it.second->processes) {
					if (!design->selected(mod_it.second, proc_it.second))
						continue;
					proc_arst(mod_it.second, proc_it.second, assign_map);
					if (global_arst.empty() || mod_it.second->wires.count(global_arst) == 0)
						continue;
					std::vector<RTLIL::SigSig> arst_actions;
					for (auto sync : proc_it.second->syncs)
						if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn)
							for (auto &act : sync->actions) {
								RTLIL::SigSpec arst_sig, arst_val;
								for (auto &chunk : act.first.chunks)
									if (chunk.wire && chunk.wire->attributes.count("\\init")) {
										RTLIL::SigSpec value = chunk.wire->attributes.at("\\init");
										value.extend(chunk.wire->width, false);
										arst_sig.append(chunk);
										arst_val.append(value.extract(chunk.offset, chunk.width));
									}
								if (arst_sig.width) {
									log("Added global reset to process %s: %s <- %s\n",
											proc_it.first.c_str(), log_signal(arst_sig), log_signal(arst_val));
									arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val));
								}
							}
					if (!arst_actions.empty()) {
						RTLIL::SyncRule *sync = new RTLIL::SyncRule;
						sync->type = global_arst_neg ? RTLIL::SyncType::ST0 : RTLIL::SyncType::ST1;
						sync->signal = mod_it.second->wires.at(global_arst);
						sync->actions = arst_actions;
						proc_it.second->syncs.push_back(sync);
					}
				}
			}
	}
} ProcArstPass;

<|endoftext|>


<commit_before>//
//  yas_audio_unit_parameter.cpp
//

#include "yas_audio_unit.h"
#include "yas_cf_utils.h"

using namespace yas;

struct audio::unit::parameter::impl : base::impl {
    AudioUnitParameterID _parameter_id;
    AudioUnitScope _scope;
    bool _has_clump;
    uint32_t _clump_id;
    AudioUnitParameterUnit _unit;
    AudioUnitParameterValue _min_value;
    AudioUnitParameterValue _max_value;
    AudioUnitParameterValue _default_value;
    std::unordered_map<AudioUnitElement, AudioUnitParameterValue> _values;
    std::string _unit_name;
    std::string _name;
    chaining::notifier<chaining_pair_t> _notifier;

    impl(AudioUnitParameterInfo const &info, AudioUnitParameterID const parameter_id, AudioUnitScope const scope)
        : _parameter_id(parameter_id),
          _scope(scope),
          _has_clump(info.flags & kAudioUnitParameterFlag_HasClump),
          _clump_id(info.clumpID),
          _unit(info.unit),
          _min_value(info.minValue),
          _max_value(info.maxValue),
          _default_value(info.defaultValue),
          _unit_name(to_string(info.unitName)),
          _name(to_string(info.cfNameString)) {
    }

    ~impl() {
    }

    void set_value(AudioUnitParameterValue const value, AudioUnitElement const element) {
        change_info info{
            .element = element,
            .old_value = this->_values[element],
            .new_value = value,
            .parameter = cast<audio::unit::parameter>(),
        };

        this->_notifier.notify(std::make_pair(method::will_change, info));
        _values[element] = value;
        this->_notifier.notify(std::make_pair(method::did_change, info));
    }
};

audio::unit::parameter::parameter(AudioUnitParameterInfo const &info, AudioUnitParameterID const parameter_id,
                                  AudioUnitScope const scope)
    : base(std::make_unique<impl>(info, parameter_id, scope)) {
}

audio::unit::parameter::parameter(std::nullptr_t) : base(nullptr) {
}

#pragma mark - accessor

AudioUnitParameterID audio::unit::parameter::parameter_id() const {
    return impl_ptr<impl>()->_parameter_id;
}

AudioUnitScope audio::unit::parameter::scope() const {
    return impl_ptr<impl>()->_scope;
}

CFStringRef audio::unit::parameter::unit_name() const {
    return to_cf_object(impl_ptr<impl>()->_unit_name);
}

bool audio::unit::parameter::has_clump() const {
    return impl_ptr<impl>()->_has_clump;
}

uint32_t audio::unit::parameter::clump_id() const {
    return impl_ptr<impl>()->_clump_id;
}

CFStringRef audio::unit::parameter::name() const {
    return to_cf_object(impl_ptr<impl>()->_name);
}

AudioUnitParameterUnit audio::unit::parameter::unit() const {
    return impl_ptr<impl>()->_unit;
}

AudioUnitParameterValue audio::unit::parameter::min_value() const {
    return impl_ptr<impl>()->_min_value;
}

AudioUnitParameterValue audio::unit::parameter::max_value() const {
    return impl_ptr<impl>()->_max_value;
}

AudioUnitParameterValue audio::unit::parameter::default_value() const {
    return impl_ptr<impl>()->_default_value;
}

float audio::unit::parameter::value(AudioUnitElement const element) const {
    return impl_ptr<impl>()->_values.at(element);
}

void audio::unit::parameter::set_value(AudioUnitParameterValue const value, AudioUnitElement const element) {
    impl_ptr<impl>()->set_value(value, element);
}

std::unordered_map<AudioUnitElement, AudioUnitParameterValue> const &audio::unit::parameter::values() const {
    return impl_ptr<impl>()->_values;
}

chaining::chain<audio::unit::parameter::chaining_pair_t, audio::unit::parameter::chaining_pair_t,
                audio::unit::parameter::chaining_pair_t, false>
audio::unit::parameter::chain() const {
    return impl_ptr<impl>()->_notifier.chain();
}

chaining::chain<audio::unit::parameter::change_info, audio::unit::parameter::chaining_pair_t,
                audio::unit::parameter::chaining_pair_t, false>
audio::unit::parameter::chain(method const method) const {
    return impl_ptr<impl>()
        ->_notifier.chain()
        .guard([method](auto const &pair) { return pair.first == method; })
        .to([](chaining_pair_t const &pair) { return pair.second; });
}

#pragma mark -

std::string yas::to_string(audio::unit::parameter::method const &method) {
    switch (method) {
        case audio::unit::parameter::method::will_change:
            return "will_change";
        case audio::unit::parameter::method::did_change:
            return "did_change";
    }
}

std::ostream &operator<<(std::ostream &os, yas::audio::unit::parameter::method const &value) {
    os << to_string(value);
    return os;
}
<commit_msg>parameter this<commit_after>//
//  yas_audio_unit_parameter.cpp
//

#include "yas_audio_unit.h"
#include "yas_cf_utils.h"

using namespace yas;

struct audio::unit::parameter::impl : base::impl {
    AudioUnitParameterID _parameter_id;
    AudioUnitScope _scope;
    bool _has_clump;
    uint32_t _clump_id;
    AudioUnitParameterUnit _unit;
    AudioUnitParameterValue _min_value;
    AudioUnitParameterValue _max_value;
    AudioUnitParameterValue _default_value;
    std::unordered_map<AudioUnitElement, AudioUnitParameterValue> _values;
    std::string _unit_name;
    std::string _name;
    chaining::notifier<chaining_pair_t> _notifier;

    impl(AudioUnitParameterInfo const &info, AudioUnitParameterID const parameter_id, AudioUnitScope const scope)
        : _parameter_id(parameter_id),
          _scope(scope),
          _has_clump(info.flags & kAudioUnitParameterFlag_HasClump),
          _clump_id(info.clumpID),
          _unit(info.unit),
          _min_value(info.minValue),
          _max_value(info.maxValue),
          _default_value(info.defaultValue),
          _unit_name(to_string(info.unitName)),
          _name(to_string(info.cfNameString)) {
    }

    ~impl() {
    }

    void set_value(AudioUnitParameterValue const value, AudioUnitElement const element) {
        change_info info{
            .element = element,
            .old_value = this->_values[element],
            .new_value = value,
            .parameter = cast<audio::unit::parameter>(),
        };

        this->_notifier.notify(std::make_pair(method::will_change, info));
        this->_values[element] = value;
        this->_notifier.notify(std::make_pair(method::did_change, info));
    }
};

audio::unit::parameter::parameter(AudioUnitParameterInfo const &info, AudioUnitParameterID const parameter_id,
                                  AudioUnitScope const scope)
    : base(std::make_unique<impl>(info, parameter_id, scope)) {
}

audio::unit::parameter::parameter(std::nullptr_t) : base(nullptr) {
}

#pragma mark - accessor

AudioUnitParameterID audio::unit::parameter::parameter_id() const {
    return impl_ptr<impl>()->_parameter_id;
}

AudioUnitScope audio::unit::parameter::scope() const {
    return impl_ptr<impl>()->_scope;
}

CFStringRef audio::unit::parameter::unit_name() const {
    return to_cf_object(impl_ptr<impl>()->_unit_name);
}

bool audio::unit::parameter::has_clump() const {
    return impl_ptr<impl>()->_has_clump;
}

uint32_t audio::unit::parameter::clump_id() const {
    return impl_ptr<impl>()->_clump_id;
}

CFStringRef audio::unit::parameter::name() const {
    return to_cf_object(impl_ptr<impl>()->_name);
}

AudioUnitParameterUnit audio::unit::parameter::unit() const {
    return impl_ptr<impl>()->_unit;
}

AudioUnitParameterValue audio::unit::parameter::min_value() const {
    return impl_ptr<impl>()->_min_value;
}

AudioUnitParameterValue audio::unit::parameter::max_value() const {
    return impl_ptr<impl>()->_max_value;
}

AudioUnitParameterValue audio::unit::parameter::default_value() const {
    return impl_ptr<impl>()->_default_value;
}

float audio::unit::parameter::value(AudioUnitElement const element) const {
    return impl_ptr<impl>()->_values.at(element);
}

void audio::unit::parameter::set_value(AudioUnitParameterValue const value, AudioUnitElement const element) {
    impl_ptr<impl>()->set_value(value, element);
}

std::unordered_map<AudioUnitElement, AudioUnitParameterValue> const &audio::unit::parameter::values() const {
    return impl_ptr<impl>()->_values;
}

chaining::chain<audio::unit::parameter::chaining_pair_t, audio::unit::parameter::chaining_pair_t,
                audio::unit::parameter::chaining_pair_t, false>
audio::unit::parameter::chain() const {
    return impl_ptr<impl>()->_notifier.chain();
}

chaining::chain<audio::unit::parameter::change_info, audio::unit::parameter::chaining_pair_t,
                audio::unit::parameter::chaining_pair_t, false>
audio::unit::parameter::chain(method const method) const {
    return impl_ptr<impl>()
        ->_notifier.chain()
        .guard([method](auto const &pair) { return pair.first == method; })
        .to([](chaining_pair_t const &pair) { return pair.second; });
}

#pragma mark -

std::string yas::to_string(audio::unit::parameter::method const &method) {
    switch (method) {
        case audio::unit::parameter::method::will_change:
            return "will_change";
        case audio::unit::parameter::method::did_change:
            return "did_change";
    }
}

std::ostream &operator<<(std::ostream &os, yas::audio::unit::parameter::method const &value) {
    os << to_string(value);
    return os;
}
<|endoftext|>