<commit_before>// Copyright (c) 2009 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.

#include "views/widget/drop_target_gtk.h"

#include <algorithm>
#include <iterator>
#include <string>
#include <vector>

#include "base/file_path.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_util.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/gtk_dnd_util.h"
#include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
#include "ui/gfx/point.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

using ui::OSExchangeData;

namespace {

std::string GdkAtomToString(GdkAtom atom) {
  gchar* c_name = gdk_atom_name(atom);
  std::string name(c_name);
  g_free(c_name);
  return name;
}

// Returns true if |name| is a known name of plain text.
bool IsTextType(const std::string& name) {
  return name == "text/plain" || name == "TEXT" ||
         name == "STRING" || name == "UTF8_STRING" ||
         name == "text/plain;charset=utf-8";
}

// Returns the OSExchangeData::Formats in |targets| and all the
// OSExchangeData::CustomFormats in |type_set|.
int CalculateTypes(GList* targets, std::set<GdkAtom>* type_set) {
  int types = 0;
  for (GList* element = targets; element;
       element = g_list_next(element)) {
    GdkAtom atom = static_cast<GdkAtom>(element->data);
    type_set->insert(atom);
    if (atom == GDK_TARGET_STRING) {
      types |= OSExchangeData::STRING;
    } else if (atom == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
      types |= OSExchangeData::URL;
    } else if (atom == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
      // TEXT_URI_LIST is used for files as well as urls.
      types |= OSExchangeData::URL | OSExchangeData::FILE_NAME;
    } else {
      std::string target_name = GdkAtomToString(atom);
      if (IsTextType(target_name)) {
        types |= OSExchangeData::STRING;
      } else {
        // Assume any unknown data is pickled.
        types |= OSExchangeData::PICKLED_DATA;
      }
    }
  }
  return types;
}

}  // namespace

namespace views {

DropTargetGtk::DropTargetGtk(RootView* root_view,
                             GdkDragContext* context)
    : helper_(root_view),
      requested_formats_(0),
      waiting_for_data_(false),
      received_drop_(false),
      pending_view_(NULL) {
  std::set<GdkAtom> all_formats;
  int source_formats = CalculateTypes(context->targets, &all_formats);
  data_.reset(new OSExchangeData(new OSExchangeDataProviderGtk(
                                     source_formats, all_formats)));
}

DropTargetGtk::~DropTargetGtk() {
}

void DropTargetGtk::ResetTargetViewIfEquals(View* view) {
  helper_.ResetTargetViewIfEquals(view);
}

void DropTargetGtk::OnDragDataReceived(GdkDragContext* context,
                                       gint x,
                                       gint y,
                                       GtkSelectionData* data,
                                       guint info,
                                       guint time) {
  std::string target_name = GdkAtomToString(data->type);
  if (data->type == GDK_TARGET_STRING || IsTextType(target_name)) {
    guchar* text_data = gtk_selection_data_get_text(data);
    string16 result;
    if (text_data) {
      char* as_char = reinterpret_cast<char*>(text_data);
      UTF8ToUTF16(as_char, strlen(as_char), &result);
      g_free(text_data);
    }
    data_provider().SetString(result);
  } else if (requested_custom_formats_.find(data->type) !=
             requested_custom_formats_.end()) {
    Pickle result;
    if (data->length > 0)
      result = Pickle(reinterpret_cast<char*>(data->data), data->length);
    data_provider().SetPickledData(data->type, result);
  } else if (data->type == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
    GURL url;
    string16 title;
    ui::ExtractNamedURL(data, &url, &title);
    data_provider().SetURL(url, title);
  } else if (data->type == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
    std::vector<GURL> urls;
    ui::ExtractURIList(data, &urls);
    if (urls.size() == 1 && urls[0].is_valid()) {
      data_provider().SetURL(urls[0], string16());

      // TEXT_URI_LIST is used for files as well as urls.
      if (urls[0].SchemeIsFile()) {
        FilePath file_path;
        if (net::FileURLToFilePath(urls[0], &file_path))
          data_provider().SetFilename(file_path);
      }
    } else {
      // Consumers of OSExchangeData will see this as an invalid URL. That is,
      // when GetURL is invoked on the OSExchangeData this triggers false to
      // be returned.
      data_provider().SetURL(GURL(), string16());
    }
  }

  if (!data_->HasAllFormats(requested_formats_, requested_custom_formats_))
    return;  // Waiting on more data.

  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  gfx::Point root_view_location(x, y);
  drag_operation = helper_.OnDragOver(*data_, root_view_location,
                                      drag_operation);
  GdkDragAction gdk_action = static_cast<GdkDragAction>(
      ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
  if (!received_drop_)
    gdk_drag_status(context, gdk_action, time);

  waiting_for_data_ = false;

  if (pending_view_ && received_drop_) {
    FinishDrop(context, x, y, time);
    // WARNING: we've been deleted.
    return;
  }
}

gboolean DropTargetGtk::OnDragDrop(GdkDragContext* context,
                                   gint x,
                                   gint y,
                                   guint time) {
  received_drop_ = true;
  OnDragMotion(context, x, y, time);
  if (!pending_view_) {
    // User isn't over a view, no drop can occur.
    static_cast<WidgetGtk*>(
        helper_.root_view()->GetWidget())->ResetDropTarget();
    // WARNING: we've been deleted.
    return FALSE;
  }

  if (!waiting_for_data_) {
    // We've got all the data now.
    FinishDrop(context, x, y, time);
    // WARNING: we've been deleted.
    return TRUE;
  }
  // We're waiting on data.
  return TRUE;
}

void DropTargetGtk::OnDragLeave(GdkDragContext* context, guint time) {
  helper_.OnDragExit();
}

gboolean DropTargetGtk::OnDragMotion(GdkDragContext* context,
                                     gint x,
                                     gint y,
                                     guint time) {
  waiting_for_data_ = false;
  gfx::Point root_view_location(x, y);
  pending_view_ =
      helper_.CalculateTargetView(root_view_location, *data_, false);
  if (pending_view_ &&
      (received_drop_ || (pending_view_ != helper_.target_view() &&
                          pending_view_->AreDropTypesRequired()))) {
    // The target requires drop types before it can answer CanDrop,
    // ask for the data now.
    int formats = 0;
    std::set<GdkAtom> custom_formats;
    pending_view_->GetDropFormats(&formats, &custom_formats);
    IntersectFormats(data_provider().known_formats(),
                     data_provider().known_custom_formats(),
                     &formats, &custom_formats);
    if (!data_provider().HasDataForAllFormats(formats, custom_formats)) {
      if (!received_drop_)
        helper_.OnDragExit();

      // The target needs data for all the types before it can test if the
      // drop is valid, but we don't have all the data. Request the data
      // now. When we get back the data we'll update the target.
      RequestFormats(context, formats, custom_formats, time);

      waiting_for_data_ = true;

      return TRUE;
    }
  }

  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  drag_operation = helper_.OnDragOver(*data_, root_view_location,
                                      drag_operation);
  if (!received_drop_) {
    GdkDragAction gdk_action =
        static_cast<GdkDragAction>(
            ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
    gdk_drag_status(context, gdk_action, time);
  }
  return TRUE;
}

void DropTargetGtk::FinishDrop(GdkDragContext* context,
                               gint x, gint y, guint time) {
  gfx::Point root_view_location(x, y);
  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  drag_operation = helper_.OnDrop(*data_, root_view_location,
                                  drag_operation);
  GdkDragAction gdk_action =
      static_cast<GdkDragAction>(
          ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
  gtk_drag_finish(context, gdk_action != 0, (gdk_action & GDK_ACTION_MOVE),
                  time);

  static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())->ResetDropTarget();
  // WARNING: we've been deleted.
}

void DropTargetGtk::IntersectFormats(int f1, const std::set<GdkAtom>& cf1,
                                     int* f2, std::set<GdkAtom>* cf2) {
  *f2 = (*f2 & f1);
  std::set<GdkAtom> cf;
  std::set_intersection(
      cf1.begin(), cf1.end(), cf2->begin(), cf2->end(),
      std::insert_iterator<std::set<GdkAtom> >(cf, cf.begin()));
  cf.swap(*cf2);
}

void DropTargetGtk::RequestFormats(GdkDragContext* context,
                                   int formats,
                                   const std::set<GdkAtom>& custom_formats,
                                   guint time) {
  GtkWidget* widget =
      static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())->
      window_contents();

  const std::set<GdkAtom>& known_formats =
      data_provider().known_custom_formats();
  if ((formats & OSExchangeData::STRING) != 0 &&
      (requested_formats_ & OSExchangeData::STRING) == 0) {
    requested_formats_ |= OSExchangeData::STRING;
    if (known_formats.count(GDK_TARGET_STRING)) {
      gtk_drag_get_data(widget, context, GDK_TARGET_STRING, time);
    } else if (known_formats.count(gdk_atom_intern("text/plain", false))) {
      gtk_drag_get_data(widget, context, gdk_atom_intern("text/plain", false),
                        time);
    } else if (known_formats.count(gdk_atom_intern("text/plain;charset=utf-8",
                                                   false))) {
      gtk_drag_get_data(widget, context,
                        gdk_atom_intern("text/plain;charset=utf-8", false),
                        time);
    } else if (known_formats.count(gdk_atom_intern("TEXT", false))) {
        gtk_drag_get_data(widget, context, gdk_atom_intern("TEXT", false),
                          time);
    } else if (known_formats.count(gdk_atom_intern("STRING", false))) {
      gtk_drag_get_data(widget, context, gdk_atom_intern("STRING", false),
                        time);
    } else if (known_formats.count(gdk_atom_intern("UTF8_STRING", false))) {
      gtk_drag_get_data(widget, context,
                        gdk_atom_intern("UTF8_STRING", false), time);
    }
  }
  if ((formats & OSExchangeData::URL) != 0 &&
      (requested_formats_ & OSExchangeData::URL) == 0) {
    requested_formats_ |= OSExchangeData::URL;
    if (known_formats.count(ui::GetAtomForTarget(ui::CHROME_NAMED_URL))) {
      gtk_drag_get_data(widget, context,
                        ui::GetAtomForTarget(ui::CHROME_NAMED_URL), time);
    } else if (known_formats.count(
                   ui::GetAtomForTarget(ui::TEXT_URI_LIST))) {
      gtk_drag_get_data(widget, context,
                        ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
    }
  }
  if (((formats & OSExchangeData::FILE_NAME) != 0) &&
      (requested_formats_ & OSExchangeData::FILE_NAME) == 0) {
    requested_formats_ |= OSExchangeData::FILE_NAME;
    gtk_drag_get_data(widget, context,
                      ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
  }
  for (std::set<GdkAtom>::const_iterator i = custom_formats.begin();
       i != custom_formats.end(); ++i) {
    if (requested_custom_formats_.find(*i) ==
        requested_custom_formats_.end()) {
      requested_custom_formats_.insert(*i);
      gtk_drag_get_data(widget, context, *i, time);
    }
  }
}

OSExchangeDataProviderGtk& DropTargetGtk::data_provider() const {
  return static_cast<OSExchangeDataProviderGtk&>(data_->provider());
}

}  // namespace views
<commit_msg>Prefer UTF8 strings over ASCII strings when requesting text from a drag and drop operation<commit_after>// Copyright (c) 2011 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.

#include "views/widget/drop_target_gtk.h"

#include <algorithm>
#include <iterator>
#include <string>
#include <vector>

#include "base/file_path.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_util.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/gtk_dnd_util.h"
#include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
#include "ui/gfx/point.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

using ui::OSExchangeData;

namespace {

std::string GdkAtomToString(GdkAtom atom) {
  gchar* c_name = gdk_atom_name(atom);
  std::string name(c_name);
  g_free(c_name);
  return name;
}

// Returns true if |name| is a known name of plain text.
bool IsTextType(const std::string& name) {
  return name == "text/plain" || name == "TEXT" ||
         name == "STRING" || name == "UTF8_STRING" ||
         name == "text/plain;charset=utf-8";
}

// Returns the OSExchangeData::Formats in |targets| and all the
// OSExchangeData::CustomFormats in |type_set|.
int CalculateTypes(GList* targets, std::set<GdkAtom>* type_set) {
  int types = 0;
  for (GList* element = targets; element;
       element = g_list_next(element)) {
    GdkAtom atom = static_cast<GdkAtom>(element->data);
    type_set->insert(atom);
    if (atom == GDK_TARGET_STRING) {
      types |= OSExchangeData::STRING;
    } else if (atom == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
      types |= OSExchangeData::URL;
    } else if (atom == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
      // TEXT_URI_LIST is used for files as well as urls.
      types |= OSExchangeData::URL | OSExchangeData::FILE_NAME;
    } else {
      std::string target_name = GdkAtomToString(atom);
      if (IsTextType(target_name)) {
        types |= OSExchangeData::STRING;
      } else {
        // Assume any unknown data is pickled.
        types |= OSExchangeData::PICKLED_DATA;
      }
    }
  }
  return types;
}

}  // namespace

namespace views {

DropTargetGtk::DropTargetGtk(RootView* root_view,
                             GdkDragContext* context)
    : helper_(root_view),
      requested_formats_(0),
      waiting_for_data_(false),
      received_drop_(false),
      pending_view_(NULL) {
  std::set<GdkAtom> all_formats;
  int source_formats = CalculateTypes(context->targets, &all_formats);
  data_.reset(new OSExchangeData(new OSExchangeDataProviderGtk(
                                     source_formats, all_formats)));
}

DropTargetGtk::~DropTargetGtk() {
}

void DropTargetGtk::ResetTargetViewIfEquals(View* view) {
  helper_.ResetTargetViewIfEquals(view);
}

void DropTargetGtk::OnDragDataReceived(GdkDragContext* context,
                                       gint x,
                                       gint y,
                                       GtkSelectionData* data,
                                       guint info,
                                       guint time) {
  std::string target_name = GdkAtomToString(data->type);
  if (data->type == GDK_TARGET_STRING || IsTextType(target_name)) {
    guchar* text_data = gtk_selection_data_get_text(data);
    string16 result;
    if (text_data) {
      char* as_char = reinterpret_cast<char*>(text_data);
      UTF8ToUTF16(as_char, strlen(as_char), &result);
      g_free(text_data);
    }
    data_provider().SetString(result);
  } else if (requested_custom_formats_.find(data->type) !=
             requested_custom_formats_.end()) {
    Pickle result;
    if (data->length > 0)
      result = Pickle(reinterpret_cast<char*>(data->data), data->length);
    data_provider().SetPickledData(data->type, result);
  } else if (data->type == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
    GURL url;
    string16 title;
    ui::ExtractNamedURL(data, &url, &title);
    data_provider().SetURL(url, title);
  } else if (data->type == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
    std::vector<GURL> urls;
    ui::ExtractURIList(data, &urls);
    if (urls.size() == 1 && urls[0].is_valid()) {
      data_provider().SetURL(urls[0], string16());

      // TEXT_URI_LIST is used for files as well as urls.
      if (urls[0].SchemeIsFile()) {
        FilePath file_path;
        if (net::FileURLToFilePath(urls[0], &file_path))
          data_provider().SetFilename(file_path);
      }
    } else {
      // Consumers of OSExchangeData will see this as an invalid URL. That is,
      // when GetURL is invoked on the OSExchangeData this triggers false to
      // be returned.
      data_provider().SetURL(GURL(), string16());
    }
  }

  if (!data_->HasAllFormats(requested_formats_, requested_custom_formats_))
    return;  // Waiting on more data.

  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  gfx::Point root_view_location(x, y);
  drag_operation = helper_.OnDragOver(*data_, root_view_location,
                                      drag_operation);
  GdkDragAction gdk_action = static_cast<GdkDragAction>(
      ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
  if (!received_drop_)
    gdk_drag_status(context, gdk_action, time);

  waiting_for_data_ = false;

  if (pending_view_ && received_drop_) {
    FinishDrop(context, x, y, time);
    // WARNING: we've been deleted.
    return;
  }
}

gboolean DropTargetGtk::OnDragDrop(GdkDragContext* context,
                                   gint x,
                                   gint y,
                                   guint time) {
  received_drop_ = true;
  OnDragMotion(context, x, y, time);
  if (!pending_view_) {
    // User isn't over a view, no drop can occur.
    static_cast<WidgetGtk*>(
        helper_.root_view()->GetWidget())->ResetDropTarget();
    // WARNING: we've been deleted.
    return FALSE;
  }

  if (!waiting_for_data_) {
    // We've got all the data now.
    FinishDrop(context, x, y, time);
    // WARNING: we've been deleted.
    return TRUE;
  }
  // We're waiting on data.
  return TRUE;
}

void DropTargetGtk::OnDragLeave(GdkDragContext* context, guint time) {
  helper_.OnDragExit();
}

gboolean DropTargetGtk::OnDragMotion(GdkDragContext* context,
                                     gint x,
                                     gint y,
                                     guint time) {
  waiting_for_data_ = false;
  gfx::Point root_view_location(x, y);
  pending_view_ =
      helper_.CalculateTargetView(root_view_location, *data_, false);
  if (pending_view_ &&
      (received_drop_ || (pending_view_ != helper_.target_view() &&
                          pending_view_->AreDropTypesRequired()))) {
    // The target requires drop types before it can answer CanDrop,
    // ask for the data now.
    int formats = 0;
    std::set<GdkAtom> custom_formats;
    pending_view_->GetDropFormats(&formats, &custom_formats);
    IntersectFormats(data_provider().known_formats(),
                     data_provider().known_custom_formats(),
                     &formats, &custom_formats);
    if (!data_provider().HasDataForAllFormats(formats, custom_formats)) {
      if (!received_drop_)
        helper_.OnDragExit();

      // The target needs data for all the types before it can test if the
      // drop is valid, but we don't have all the data. Request the data
      // now. When we get back the data we'll update the target.
      RequestFormats(context, formats, custom_formats, time);

      waiting_for_data_ = true;

      return TRUE;
    }
  }

  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  drag_operation = helper_.OnDragOver(*data_, root_view_location,
                                      drag_operation);
  if (!received_drop_) {
    GdkDragAction gdk_action =
        static_cast<GdkDragAction>(
            ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
    gdk_drag_status(context, gdk_action, time);
  }
  return TRUE;
}

void DropTargetGtk::FinishDrop(GdkDragContext* context,
                               gint x, gint y, guint time) {
  gfx::Point root_view_location(x, y);
  int drag_operation = ui::DragDropTypes::GdkDragActionToDragOperation(
      context->actions);
  drag_operation = helper_.OnDrop(*data_, root_view_location,
                                  drag_operation);
  GdkDragAction gdk_action =
      static_cast<GdkDragAction>(
          ui::DragDropTypes::DragOperationToGdkDragAction(drag_operation));
  gtk_drag_finish(context, gdk_action != 0, (gdk_action & GDK_ACTION_MOVE),
                  time);

  static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())->ResetDropTarget();
  // WARNING: we've been deleted.
}

void DropTargetGtk::IntersectFormats(int f1, const std::set<GdkAtom>& cf1,
                                     int* f2, std::set<GdkAtom>* cf2) {
  *f2 = (*f2 & f1);
  std::set<GdkAtom> cf;
  std::set_intersection(
      cf1.begin(), cf1.end(), cf2->begin(), cf2->end(),
      std::insert_iterator<std::set<GdkAtom> >(cf, cf.begin()));
  cf.swap(*cf2);
}

void DropTargetGtk::RequestFormats(GdkDragContext* context,
                                   int formats,
                                   const std::set<GdkAtom>& custom_formats,
                                   guint time) {
  GtkWidget* widget =
      static_cast<WidgetGtk*>(helper_.root_view()->GetWidget())->
      window_contents();

  const std::set<GdkAtom>& known_formats =
      data_provider().known_custom_formats();
  if ((formats & OSExchangeData::STRING) != 0 &&
      (requested_formats_ & OSExchangeData::STRING) == 0) {
    requested_formats_ |= OSExchangeData::STRING;
    if (known_formats.count(gdk_atom_intern("UTF8_STRING", false))) {
      gtk_drag_get_data(widget, context,
                        gdk_atom_intern("UTF8_STRING", false), time);
    } else if (known_formats.count(gdk_atom_intern("text/plain;charset=utf-8",
                                                   false))) {
      gtk_drag_get_data(widget, context,
                        gdk_atom_intern("text/plain;charset=utf-8", false),
                        time);
    } else if (known_formats.count(GDK_TARGET_STRING)) {
      gtk_drag_get_data(widget, context, GDK_TARGET_STRING, time);
    } else if (known_formats.count(gdk_atom_intern("text/plain", false))) {
      gtk_drag_get_data(widget, context, gdk_atom_intern("text/plain", false),
                        time);
    } else if (known_formats.count(gdk_atom_intern("TEXT", false))) {
        gtk_drag_get_data(widget, context, gdk_atom_intern("TEXT", false),
                          time);
    } else if (known_formats.count(gdk_atom_intern("STRING", false))) {
      gtk_drag_get_data(widget, context, gdk_atom_intern("STRING", false),
                        time);
    }
  }
  if ((formats & OSExchangeData::URL) != 0 &&
      (requested_formats_ & OSExchangeData::URL) == 0) {
    requested_formats_ |= OSExchangeData::URL;
    if (known_formats.count(ui::GetAtomForTarget(ui::CHROME_NAMED_URL))) {
      gtk_drag_get_data(widget, context,
                        ui::GetAtomForTarget(ui::CHROME_NAMED_URL), time);
    } else if (known_formats.count(
                   ui::GetAtomForTarget(ui::TEXT_URI_LIST))) {
      gtk_drag_get_data(widget, context,
                        ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
    }
  }
  if (((formats & OSExchangeData::FILE_NAME) != 0) &&
      (requested_formats_ & OSExchangeData::FILE_NAME) == 0) {
    requested_formats_ |= OSExchangeData::FILE_NAME;
    gtk_drag_get_data(widget, context,
                      ui::GetAtomForTarget(ui::TEXT_URI_LIST), time);
  }
  for (std::set<GdkAtom>::const_iterator i = custom_formats.begin();
       i != custom_formats.end(); ++i) {
    if (requested_custom_formats_.find(*i) ==
        requested_custom_formats_.end()) {
      requested_custom_formats_.insert(*i);
      gtk_drag_get_data(widget, context, *i, time);
    }
  }
}

OSExchangeDataProviderGtk& DropTargetGtk::data_provider() const {
  return static_cast<OSExchangeDataProviderGtk&>(data_->provider());
}

}  // namespace views
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/tf2xla/xla_op_registry.h"

#include <functional>
#include <memory>

#include "tensorflow/compiler/tf2xla/type_util.h"
#include "tensorflow/compiler/tf2xla/xla_context.h"
#include "tensorflow/compiler/xla/client/client_library.h"
#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/framework/device_base.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/stream_executor_no_cuda.h"

namespace tensorflow {

const char* const DEVICE_CPU_XLA_JIT = "XLA_CPU_JIT";
const char* const DEVICE_GPU_XLA_JIT = "XLA_GPU_JIT";

// Is platform 'id' supported by XLA?
static bool IsPlatformSupported(perftools::gputools::Platform::Id id) {
  auto platform = perftools::gputools::MultiPlatformManager::PlatformWithId(id);
  if (!platform.ok()) return false;
  return xla::ClientLibrary::GetOrCreateLocalClient(platform.ValueOrDie()).ok();
}

XlaOpRegistry::XlaOpRegistry() = default;
XlaOpRegistry::~XlaOpRegistry() = default;

/* static */ void XlaOpRegistry::RegisterCompilationDevice(
    const string& device_name, const DeviceRegistration& registration) {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto result =
      registry.compilation_devices_.emplace(device_name, registration);
  CHECK(result.second || result.first->second.compilation_device_name ==
                             registration.compilation_device_name);
}

/* static */ void XlaOpRegistry::RegisterBackend(
    const string& compilation_device_name,
    gtl::ArraySlice<DataType> supported_types, BackendOpFilter op_filter) {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto result = registry.backends_.emplace(compilation_device_name, Backend());
  CHECK(result.second) << "Duplicate XLA backend registration "
                       << compilation_device_name;
  result.first->second.supported_types.insert(supported_types.begin(),
                                              supported_types.end());
  result.first->second.op_filter = op_filter;
}

/* static */ bool XlaOpRegistry::GetCompilationDevice(
    const string& device_name, const DeviceRegistration** registration) {
  XlaOpRegistry& registry = Instance();

  // Lazily register the CPU and GPU JIT devices the first time
  // GetCompilationDevice is called.
  static void* registration_init = [&registry]() {
    mutex_lock lock(registry.mutex_);
    if (IsPlatformSupported(perftools::gputools::host::kHostPlatformId)) {
      DeviceRegistration& registration =
          registry.compilation_devices_[DEVICE_CPU];
      registration.compilation_device_name = DEVICE_CPU_XLA_JIT;
      registration.requires_compilation = false;
      registration.enable_jit_by_default = false;
      registration.compile_resource_ops = false;
    }
    if (IsPlatformSupported(perftools::gputools::cuda::kCudaPlatformId)) {
      DeviceRegistration& registration =
          registry.compilation_devices_[DEVICE_GPU];
      registration.compilation_device_name = DEVICE_GPU_XLA_JIT;
      registration.requires_compilation = false;
      registration.enable_jit_by_default = true;
      registration.compile_resource_ops = false;
    }
    return nullptr;
  }();
  (void)registration_init;

  mutex_lock lock(registry.mutex_);
  auto it = registry.compilation_devices_.find(device_name);
  if (it == registry.compilation_devices_.end()) return false;
  *registration = &it->second;
  return true;
}

void XlaOpRegistry::RegisterCompilationKernels() {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);

  if (registry.jit_kernels_registered_) return;
  registry.jit_kernels_registered_ = true;

  OpRegistryInterface* op_registry = OpRegistry::Global();
  for (const auto& op : registry.ops_) {
    const OpDef* op_def;
    TF_CHECK_OK(op_registry->LookUpOpDef(op.first, &op_def));

    std::unordered_set<string> type_attrs;
    for (const OpDef::AttrDef& attr_def : op_def->attr()) {
      if (attr_def.type() == "type" || attr_def.type() == "list(type)") {
        type_attrs.insert(attr_def.name());
      }
    }

    // Checks there are no type constraints referring to unknown attributes.
    for (const auto& constraint : op.second->type_constraints) {
      if (type_attrs.find(constraint.first) == type_attrs.end()) {
        LOG(FATAL) << "Unknown type attribute " << constraint.first
                   << " in XLA op registration for " << op.first;
      }
    }

    for (auto& backend : registry.backends_) {
      // If the operator has a device whitelist, only register on whitelisted
      // devices.
      if (op.second->has_device_whitelist &&
          op.second->device_whitelist.find(backend.first) ==
              op.second->device_whitelist.end()) {
        continue;
      }

      std::unique_ptr<KernelDef> kdef(new KernelDef);
      kdef->set_op(op.second->name);
      kdef->set_device_type(backend.first);

      // Constrain each type attribute to the intersection of:
      // a) the types supported by the backend, and
      // b) the attribute's type constraints.
      // TODO(phawkins): it may be necessary to also take the intersection with
      // the set of types supported by the OpDef.
      for (const string& type_attr : type_attrs) {
        KernelDef::AttrConstraint* attr_constraint = kdef->add_constraint();
        attr_constraint->set_name(type_attr);
        auto* allowed_values =
            attr_constraint->mutable_allowed_values()->mutable_list();

        auto it = op.second->type_constraints.find(type_attr);
        for (DataType dtype : backend.second.supported_types) {
          if (it == op.second->type_constraints.end() ||
              (it != op.second->type_constraints.end() &&
               it->second.find(dtype) != it->second.end())) {
            allowed_values->add_type(dtype);
          }
        }
        if (op.second->allow_resource_types) {
          allowed_values->add_type(DT_RESOURCE);
        }
      }
      if (backend.second.op_filter != nullptr &&
          !backend.second.op_filter(kdef.get())) {
        continue;
      }
      registry.kernel_registrars_.emplace_back(
          new kernel_factory::OpKernelRegistrar(
              new KernelDef(*kdef), "XlaJitOp", op.second->factory));
      backend.second.kernel_defs.push_back(std::move(kdef));
    }
  }
}

std::vector<const KernelDef*> XlaOpRegistry::DeviceKernels(
    const string& compilation_device_name) {
  std::vector<const KernelDef*> kernels;
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto it = registry.backends_.find(compilation_device_name);
  CHECK(it != registry.backends_.end())
      << "Unknown backend " << compilation_device_name;
  for (const std::unique_ptr<KernelDef>& k : it->second.kernel_defs) {
    if (!registry.ops_.at(k->op())->compilation_only) {
      kernels.push_back(k.get());
    }
  }
  return kernels;
}

XlaOpRegistry& XlaOpRegistry::Instance() {
  static XlaOpRegistry* r = new XlaOpRegistry;
  return *r;
}

XlaOpRegistrationBuilder::XlaOpRegistrationBuilder(StringPiece name) {
  registration_.reset(new XlaOpRegistry::OpRegistration);
  registration_->name = name.ToString();
}

XlaOpRegistrationBuilder XlaOpRegistrationBuilder::Name(StringPiece name) {
  XlaOpRegistrationBuilder registration(name);
  return registration;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::Device(
    gtl::ArraySlice<StringPiece> devices) {
  registration_->has_device_whitelist = true;
  for (StringPiece device : devices) {
    registration_->device_whitelist.insert(device.ToString());
  }
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::Device(StringPiece device) {
  registration_->has_device_whitelist = true;
  registration_->device_whitelist.insert(device.ToString());
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::CompilationOnly() {
  registration_->compilation_only = true;
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::AllowResourceTypes() {
  registration_->allow_resource_types = true;
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::TypeConstraint(
    StringPiece attr_name, DataType allowed) {
  std::set<DataType>& types =
      registration_->type_constraints[attr_name.ToString()];
  types.insert(allowed);
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::TypeConstraint(
    StringPiece attr_name, gtl::ArraySlice<DataType> allowed) {
  std::set<DataType>& types =
      registration_->type_constraints[attr_name.ToString()];
  for (DataType t : allowed) {
    types.insert(t);
  }
  return *this;
}

std::unique_ptr<XlaOpRegistry::OpRegistration> XlaOpRegistrationBuilder::Build(
    XlaOpRegistry::Factory factory) {
  registration_->factory = factory;
  return std::move(registration_);
}

XlaOpRegistrar::XlaOpRegistrar(
    std::unique_ptr<XlaOpRegistry::OpRegistration> registration) {
  XlaOpRegistry& registry = XlaOpRegistry::Instance();
  mutex_lock lock(registry.mutex_);
  auto result = registry.ops_.emplace(registration->name, nullptr);
  if (!result.second) {
    LOG(FATAL) << "Duplicate XLA op registration " << registration->name;
  }
  result.first->second = std::move(registration);
}

XlaBackendRegistrar::XlaBackendRegistrar(
    StringPiece name, gtl::ArraySlice<DataType> types,
    XlaOpRegistry::BackendOpFilter op_filter) {
  XlaOpRegistry& registry = XlaOpRegistry::Instance();
  registry.RegisterBackend(name.ToString(), types, op_filter);
}

bool CpuOpFilter(KernelDef* kdef) {
  // TODO(b/34339814): implement inverse erf for double types and remove this
  // workaround.
  if (kdef->op() == "RandomStandardNormal") {
    kdef->clear_constraint();
    // Change the type constraint to permit only DTD_FLOAT.
    KernelDef::AttrConstraint* attr_constraint = kdef->add_constraint();
    attr_constraint->set_name("dtype");
    attr_constraint->mutable_allowed_values()->mutable_list()->add_type(
        DT_FLOAT);
    return true;
  }
  return true;
}

REGISTER_XLA_BACKEND(DEVICE_CPU_XLA_JIT, kCpuAllTypes, CpuOpFilter);

bool GpuOpFilter(KernelDef* kdef) {
  // TODO(b/31361304): The GPU backend does not parallelize PRNG ops, leading to
  // slow code.
  // TODO(b/34969189) The implementation of TruncatedNormal generates illegal
  // code on GPU.
  if (kdef->op() == "RandomStandardNormal" || kdef->op() == "RandomUniform" ||
      kdef->op() == "RandomUniformInt" || kdef->op() == "TruncatedNormal") {
    return false;
  }
  return true;
}

REGISTER_XLA_BACKEND(DEVICE_GPU_XLA_JIT, kGpuAllTypes, GpuOpFilter);

}  // namespace tensorflow
<commit_msg>[TF:XLA] Add a VLOG() to log the operators registered by the XlaOpRegistry. Change: 151877152<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/tf2xla/xla_op_registry.h"

#include <functional>
#include <memory>

#include "tensorflow/compiler/tf2xla/type_util.h"
#include "tensorflow/compiler/tf2xla/xla_context.h"
#include "tensorflow/compiler/xla/client/client_library.h"
#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/common_runtime/local_device.h"
#include "tensorflow/core/framework/device_base.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/stream_executor_no_cuda.h"

namespace tensorflow {

const char* const DEVICE_CPU_XLA_JIT = "XLA_CPU_JIT";
const char* const DEVICE_GPU_XLA_JIT = "XLA_GPU_JIT";

// Is platform 'id' supported by XLA?
static bool IsPlatformSupported(perftools::gputools::Platform::Id id) {
  auto platform = perftools::gputools::MultiPlatformManager::PlatformWithId(id);
  if (!platform.ok()) return false;
  return xla::ClientLibrary::GetOrCreateLocalClient(platform.ValueOrDie()).ok();
}

XlaOpRegistry::XlaOpRegistry() = default;
XlaOpRegistry::~XlaOpRegistry() = default;

/* static */ void XlaOpRegistry::RegisterCompilationDevice(
    const string& device_name, const DeviceRegistration& registration) {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto result =
      registry.compilation_devices_.emplace(device_name, registration);
  CHECK(result.second || result.first->second.compilation_device_name ==
                             registration.compilation_device_name);
}

/* static */ void XlaOpRegistry::RegisterBackend(
    const string& compilation_device_name,
    gtl::ArraySlice<DataType> supported_types, BackendOpFilter op_filter) {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto result = registry.backends_.emplace(compilation_device_name, Backend());
  CHECK(result.second) << "Duplicate XLA backend registration "
                       << compilation_device_name;
  result.first->second.supported_types.insert(supported_types.begin(),
                                              supported_types.end());
  result.first->second.op_filter = op_filter;
}

/* static */ bool XlaOpRegistry::GetCompilationDevice(
    const string& device_name, const DeviceRegistration** registration) {
  XlaOpRegistry& registry = Instance();

  // Lazily register the CPU and GPU JIT devices the first time
  // GetCompilationDevice is called.
  static void* registration_init = [&registry]() {
    mutex_lock lock(registry.mutex_);
    if (IsPlatformSupported(perftools::gputools::host::kHostPlatformId)) {
      DeviceRegistration& registration =
          registry.compilation_devices_[DEVICE_CPU];
      registration.compilation_device_name = DEVICE_CPU_XLA_JIT;
      registration.requires_compilation = false;
      registration.enable_jit_by_default = false;
      registration.compile_resource_ops = false;
    }
    if (IsPlatformSupported(perftools::gputools::cuda::kCudaPlatformId)) {
      DeviceRegistration& registration =
          registry.compilation_devices_[DEVICE_GPU];
      registration.compilation_device_name = DEVICE_GPU_XLA_JIT;
      registration.requires_compilation = false;
      registration.enable_jit_by_default = true;
      registration.compile_resource_ops = false;
    }
    return nullptr;
  }();
  (void)registration_init;

  mutex_lock lock(registry.mutex_);
  auto it = registry.compilation_devices_.find(device_name);
  if (it == registry.compilation_devices_.end()) return false;
  *registration = &it->second;
  return true;
}

void XlaOpRegistry::RegisterCompilationKernels() {
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);

  if (registry.jit_kernels_registered_) return;
  registry.jit_kernels_registered_ = true;

  OpRegistryInterface* op_registry = OpRegistry::Global();
  for (const auto& op : registry.ops_) {
    const OpDef* op_def;
    TF_CHECK_OK(op_registry->LookUpOpDef(op.first, &op_def));

    std::unordered_set<string> type_attrs;
    for (const OpDef::AttrDef& attr_def : op_def->attr()) {
      if (attr_def.type() == "type" || attr_def.type() == "list(type)") {
        type_attrs.insert(attr_def.name());
      }
    }

    // Checks there are no type constraints referring to unknown attributes.
    for (const auto& constraint : op.second->type_constraints) {
      if (type_attrs.find(constraint.first) == type_attrs.end()) {
        LOG(FATAL) << "Unknown type attribute " << constraint.first
                   << " in XLA op registration for " << op.first;
      }
    }

    for (auto& backend : registry.backends_) {
      // If the operator has a device whitelist, only register on whitelisted
      // devices.
      if (op.second->has_device_whitelist &&
          op.second->device_whitelist.find(backend.first) ==
              op.second->device_whitelist.end()) {
        continue;
      }

      std::unique_ptr<KernelDef> kdef(new KernelDef);
      kdef->set_op(op.second->name);
      kdef->set_device_type(backend.first);

      // Constrain each type attribute to the intersection of:
      // a) the types supported by the backend, and
      // b) the attribute's type constraints.
      // TODO(phawkins): it may be necessary to also take the intersection with
      // the set of types supported by the OpDef.
      for (const string& type_attr : type_attrs) {
        KernelDef::AttrConstraint* attr_constraint = kdef->add_constraint();
        attr_constraint->set_name(type_attr);
        auto* allowed_values =
            attr_constraint->mutable_allowed_values()->mutable_list();

        auto it = op.second->type_constraints.find(type_attr);
        for (DataType dtype : backend.second.supported_types) {
          if (it == op.second->type_constraints.end() ||
              (it != op.second->type_constraints.end() &&
               it->second.find(dtype) != it->second.end())) {
            allowed_values->add_type(dtype);
          }
        }
        if (op.second->allow_resource_types) {
          allowed_values->add_type(DT_RESOURCE);
        }
      }
      if (backend.second.op_filter != nullptr &&
          !backend.second.op_filter(kdef.get())) {
        continue;
      }
      VLOG(2) << "XLA op registration: device: " << backend.first
              << " op: " << op.first;
      registry.kernel_registrars_.emplace_back(
          new kernel_factory::OpKernelRegistrar(
              new KernelDef(*kdef), "XlaJitOp", op.second->factory));
      backend.second.kernel_defs.push_back(std::move(kdef));
    }
  }
}

std::vector<const KernelDef*> XlaOpRegistry::DeviceKernels(
    const string& compilation_device_name) {
  std::vector<const KernelDef*> kernels;
  XlaOpRegistry& registry = Instance();
  mutex_lock lock(registry.mutex_);
  auto it = registry.backends_.find(compilation_device_name);
  CHECK(it != registry.backends_.end())
      << "Unknown backend " << compilation_device_name;
  for (const std::unique_ptr<KernelDef>& k : it->second.kernel_defs) {
    if (!registry.ops_.at(k->op())->compilation_only) {
      kernels.push_back(k.get());
    }
  }
  return kernels;
}

XlaOpRegistry& XlaOpRegistry::Instance() {
  static XlaOpRegistry* r = new XlaOpRegistry;
  return *r;
}

XlaOpRegistrationBuilder::XlaOpRegistrationBuilder(StringPiece name) {
  registration_.reset(new XlaOpRegistry::OpRegistration);
  registration_->name = name.ToString();
}

XlaOpRegistrationBuilder XlaOpRegistrationBuilder::Name(StringPiece name) {
  XlaOpRegistrationBuilder registration(name);
  return registration;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::Device(
    gtl::ArraySlice<StringPiece> devices) {
  registration_->has_device_whitelist = true;
  for (StringPiece device : devices) {
    registration_->device_whitelist.insert(device.ToString());
  }
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::Device(StringPiece device) {
  registration_->has_device_whitelist = true;
  registration_->device_whitelist.insert(device.ToString());
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::CompilationOnly() {
  registration_->compilation_only = true;
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::AllowResourceTypes() {
  registration_->allow_resource_types = true;
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::TypeConstraint(
    StringPiece attr_name, DataType allowed) {
  std::set<DataType>& types =
      registration_->type_constraints[attr_name.ToString()];
  types.insert(allowed);
  return *this;
}

XlaOpRegistrationBuilder& XlaOpRegistrationBuilder::TypeConstraint(
    StringPiece attr_name, gtl::ArraySlice<DataType> allowed) {
  std::set<DataType>& types =
      registration_->type_constraints[attr_name.ToString()];
  for (DataType t : allowed) {
    types.insert(t);
  }
  return *this;
}

std::unique_ptr<XlaOpRegistry::OpRegistration> XlaOpRegistrationBuilder::Build(
    XlaOpRegistry::Factory factory) {
  registration_->factory = factory;
  return std::move(registration_);
}

XlaOpRegistrar::XlaOpRegistrar(
    std::unique_ptr<XlaOpRegistry::OpRegistration> registration) {
  XlaOpRegistry& registry = XlaOpRegistry::Instance();
  mutex_lock lock(registry.mutex_);
  auto result = registry.ops_.emplace(registration->name, nullptr);
  if (!result.second) {
    LOG(FATAL) << "Duplicate XLA op registration " << registration->name;
  }
  result.first->second = std::move(registration);
}

XlaBackendRegistrar::XlaBackendRegistrar(
    StringPiece name, gtl::ArraySlice<DataType> types,
    XlaOpRegistry::BackendOpFilter op_filter) {
  XlaOpRegistry& registry = XlaOpRegistry::Instance();
  registry.RegisterBackend(name.ToString(), types, op_filter);
}

bool CpuOpFilter(KernelDef* kdef) {
  // TODO(b/34339814): implement inverse erf for double types and remove this
  // workaround.
  if (kdef->op() == "RandomStandardNormal") {
    kdef->clear_constraint();
    // Change the type constraint to permit only DTD_FLOAT.
    KernelDef::AttrConstraint* attr_constraint = kdef->add_constraint();
    attr_constraint->set_name("dtype");
    attr_constraint->mutable_allowed_values()->mutable_list()->add_type(
        DT_FLOAT);
    return true;
  }
  return true;
}

REGISTER_XLA_BACKEND(DEVICE_CPU_XLA_JIT, kCpuAllTypes, CpuOpFilter);

bool GpuOpFilter(KernelDef* kdef) {
  // TODO(b/31361304): The GPU backend does not parallelize PRNG ops, leading to
  // slow code.
  // TODO(b/34969189) The implementation of TruncatedNormal generates illegal
  // code on GPU.
  if (kdef->op() == "RandomStandardNormal" || kdef->op() == "RandomUniform" ||
      kdef->op() == "RandomUniformInt" || kdef->op() == "TruncatedNormal") {
    return false;
  }
  return true;
}

REGISTER_XLA_BACKEND(DEVICE_GPU_XLA_JIT, kGpuAllTypes, GpuOpFilter);

}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/platform/cpu_feature_guard.h"

#include <mutex>
#include <string>

#include "absl/base/call_once.h"
#include "tensorflow/core/platform/byte_order.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {
namespace port {
namespace {

// If the CPU feature isn't present, log a fatal error.
void CheckFeatureOrDie(CPUFeature feature, const string& feature_name) {
  if (!TestCPUFeature(feature)) {
#ifdef __ANDROID__
    // Some Android emulators seem to indicate they don't support SSE, so to
    // avoid crashes when testing, switch this to a warning.
    LOG(WARNING)
#else
    LOG(FATAL)
#endif
        << "The TensorFlow library was compiled to use " << feature_name
        << " instructions, but these aren't available on your machine.";
  }
}

// Check if CPU feature is included in the TensorFlow binary.
void CheckIfFeatureUnused(CPUFeature feature, const string& feature_name,
                          string& missing_instructions) {
  if (TestCPUFeature(feature)) {
    missing_instructions.append(" ");
    missing_instructions.append(feature_name);
  }
}

// Raises an error if the binary has been compiled for a CPU feature (like AVX)
// that isn't available on the current machine. It also warns of performance
// loss if there's a feature available that's not being used.
// Depending on the compiler and initialization order, a SIGILL exception may
// occur before this code is reached, but this at least offers a chance to give
// a more meaningful error message.
class CPUFeatureGuard {
 public:
  CPUFeatureGuard() {
#ifdef __SSE__
    CheckFeatureOrDie(CPUFeature::SSE, "SSE");
#endif  // __SSE__
#ifdef __SSE2__
    CheckFeatureOrDie(CPUFeature::SSE2, "SSE2");
#endif  // __SSE2__
#ifdef __SSE3__
    CheckFeatureOrDie(CPUFeature::SSE3, "SSE3");
#endif  // __SSE3__
#ifdef __SSE4_1__
    CheckFeatureOrDie(CPUFeature::SSE4_1, "SSE4.1");
#endif  // __SSE4_1__
#ifdef __SSE4_2__
    CheckFeatureOrDie(CPUFeature::SSE4_2, "SSE4.2");
#endif  // __SSE4_2__
#ifdef __AVX__
    CheckFeatureOrDie(CPUFeature::AVX, "AVX");
#endif  // __AVX__
#ifdef __AVX2__
    CheckFeatureOrDie(CPUFeature::AVX2, "AVX2");
#endif  // __AVX2__
#ifdef __AVX512F__
    CheckFeatureOrDie(CPUFeature::AVX512F, "AVX512F");
#endif  // __AVX512F__
#ifdef __FMA__
    CheckFeatureOrDie(CPUFeature::FMA, "FMA");
#endif  // __FMA__
  }
};

CPUFeatureGuard g_cpu_feature_guard_singleton;

absl::once_flag g_cpu_feature_guard_warn_once_flag;

}  // namespace

void InfoAboutUnusedCPUFeatures() {
  absl::call_once(g_cpu_feature_guard_warn_once_flag, [] {
    string missing_instructions;
#if defined(_MSC_VER) && !defined(__clang__)

#ifndef __AVX__
    CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
#endif  // __AVX__
#ifndef __AVX2__
    CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
#endif  // __AVX2__

#else  // if defined(_MSC_VER) && !defined(__clang__)

#ifndef __SSE__
    CheckIfFeatureUnused(CPUFeature::SSE, "SSE", missing_instructions);
#endif  // __SSE__
#ifndef __SSE2__
    CheckIfFeatureUnused(CPUFeature::SSE2, "SSE2", missing_instructions);
#endif  // __SSE2__
#ifndef __SSE3__
    CheckIfFeatureUnused(CPUFeature::SSE3, "SSE3", missing_instructions);
#endif  // __SSE3__
#ifndef __SSE4_1__
    CheckIfFeatureUnused(CPUFeature::SSE4_1, "SSE4.1", missing_instructions);
#endif  // __SSE4_1__
#ifndef __SSE4_2__
    CheckIfFeatureUnused(CPUFeature::SSE4_2, "SSE4.2", missing_instructions);
#endif  // __SSE4_2__
#ifndef __AVX__
    CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
#endif  // __AVX__
#ifndef __AVX2__
    CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
#endif  // __AVX2__
#ifndef __AVX512F__
    CheckIfFeatureUnused(CPUFeature::AVX512F, "AVX512F", missing_instructions);
#endif  // __AVX512F__
#ifndef __FMA__
    CheckIfFeatureUnused(CPUFeature::FMA, "FMA", missing_instructions);
#endif  // __FMA__
#endif  // else of if defined(_MSC_VER) && !defined(__clang__)

    string intel_library_official_name(
        "Intel(R) oneAPI Deep Neural Network Library (oneDNN) ");
#ifndef INTEL_MKL
    intel_library_official_name = "oneAPI Deep Neural Network Library (oneDNN) ";
#endif

        if (!missing_instructions.empty()) {
      LOG(INFO) << "This TensorFlow binary is optimized with "
                << intel_library_official_name
                << "to use the following CPU instructions in performance-"
                << "critical operations: " << missing_instructions << std::endl
                << "To enable them in other operations, rebuild TensorFlow "
                << "with the appropriate compiler flags.";
    }
  });
}

}  // namespace port
}  // namespace tensorflow
<commit_msg>create a single oneDNN string<commit_after>/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/platform/cpu_feature_guard.h"

#include <mutex>
#include <string>

#include "absl/base/call_once.h"
#include "tensorflow/core/platform/byte_order.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {
namespace port {
namespace {

// If the CPU feature isn't present, log a fatal error.
void CheckFeatureOrDie(CPUFeature feature, const string& feature_name) {
  if (!TestCPUFeature(feature)) {
#ifdef __ANDROID__
    // Some Android emulators seem to indicate they don't support SSE, so to
    // avoid crashes when testing, switch this to a warning.
    LOG(WARNING)
#else
    LOG(FATAL)
#endif
        << "The TensorFlow library was compiled to use " << feature_name
        << " instructions, but these aren't available on your machine.";
  }
}

// Check if CPU feature is included in the TensorFlow binary.
void CheckIfFeatureUnused(CPUFeature feature, const string& feature_name,
                          string& missing_instructions) {
  if (TestCPUFeature(feature)) {
    missing_instructions.append(" ");
    missing_instructions.append(feature_name);
  }
}

// Raises an error if the binary has been compiled for a CPU feature (like AVX)
// that isn't available on the current machine. It also warns of performance
// loss if there's a feature available that's not being used.
// Depending on the compiler and initialization order, a SIGILL exception may
// occur before this code is reached, but this at least offers a chance to give
// a more meaningful error message.
class CPUFeatureGuard {
 public:
  CPUFeatureGuard() {
#ifdef __SSE__
    CheckFeatureOrDie(CPUFeature::SSE, "SSE");
#endif  // __SSE__
#ifdef __SSE2__
    CheckFeatureOrDie(CPUFeature::SSE2, "SSE2");
#endif  // __SSE2__
#ifdef __SSE3__
    CheckFeatureOrDie(CPUFeature::SSE3, "SSE3");
#endif  // __SSE3__
#ifdef __SSE4_1__
    CheckFeatureOrDie(CPUFeature::SSE4_1, "SSE4.1");
#endif  // __SSE4_1__
#ifdef __SSE4_2__
    CheckFeatureOrDie(CPUFeature::SSE4_2, "SSE4.2");
#endif  // __SSE4_2__
#ifdef __AVX__
    CheckFeatureOrDie(CPUFeature::AVX, "AVX");
#endif  // __AVX__
#ifdef __AVX2__
    CheckFeatureOrDie(CPUFeature::AVX2, "AVX2");
#endif  // __AVX2__
#ifdef __AVX512F__
    CheckFeatureOrDie(CPUFeature::AVX512F, "AVX512F");
#endif  // __AVX512F__
#ifdef __FMA__
    CheckFeatureOrDie(CPUFeature::FMA, "FMA");
#endif  // __FMA__
  }
};

CPUFeatureGuard g_cpu_feature_guard_singleton;

absl::once_flag g_cpu_feature_guard_warn_once_flag;

}  // namespace

void InfoAboutUnusedCPUFeatures() {
  absl::call_once(g_cpu_feature_guard_warn_once_flag, [] {
    string missing_instructions;
#if defined(_MSC_VER) && !defined(__clang__)

#ifndef __AVX__
    CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
#endif  // __AVX__
#ifndef __AVX2__
    CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
#endif  // __AVX2__

#else  // if defined(_MSC_VER) && !defined(__clang__)

#ifndef __SSE__
    CheckIfFeatureUnused(CPUFeature::SSE, "SSE", missing_instructions);
#endif  // __SSE__
#ifndef __SSE2__
    CheckIfFeatureUnused(CPUFeature::SSE2, "SSE2", missing_instructions);
#endif  // __SSE2__
#ifndef __SSE3__
    CheckIfFeatureUnused(CPUFeature::SSE3, "SSE3", missing_instructions);
#endif  // __SSE3__
#ifndef __SSE4_1__
    CheckIfFeatureUnused(CPUFeature::SSE4_1, "SSE4.1", missing_instructions);
#endif  // __SSE4_1__
#ifndef __SSE4_2__
    CheckIfFeatureUnused(CPUFeature::SSE4_2, "SSE4.2", missing_instructions);
#endif  // __SSE4_2__
#ifndef __AVX__
    CheckIfFeatureUnused(CPUFeature::AVX, "AVX", missing_instructions);
#endif  // __AVX__
#ifndef __AVX2__
    CheckIfFeatureUnused(CPUFeature::AVX2, "AVX2", missing_instructions);
#endif  // __AVX2__
#ifndef __AVX512F__
    CheckIfFeatureUnused(CPUFeature::AVX512F, "AVX512F", missing_instructions);
#endif  // __AVX512F__
#ifndef __FMA__
    CheckIfFeatureUnused(CPUFeature::FMA, "FMA", missing_instructions);
#endif  // __FMA__
#endif  // else of if defined(_MSC_VER) && !defined(__clang__)
    if (!missing_instructions.empty()) {
      LOG(INFO) << "This TensorFlow binary is optimized with "
                << "oneAPI Deep Neural Network Library (oneDNN)"
                << "to use the following CPU instructions in performance-"
                << "critical operations: " << missing_instructions << std::endl
                << "To enable them in other operations, rebuild TensorFlow "
                << "with the appropriate compiler flags.";
    }
  });
}

}  // namespace port
}  // namespace tensorflow
<|endoftext|>


<commit_before>/**
 * \file
 * \brief softwareTimerTestCases object definition
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "softwareTimerTestCases.hpp"

#include "SoftwareTimerOrderingTestCase.hpp"
#include "SoftwareTimerOperationsTestCase.hpp"
#include "SoftwareTimerFunctionTypesTestCase.hpp"

#include "TestCaseGroup.hpp"

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

/// SoftwareTimerOrderingTestCase instance
const SoftwareTimerOrderingTestCase orderingTestCase;

/// SoftwareTimerOperationsTestCase instance
const SoftwareTimerOperationsTestCase operationsTestCase;

/// SoftwareTimerFunctionTypesTestCase instance
const SoftwareTimerFunctionTypesTestCase functionTypesTestCase;

/// array with references to TestCase objects related to software timers
const TestCaseGroup::Range::value_type softwareTimerTestCases_[]
{
		TestCaseGroup::Range::value_type{orderingTestCase},
		TestCaseGroup::Range::value_type{operationsTestCase},
		TestCaseGroup::Range::value_type{functionTypesTestCase},
};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global objects
+---------------------------------------------------------------------------------------------------------------------*/

const TestCaseGroup softwareTimerTestCases {TestCaseGroup::Range{softwareTimerTestCases_}};

}	// namespace test

}	// namespace distortos
<commit_msg>Add SoftwareTimerPeriodicTestCase to executed test cases<commit_after>/**
 * \file
 * \brief softwareTimerTestCases object definition
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "softwareTimerTestCases.hpp"

#include "SoftwareTimerOrderingTestCase.hpp"
#include "SoftwareTimerOperationsTestCase.hpp"
#include "SoftwareTimerFunctionTypesTestCase.hpp"
#include "SoftwareTimerPeriodicTestCase.hpp"

#include "TestCaseGroup.hpp"

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

/// SoftwareTimerOrderingTestCase instance
const SoftwareTimerOrderingTestCase orderingTestCase;

/// SoftwareTimerOperationsTestCase instance
const SoftwareTimerOperationsTestCase operationsTestCase;

/// SoftwareTimerFunctionTypesTestCase instance
const SoftwareTimerFunctionTypesTestCase functionTypesTestCase;

/// SoftwareTimerPeriodicTestCase instance
const SoftwareTimerPeriodicTestCase periodicTestCase;

/// array with references to TestCase objects related to software timers
const TestCaseGroup::Range::value_type softwareTimerTestCases_[]
{
		TestCaseGroup::Range::value_type{orderingTestCase},
		TestCaseGroup::Range::value_type{operationsTestCase},
		TestCaseGroup::Range::value_type{functionTypesTestCase},
		TestCaseGroup::Range::value_type{periodicTestCase},
};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global objects
+---------------------------------------------------------------------------------------------------------------------*/

const TestCaseGroup softwareTimerTestCases {TestCaseGroup::Range{softwareTimerTestCases_}};

}	// namespace test

}	// namespace distortos
<|endoftext|>


<commit_before>// RUN: %clangxx -fsanitize=alignment -g %s -O3 -o %t
// RUN: %run %t l0 && %run %t s0 && %run %t r0 && %run %t m0 && %run %t f0 && %run %t n0 && %run %t u0
// RUN: %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --strict-whitespace
// RUN: %run %t s1 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
// RUN: %run %t r1 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: %run %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: %run %t f1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
// RUN: %run %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW
// RUN: %run %t u1 2>&1 | FileCheck %s --check-prefix=CHECK-UPCAST
// RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --check-prefix=CHECK-%os-STACK-LOAD

// RUN: %clangxx -fsanitize=alignment -fno-sanitize-recover %s -O3 -o %t
// RUN: not %run %t w1 2>&1 | FileCheck %s --check-prefix=CHECK-WILD
// XFAIL: armv7l-unknown-linux-gnueabihf

#include <new>

struct S {
  S() {}
  int f() { return 0; }
  int k;
};

struct T : S {
  int t;
};

int main(int, char **argv) {
  char c[] __attribute__((aligned(8))) = { 0, 0, 0, 0, 1, 2, 3, 4, 5 };

  // Pointer value may be unspecified here, but behavior is not undefined.
  int *p = (int*)&c[4 + argv[1][1] - '0'];
  S *s = (S*)p;
  T *t = (T*)p;

  void *wild = reinterpret_cast<void *>(0x123L);

  (void)*p; // ok!

  switch (argv[1][0]) {
  case 'l':
    // CHECK-LOAD: misaligned.cpp:[[@LINE+4]]:12: runtime error: load of misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-LOAD-NEXT: [[PTR]]: note: pointer points here
    // CHECK-LOAD-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-LOAD-NEXT: {{^             \^}}
    return *p && 0;
    // Slow stack unwinding is disabled on Darwin for now, see
    // https://code.google.com/p/address-sanitizer/issues/detail?id=137
    // CHECK-Linux-STACK-LOAD: #0 {{.*}} in main{{.*}}misaligned.cpp
    // Check for the already checked line to avoid lit error reports.
    // CHECK-Darwin-STACK-LOAD: {{ }}

  case 's':
    // CHECK-STORE: misaligned.cpp:[[@LINE+4]]:5: runtime error: store to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-STORE-NEXT: [[PTR]]: note: pointer points here
    // CHECK-STORE-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-STORE-NEXT: {{^             \^}}
    *p = 1;
    break;

  case 'r':
    // CHECK-REFERENCE: misaligned.cpp:[[@LINE+4]]:15: runtime error: reference binding to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-REFERENCE-NEXT: [[PTR]]: note: pointer points here
    // CHECK-REFERENCE-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-REFERENCE-NEXT: {{^             \^}}
    {int &r = *p;}
    break;

  case 'm':
    // CHECK-MEMBER: misaligned.cpp:[[@LINE+4]]:15: runtime error: member access within misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-MEMBER-NEXT: [[PTR]]: note: pointer points here
    // CHECK-MEMBER-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-MEMBER-NEXT: {{^             \^}}
    return s->k && 0;

  case 'f':
    // CHECK-MEMFUN: misaligned.cpp:[[@LINE+4]]:12: runtime error: member call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-MEMFUN-NEXT: [[PTR]]: note: pointer points here
    // CHECK-MEMFUN-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-MEMFUN-NEXT: {{^             \^}}
    return s->f() && 0;

  case 'n':
    // CHECK-NEW: misaligned.cpp:[[@LINE+4]]:5: runtime error: constructor call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-NEW-NEXT: [[PTR]]: note: pointer points here
    // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-NEW-NEXT: {{^             \^}}
    return (new (s) S)->k && 0;

  case 'u': {
    // CHECK-UPCAST: misaligned.cpp:[[@LINE+4]]:17: runtime error: upcast of misaligned address [[PTR:0x[0-9a-f]*]] for type 'T', which requires 4 byte alignment
    // CHECK-UPCAST-NEXT: [[PTR]]: note: pointer points here
    // CHECK-UPCAST-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-UPCAST-NEXT: {{^             \^}}
    S *s2 = (S*)t;
    return s2->f();
  }

  case 'w':
    // CHECK-WILD: misaligned.cpp:[[@LINE+3]]:35: runtime error: member access within misaligned address 0x000000000123 for type 'S', which requires 4 byte alignment
    // CHECK-WILD-NEXT: 0x000000000123: note: pointer points here
    // CHECK-WILD-NEXT: <memory cannot be printed>
    return static_cast<S*>(wild)->k;
  }
}
<commit_msg>Update test case with more accurate column information now that Clang produces same<commit_after>// RUN: %clangxx -fsanitize=alignment -g %s -O3 -o %t
// RUN: %run %t l0 && %run %t s0 && %run %t r0 && %run %t m0 && %run %t f0 && %run %t n0 && %run %t u0
// RUN: %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --strict-whitespace
// RUN: %run %t s1 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
// RUN: %run %t r1 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: %run %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: %run %t f1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
// RUN: %run %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW
// RUN: %run %t u1 2>&1 | FileCheck %s --check-prefix=CHECK-UPCAST
// RUN: UBSAN_OPTIONS=print_stacktrace=1 %run %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD --check-prefix=CHECK-%os-STACK-LOAD

// RUN: %clangxx -fsanitize=alignment -fno-sanitize-recover %s -O3 -o %t
// RUN: not %run %t w1 2>&1 | FileCheck %s --check-prefix=CHECK-WILD
// XFAIL: armv7l-unknown-linux-gnueabihf

#include <new>

struct S {
  S() {}
  int f() { return 0; }
  int k;
};

struct T : S {
  int t;
};

int main(int, char **argv) {
  char c[] __attribute__((aligned(8))) = { 0, 0, 0, 0, 1, 2, 3, 4, 5 };

  // Pointer value may be unspecified here, but behavior is not undefined.
  int *p = (int*)&c[4 + argv[1][1] - '0'];
  S *s = (S*)p;
  T *t = (T*)p;

  void *wild = reinterpret_cast<void *>(0x123L);

  (void)*p; // ok!

  switch (argv[1][0]) {
  case 'l':
    // CHECK-LOAD: misaligned.cpp:[[@LINE+4]]:12: runtime error: load of misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-LOAD-NEXT: [[PTR]]: note: pointer points here
    // CHECK-LOAD-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-LOAD-NEXT: {{^             \^}}
    return *p && 0;
    // Slow stack unwinding is disabled on Darwin for now, see
    // https://code.google.com/p/address-sanitizer/issues/detail?id=137
    // CHECK-Linux-STACK-LOAD: #0 {{.*}} in main{{.*}}misaligned.cpp
    // Check for the already checked line to avoid lit error reports.
    // CHECK-Darwin-STACK-LOAD: {{ }}

  case 's':
    // CHECK-STORE: misaligned.cpp:[[@LINE+4]]:5: runtime error: store to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-STORE-NEXT: [[PTR]]: note: pointer points here
    // CHECK-STORE-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-STORE-NEXT: {{^             \^}}
    *p = 1;
    break;

  case 'r':
    // CHECK-REFERENCE: misaligned.cpp:[[@LINE+4]]:15: runtime error: reference binding to misaligned address [[PTR:0x[0-9a-f]*]] for type 'int', which requires 4 byte alignment
    // CHECK-REFERENCE-NEXT: [[PTR]]: note: pointer points here
    // CHECK-REFERENCE-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-REFERENCE-NEXT: {{^             \^}}
    {int &r = *p;}
    break;

  case 'm':
    // CHECK-MEMBER: misaligned.cpp:[[@LINE+4]]:15: runtime error: member access within misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-MEMBER-NEXT: [[PTR]]: note: pointer points here
    // CHECK-MEMBER-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-MEMBER-NEXT: {{^             \^}}
    return s->k && 0;

  case 'f':
    // CHECK-MEMFUN: misaligned.cpp:[[@LINE+4]]:12: runtime error: member call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-MEMFUN-NEXT: [[PTR]]: note: pointer points here
    // CHECK-MEMFUN-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-MEMFUN-NEXT: {{^             \^}}
    return s->f() && 0;

  case 'n':
    // CHECK-NEW: misaligned.cpp:[[@LINE+4]]:13: runtime error: constructor call on misaligned address [[PTR:0x[0-9a-f]*]] for type 'S', which requires 4 byte alignment
    // CHECK-NEW-NEXT: [[PTR]]: note: pointer points here
    // CHECK-NEW-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-NEW-NEXT: {{^             \^}}
    return (new (s) S)->k && 0;

  case 'u': {
    // CHECK-UPCAST: misaligned.cpp:[[@LINE+4]]:17: runtime error: upcast of misaligned address [[PTR:0x[0-9a-f]*]] for type 'T', which requires 4 byte alignment
    // CHECK-UPCAST-NEXT: [[PTR]]: note: pointer points here
    // CHECK-UPCAST-NEXT: {{^ 00 00 00 01 02 03 04  05}}
    // CHECK-UPCAST-NEXT: {{^             \^}}
    S *s2 = (S*)t;
    return s2->f();
  }

  case 'w':
    // CHECK-WILD: misaligned.cpp:[[@LINE+3]]:35: runtime error: member access within misaligned address 0x000000000123 for type 'S', which requires 4 byte alignment
    // CHECK-WILD-NEXT: 0x000000000123: note: pointer points here
    // CHECK-WILD-NEXT: <memory cannot be printed>
    return static_cast<S*>(wild)->k;
  }
}
<|endoftext|>


<commit_before><commit_msg>added option to remove unwanted characters for generated filename<commit_after><|endoftext|>


<commit_before><commit_msg>comment freopen, googd<commit_after><|endoftext|>


<commit_before><commit_msg>[RF] Apply Rule of Silence to testRooAbsPdf.<commit_after><|endoftext|>


<commit_before>/*!
    \file errors_exceptions_handler.cpp
    \brief Exceptions handler example
    \author Ivan Shynkarenka
    \date 22.04.2016
    \copyright MIT License
*/

#include "errors/exceptions_handler.h"
#include "system/stack_trace_manager.h"

#include <cfloat>
#include <csignal>
#include <iostream>
#include <string>
#include <thread>

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

void GenerateSIGABRT()
{
    abort();
}

void GenerateSIGFPE()
{
    // Code taken from http://www.devx.com/cplus/Article/34993/1954

    // Set the x86 floating-point control word according to what
    // exceptions you want to trap. Always call _clearfp before
    // setting the control word
    _clearfp();

    // Because the second parameter in the following call is 0, it
    // only returns the floating-point control word.
    unsigned int cw;
    _controlfp_s(&cw, 0, 0);

    // Set the exception masks off for exceptions that you want to
    // trap. When a mask bit is set, the corresponding floating-point
    // exception is blocked from being generating.
    cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID);

    // For any bit in the second parameter (mask) that is 1, the
    // corresponding bit in the first parameter is used to update
    // the control word.
    unsigned int cwOriginal;
    _controlfp_s(&cwOriginal, cw, MCW_EM);

    // MCW_EM is defined in float.h.
    // Restore the original value when done:
    // _controlfp(cwOriginal, MCW_EM);

    // Divide by zero
    float a = 1;
    float b = 0;
    float c = a / b;
    c;
}

void GenerateSIGILL()
{
    raise(SIGILL);
}

void GenerateSIGINT()
{
    raise(SIGINT);
}

void GenerateSIGSEGV()
{
    raise(SIGSEGV);
}

void GenerateSIGTERM()
{
    raise(SIGTERM);
}

void GenerateExit()
{
    exit(0);
}

void GenerateTerminate()
{
    terminate();
}

void GenerateUnexpected()
{
    unexpected();
}

void GenerateExceptionThrow()
{
    throw std::exception("My exception");
}

#if defined(_WIN32) || defined(_WIN64)
void GenerateInvalidParameter()
{
    char* format = nullptr;
    printf(format);
}

#pragma warning(push)
// VS 4717: 'function' : recursive on all control paths, function will cause runtime stack overflow
#pragma warning(disable: 4717)
void GenerateRecurseAlloc()
{
    char* buffer = new char[0x1FFFFFFF];
    buffer;
    GenerateRecurseAlloc();
}
#pragma warning(pop)

class Base;

void function(Base* instance);

class Base
{
public:
    Base() { function(this); }
    virtual void method(void) = 0;
};

class Derived : public Base
{
public:
    void method(void) override {}
};

void function(Base* instance)
{
    instance->method();
}

void GeneratePureVirtualMethodCall()
{
    Derived derived;
}

void GenerateSEH()
{
    int* p = nullptr;
#pragma warning(push)
// VS 6011: dereferencing NULL pointer <name>
#pragma warning(disable: 6011)
    *p = 0;
#pragma warning(pop)
}

void GenerateRaiseException()
{
    RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
#endif

void GenerateCustomException(int type)
{
    switch (type)
    {
        case 1:
            GenerateSIGABRT();
            break;
        case 2:
            GenerateSIGFPE();
            break;
        case 3:
            GenerateSIGILL();
            break;
        case 4:
            GenerateSIGINT();
            break;
        case 5:
            GenerateSIGSEGV();
            break;
        case 6:
            GenerateSIGTERM();
            break;
        case 7:
            GenerateExit();
            break;
        case 8:
            GenerateTerminate();
            break;
        case 9:
            GenerateUnexpected();
            break;
        case 10:
            GenerateExceptionThrow();
            break;
#if defined(_WIN32) || defined(_WIN64)
        case 11:
            GenerateInvalidParameter();
            break;
        case 12:
            GenerateRecurseAlloc();
            break;
        case 13:
            GeneratePureVirtualMethodCall();
            break;
        case 14:
            GenerateSEH();
            break;
        case 15:
            GenerateRaiseException();
            break;
#endif
    }
}

void GenerateCustomException(int type, bool thread)
{
    auto function = [=]()
    {
        // Setup exceptions handler for the created thread
        if (thread)
            CppCommon::ExceptionsHandler::SetupThread();

        GenerateCustomException(type);
    };

    if (thread)
        std::thread(function).join();
    else
        function();
}

int main(int argc, char** argv)
{
    // Initialize stack trace manager of the current process
    CppCommon::StackTraceManager::Initialize();
    // Setup exceptions handler for the current process
    CppCommon::ExceptionsHandler::SetupProcess();

    std::cout << "1 - SIGABRT" << std::endl;
    std::cout << "2 - SIGFPE" << std::endl;
    std::cout << "3 - SIGILL" << std::endl;
    std::cout << "4 - SIGINT" << std::endl;
    std::cout << "5 - SIGSEGV" << std::endl;
    std::cout << "6 - SIGTERM" << std::endl;
    std::cout << "7 - exit" << std::endl;
    std::cout << "8 - terminate" << std::endl;
    std::cout << "9 - unexpected" << std::endl;
    std::cout << "10 - exception throw" << std::endl;
#if defined(_WIN32) || defined(_WIN64)
    std::cout << "11 - invalid parameter" << std::endl;
    std::cout << "12 - new operator fault" << std::endl;
    std::cout << "13 - pure virtual method call" << std::endl;
    std::cout << "14 - SEH exception" << std::endl;
    std::cout << "15 - RaiseException()" << std::endl;
#endif
    std::cout << "Choose an exception type: ";

    std::string line;
    if (getline(std::cin, line))
    {
        int type = std::stoi(line);
        GenerateCustomException(type, true);
    }

    // Cleanup stack trace manager of the current process
    CppCommon::StackTraceManager::Cleanup();

    return 0;
}
<commit_msg>Fix linux build<commit_after>/*!
    \file errors_exceptions_handler.cpp
    \brief Exceptions handler example
    \author Ivan Shynkarenka
    \date 22.04.2016
    \copyright MIT License
*/

#include "errors/exceptions_handler.h"
#include "system/stack_trace_manager.h"

#include <cfloat>
#include <csignal>
#include <iostream>
#include <string>
#include <thread>

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif

void GenerateSIGABRT()
{
    abort();
}

void GenerateSIGFPE()
{
    // Code taken from http://www.devx.com/cplus/Article/34993/1954

#if defined(_WIN32) || defined(_WIN64)
    // Set the x86 floating-point control word according to what
    // exceptions you want to trap. Always call _clearfp before
    // setting the control word
    _clearfp();

    // Because the second parameter in the following call is 0, it
    // only returns the floating-point control word.
    unsigned int cw;
    _controlfp_s(&cw, 0, 0);

    // Set the exception masks off for exceptions that you want to
    // trap. When a mask bit is set, the corresponding floating-point
    // exception is blocked from being generating.
    cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID);

    // For any bit in the second parameter (mask) that is 1, the
    // corresponding bit in the first parameter is used to update
    // the control word.
    unsigned int cwOriginal;
    _controlfp_s(&cwOriginal, cw, MCW_EM);

    // MCW_EM is defined in float.h.
    // Restore the original value when done:
    // _controlfp(cwOriginal, MCW_EM);
#endif

    // Divide by zero
    float a = 1;
    float b = 0;
    float c = a / b;
    c;
}

void GenerateSIGILL()
{
    raise(SIGILL);
}

void GenerateSIGINT()
{
    raise(SIGINT);
}

void GenerateSIGSEGV()
7{
    raise(SIGSEGV);
}

void GenerateSIGTERM()
{
    raise(SIGTERM);
}

void GenerateExit()
{
    exit(0);
}

void GenerateTerminate()
{
    terminate();
}

void GenerateUnexpected()
{
    unexpected();
}

void GenerateExceptionThrow()
{
    throw std::exception("My exception");
}

#if defined(_WIN32) || defined(_WIN64)
void GenerateInvalidParameter()
{
    char* format = nullptr;
    printf(format);
}

#pragma warning(push)
// VS 4717: 'function' : recursive on all control paths, function will cause runtime stack overflow
#pragma warning(disable: 4717)
void GenerateRecurseAlloc()
{
    char* buffer = new char[0x1FFFFFFF];
    buffer;
    GenerateRecurseAlloc();
}
#pragma warning(pop)

class Base;

void function(Base* instance);

class Base
{
public:
    Base() { function(this); }
    virtual void method(void) = 0;
};

class Derived : public Base
{
public:
    void method(void) override {}
};

void function(Base* instance)
{
    instance->method();
}

void GeneratePureVirtualMethodCall()
{
    Derived derived;
}

void GenerateSEH()
{
    int* p = nullptr;
#pragma warning(push)
// VS 6011: dereferencing NULL pointer <name>
#pragma warning(disable: 6011)
    *p = 0;
#pragma warning(pop)
}

void GenerateRaiseException()
{
    RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, nullptr);
}
#endif

void GenerateCustomException(int type)
{
    switch (type)
    {
        case 1:
            GenerateSIGABRT();
            break;
        case 2:
            GenerateSIGFPE();
            break;
        case 3:
            GenerateSIGILL();
            break;
        case 4:
            GenerateSIGINT();
            break;
        case 5:
            GenerateSIGSEGV();
            break;
        case 6:
            GenerateSIGTERM();
            break;
        case 7:
            GenerateExit();
            break;
        case 8:
            GenerateTerminate();
            break;
        case 9:
            GenerateUnexpected();
            break;
        case 10:
            GenerateExceptionThrow();
            break;
#if defined(_WIN32) || defined(_WIN64)
        case 11:
            GenerateInvalidParameter();
            break;
        case 12:
            GenerateRecurseAlloc();
            break;
        case 13:
            GeneratePureVirtualMethodCall();
            break;
        case 14:
            GenerateSEH();
            break;
        case 15:
            GenerateRaiseException();
            break;
#endif
    }
}

void GenerateCustomException(int type, bool thread)
{
    auto function = [=]()
    {
        // Setup exceptions handler for the created thread
        if (thread)
            CppCommon::ExceptionsHandler::SetupThread();

        GenerateCustomException(type);
    };

    if (thread)
        std::thread(function).join();
    else
        function();
}

int main(int argc, char** argv)
{
    // Initialize stack trace manager of the current process
    CppCommon::StackTraceManager::Initialize();
    // Setup exceptions handler for the current process
    CppCommon::ExceptionsHandler::SetupProcess();

    std::cout << "1 - SIGABRT" << std::endl;
    std::cout << "2 - SIGFPE" << std::endl;
    std::cout << "3 - SIGILL" << std::endl;
    std::cout << "4 - SIGINT" << std::endl;
    std::cout << "5 - SIGSEGV" << std::endl;
    std::cout << "6 - SIGTERM" << std::endl;
    std::cout << "7 - exit" << std::endl;
    std::cout << "8 - terminate" << std::endl;
    std::cout << "9 - unexpected" << std::endl;
    std::cout << "10 - exception throw" << std::endl;
#if defined(_WIN32) || defined(_WIN64)
    std::cout << "11 - invalid parameter" << std::endl;
    std::cout << "12 - new operator fault" << std::endl;
    std::cout << "13 - pure virtual method call" << std::endl;
    std::cout << "14 - SEH exception" << std::endl;
    std::cout << "15 - RaiseException()" << std::endl;
#endif
    std::cout << "Choose an exception type: ";

    std::string line;
    if (getline(std::cin, line))
    {
        int type = std::stoi(line);
        GenerateCustomException(type, true);
    }

    // Cleanup stack trace manager of the current process
    CppCommon::StackTraceManager::Cleanup();

    return 0;
}
<|endoftext|>


<commit_before>#include <osg/Group>
#include <osg/Notify>
#include <osg/Depth>
#include <osg/StateSet>
#include <osg/ClearNode>
#include <osg/Transform>

#include <osgUtil/CullVisitor>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

#include "GliderManipulator.h"

#include <iostream>

extern osg::Node *makeTerrain( void );
extern osg::Node *makeTrees( void );
extern osg::Node *makeTank( void );
extern osg::Node *makeWindsocks( void );
extern osg::Node *makeGliders( void );
extern osg::Node *makeGlider( void );
extern osg::Node *makeSky( void );
extern osg::Node *makeBase( void );
extern osg::Node *makeClouds( void );

class MoveEarthySkyWithEyePointTransform : public osg::Transform
{
public:
    /** Get the transformation matrix which moves from local coords to world coords.*/
    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.preMult(osg::Matrix::translate(eyePointLocal.x(),eyePointLocal.y(),0.0f));
        }
        return true;
    }

    /** Get the transformation matrix which moves from world coords to local coords.*/
    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        std::cout<<"computing transform"<<std::endl;

        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.postMult(osg::Matrix::translate(-eyePointLocal.x(),-eyePointLocal.y(),0.0f));
        }
        return true;
    }
};

osg::Group* createModel()
{
    // no database loaded so automatically create Ed Levin Park..
    osg::Group* group = new osg::Group;

    // the base and sky subgraphs go to set the earth sky of the
    // model and clear the color and depth buffer for us, by using
    // osg::Depth, and setting their bin numbers to less than 0,
    // to force them to draw before the rest of the scene.

    osg::ClearNode* clearNode = new osg::ClearNode;
    clearNode->setRequiresClear(false); // we've got base and sky to do it.

    // use a transform to make the sky and base around with the eye point.
    osg::Transform* transform = new MoveEarthySkyWithEyePointTransform;

    // transform's value isn't knowm until in the cull traversal so its bounding
    // volume is can't be determined, therefore culling will be invalid,
    // so switch it off, this cause all our paresnts to switch culling
    // off as well. But don't worry culling will be back on once underneath
    // this node or any other branch above this transform.
    transform->setCullingActive(false);

    // add the sky and base layer.
    transform->addChild(makeSky());  // bin number -2 so drawn first.
    transform->addChild(makeBase()); // bin number -1 so draw second.

    // add the transform to the earth sky.
    clearNode->addChild(transform);

    // add to earth sky to the scene.
    group->addChild(clearNode);

    // the rest of the scene drawn after the base and sky above.
    group->addChild(makeTrees()); // will drop into a transparent, depth sorted bin (1)
    group->addChild(makeTerrain()); // will drop into default bin - state sorted 0
    group->addChild(makeTank()); // will drop into default bin - state sorted 0
    // add the following in the future...
    // makeGliders
    // makeClouds

    return group;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to create a scene programatically, in this case a hang gliding flying site.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgViewer::Viewer viewer;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    bool customWindows = false;
    while(arguments.read("-2")) customWindows = true;

    if (customWindows)
    {
        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
        if (!wsi)
        {
            osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
            return 0;
        }

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->x = 250;
        traits->y = 200;
        traits->width = 800;
        traits->height = 600;
        traits->windowDecoration = true;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;

        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
        if (gc.valid())
        {
            // need to ensure that the window is cleared make sure that the complete window is set the correct colour
            // rather than just the parts of the window that are under the camera's viewports
            gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
            gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
        else
        {
            osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
        }

        unsigned int numCameras = 2;
        double aspectRatioScale = 1.0/(double)numCameras;
        for(unsigned int i=0; i<numCameras;++i)
        {
            osg::ref_ptr<osg::Camera> camera = new osg::Camera;
            camera->setGraphicsContext(gc.get());
            camera->setViewport(new osg::Viewport((i* traits->width)/numCameras,(i* traits->height)/numCameras,  traits->width/numCameras,  traits->height/numCameras));
            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
            camera->setDrawBuffer(buffer);
            camera->setReadBuffer(buffer);

            viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::scale(aspectRatioScale,1.0,1.0));
        }
    }
    else
    {
        viewer.setUpViewAcrossAllScreens();

    }

    // set up the camera manipulation with out custom manipultor
    viewer.setCameraManipulator(new GliderManipulator());

    // pass the scene graph to the viewer
    viewer.setSceneData( createModel() );

    return viewer.run();
}

<commit_msg>Fixed aspect ratio.<commit_after>#include <osg/Group>
#include <osg/Notify>
#include <osg/Depth>
#include <osg/StateSet>
#include <osg/ClearNode>
#include <osg/Transform>

#include <osgUtil/CullVisitor>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

#include "GliderManipulator.h"

#include <iostream>

extern osg::Node *makeTerrain( void );
extern osg::Node *makeTrees( void );
extern osg::Node *makeTank( void );
extern osg::Node *makeWindsocks( void );
extern osg::Node *makeGliders( void );
extern osg::Node *makeGlider( void );
extern osg::Node *makeSky( void );
extern osg::Node *makeBase( void );
extern osg::Node *makeClouds( void );

class MoveEarthySkyWithEyePointTransform : public osg::Transform
{
public:
    /** Get the transformation matrix which moves from local coords to world coords.*/
    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.preMult(osg::Matrix::translate(eyePointLocal.x(),eyePointLocal.y(),0.0f));
        }
        return true;
    }

    /** Get the transformation matrix which moves from world coords to local coords.*/
    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const
    {
        std::cout<<"computing transform"<<std::endl;

        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
        if (cv)
        {
            osg::Vec3 eyePointLocal = cv->getEyeLocal();
            matrix.postMult(osg::Matrix::translate(-eyePointLocal.x(),-eyePointLocal.y(),0.0f));
        }
        return true;
    }
};

osg::Group* createModel()
{
    // no database loaded so automatically create Ed Levin Park..
    osg::Group* group = new osg::Group;

    // the base and sky subgraphs go to set the earth sky of the
    // model and clear the color and depth buffer for us, by using
    // osg::Depth, and setting their bin numbers to less than 0,
    // to force them to draw before the rest of the scene.

    osg::ClearNode* clearNode = new osg::ClearNode;
    clearNode->setRequiresClear(false); // we've got base and sky to do it.

    // use a transform to make the sky and base around with the eye point.
    osg::Transform* transform = new MoveEarthySkyWithEyePointTransform;

    // transform's value isn't knowm until in the cull traversal so its bounding
    // volume is can't be determined, therefore culling will be invalid,
    // so switch it off, this cause all our paresnts to switch culling
    // off as well. But don't worry culling will be back on once underneath
    // this node or any other branch above this transform.
    transform->setCullingActive(false);

    // add the sky and base layer.
    transform->addChild(makeSky());  // bin number -2 so drawn first.
    transform->addChild(makeBase()); // bin number -1 so draw second.

    // add the transform to the earth sky.
    clearNode->addChild(transform);

    // add to earth sky to the scene.
    group->addChild(clearNode);

    // the rest of the scene drawn after the base and sky above.
    group->addChild(makeTrees()); // will drop into a transparent, depth sorted bin (1)
    group->addChild(makeTerrain()); // will drop into default bin - state sorted 0
    group->addChild(makeTank()); // will drop into default bin - state sorted 0
    // add the following in the future...
    // makeGliders
    // makeClouds

    return group;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to create a scene programatically, in this case a hang gliding flying site.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgViewer::Viewer viewer;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    bool customWindows = false;
    while(arguments.read("-2")) customWindows = true;

    if (customWindows)
    {
        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
        if (!wsi)
        {
            osg::notify(osg::NOTICE)<<"View::setUpViewAcrossAllScreens() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
            return 0;
        }

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->x = 250;
        traits->y = 200;
        traits->width = 800;
        traits->height = 600;
        traits->windowDecoration = true;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;

        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
        if (gc.valid())
        {
            // need to ensure that the window is cleared make sure that the complete window is set the correct colour
            // rather than just the parts of the window that are under the camera's viewports
            gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
            gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        }
        else
        {
            osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created successfully."<<std::endl;
        }

        unsigned int numCameras = 2;
        double aspectRatioScale = 1.0;
        for(unsigned int i=0; i<numCameras;++i)
        {
            osg::ref_ptr<osg::Camera> camera = new osg::Camera;
            camera->setGraphicsContext(gc.get());
            camera->setViewport(new osg::Viewport((i* traits->width)/numCameras,(i* traits->height)/numCameras,  traits->width/numCameras,  traits->height/numCameras));
            GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
            camera->setDrawBuffer(buffer);
            camera->setReadBuffer(buffer);

            viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::scale(aspectRatioScale,1.0,1.0));
        }
    }
    else
    {
        viewer.setUpViewAcrossAllScreens();

    }

    // set up the camera manipulation with out custom manipultor
    viewer.setCameraManipulator(new GliderManipulator());

    // pass the scene graph to the viewer
    viewer.setSceneData( createModel() );

    return viewer.run();
}

<|endoftext|>