<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <interfaces/wallet.h>
#include <net.h>
#include <node/context.h>
#include <node/ui_interface.h>
#include <outputtype.h>
#include <univalue.h>
#include <util/check.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/translation.h>
#ifdef USE_BDB
#include <wallet/bdb.h>
#endif
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
#include <walletinitinterface.h>

class WalletInit : public WalletInitInterface
{
public:
    //! Was the wallet component compiled in.
    bool HasWalletSupport() const override {return true;}

    //! Return the wallets help message.
    void AddWalletOptions(ArgsManager& argsman) const override;

    //! Wallets parameter interaction
    bool ParameterInteraction() const override;

    //! Add wallets that should be opened to list of chain clients.
    void Construct(NodeContext& node) const override;
};

const WalletInitInterface& g_wallet_init_interface = WalletInit();

void WalletInit::AddWalletOptions(ArgsManager& argsman) const
{
    argsman.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting many (possibly all) or none, instead of selecting on a per-output basis. Privacy is improved as addresses are mostly swept with fewer transactions and outputs are aggregated in clean change addresses. It may result in higher fees due to less optimal coin selection caused by this added limitation and possibly a larger-than-necessary number of inputs being used. Always enabled for wallets with \"avoid_reuse\" enabled, otherwise default: %u.", DEFAULT_AVOIDPARTIALSPENDS), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-consolidatefeerate=<amt>", strprintf("The maximum feerate (in %s/kvB) at which transaction building may use more inputs than strictly necessary so that the wallet's UTXO pool can be reduced (default: %s).", CURRENCY_UNIT, FormatMoney(DEFAULT_CONSOLIDATE_FEERATE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kvB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
                                                                "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target",
                                                              CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);

    argsman.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kvB) that will be used when fee estimation has insufficient data. 0 to entirely disable the fallbackfee feature. (default: %s)",
                                                               CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u). Warning: Smaller sizes may increase the risk of losing funds when restoring from an old backup, if none of the addresses in the original keypool have been used.", DEFAULT_KEYPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-maxapsfee=<n>", strprintf("Spend up to this amount in additional (absolute) fees (in %s) if it allows the use of partial spend avoidance (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_MAX_AVOIDPARTIALSPEND_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)",
        CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
    argsman.AddArg("-mintxfee=<amt>", strprintf("Fee rates (in %s/kvB) smaller than this are considered zero fee for transaction creation (default: %s)",
                                                            CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-paytxfee=<amt>", strprintf("Fee rate (in %s/kvB) to add to transactions you send (default: %s)",
                                                            CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#ifdef ENABLE_EXTERNAL_SIGNER
    argsman.AddArg("-signer=<cmd>", "External signing tool, see doc/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
    argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-wallet=<path>", "Specify wallet path to load at startup. Can be used multiple times to load multiple wallets. Path is to a directory containing wallet data and log files. If the path is not absolute, it is interpreted relative to <walletdir>. This only loads existing wallets and does not create new ones. For backwards compatibility this also accepts names of existing top-level data files in <walletdir>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
    argsman.AddArg("-walletbroadcast",  strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
#if HAVE_SYSTEM
    argsman.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes. %s in cmd is replaced by TxID, %w is replaced by wallet name, %b is replaced by the hash of the block including the transaction (set to 'unconfirmed' if the transaction is not included) and %h is replaced by the block height (-1 if not included). %w is not currently implemented on windows. On systems where %w is supported, it should NOT be quoted because this would break shell escaping used to invoke the command.", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
    argsman.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);

#ifdef USE_BDB
    argsman.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
    argsman.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
    argsman.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
#else
    argsman.AddHiddenArgs({"-dblogsize", "-flushwallet", "-privdb"});
#endif

#ifdef USE_SQLITE
    argsman.AddArg("-unsafesqlitesync", "Set SQLite synchronous=OFF to disable waiting for the database to sync to disk. This is unsafe and can cause data loss and corruption. This option is only used by tests to improve their performance (default: false)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
#else
    argsman.AddHiddenArgs({"-unsafesqlitesync"});
#endif

    argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);

    argsman.AddHiddenArgs({"-zapwallettxes"});
}

bool WalletInit::ParameterInteraction() const
{
#ifdef USE_BDB
     if (!BerkeleyDatabaseSanityCheck()) {
         return InitError(Untranslated("A version conflict was detected between the run-time BerkeleyDB library and the one used during compilation."));
     }
#endif
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
            LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
        }

        return true;
    }

    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
        LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
    }

    if (gArgs.IsArgSet("-zapwallettxes")) {
        return InitError(Untranslated("-zapwallettxes has been removed. If you are attempting to remove a stuck transaction from your wallet, please use abandontransaction instead."));
    }

    if (gArgs.GetBoolArg("-sysperms", false))
        return InitError(Untranslated("-sysperms is not allowed in combination with enabled wallet functionality"));

    return true;
}

void WalletInit::Construct(NodeContext& node) const
{
    ArgsManager& args = *Assert(node.args);
    if (args.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        LogPrintf("Wallet disabled!\n");
        return;
    }
    auto wallet_client = node.init->makeWalletClient(*node.chain);
    node.wallet_client = wallet_client.get();
    node.chain_clients.emplace_back(std::move(wallet_client));
}
<commit_msg>doc: Fix -changetype help text<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <interfaces/wallet.h>
#include <net.h>
#include <node/context.h>
#include <node/ui_interface.h>
#include <outputtype.h>
#include <univalue.h>
#include <util/check.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/translation.h>
#ifdef USE_BDB
#include <wallet/bdb.h>
#endif
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
#include <walletinitinterface.h>

class WalletInit : public WalletInitInterface
{
public:
    //! Was the wallet component compiled in.
    bool HasWalletSupport() const override {return true;}

    //! Return the wallets help message.
    void AddWalletOptions(ArgsManager& argsman) const override;

    //! Wallets parameter interaction
    bool ParameterInteraction() const override;

    //! Add wallets that should be opened to list of chain clients.
    void Construct(NodeContext& node) const override;
};

const WalletInitInterface& g_wallet_init_interface = WalletInit();

void WalletInit::AddWalletOptions(ArgsManager& argsman) const
{
    argsman.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting many (possibly all) or none, instead of selecting on a per-output basis. Privacy is improved as addresses are mostly swept with fewer transactions and outputs are aggregated in clean change addresses. It may result in higher fees due to less optimal coin selection caused by this added limitation and possibly a larger-than-necessary number of inputs being used. Always enabled for wallets with \"avoid_reuse\" enabled, otherwise default: %u.", DEFAULT_AVOIDPARTIALSPENDS), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-changetype",
                   "What type of change to use (\"legacy\", \"p2sh-segwit\", \"bech32\", or \"bech32m\"). Default is \"legacy\" when "
                   "-addresstype=legacy, else it is an implementation detail.",
                   ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-consolidatefeerate=<amt>", strprintf("The maximum feerate (in %s/kvB) at which transaction building may use more inputs than strictly necessary so that the wallet's UTXO pool can be reduced (default: %s).", CURRENCY_UNIT, FormatMoney(DEFAULT_CONSOLIDATE_FEERATE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kvB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
                                                                "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target",
                                                              CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);

    argsman.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kvB) that will be used when fee estimation has insufficient data. 0 to entirely disable the fallbackfee feature. (default: %s)",
                                                               CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u). Warning: Smaller sizes may increase the risk of losing funds when restoring from an old backup, if none of the addresses in the original keypool have been used.", DEFAULT_KEYPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-maxapsfee=<n>", strprintf("Spend up to this amount in additional (absolute) fees (in %s) if it allows the use of partial spend avoidance (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_MAX_AVOIDPARTIALSPEND_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)",
        CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
    argsman.AddArg("-mintxfee=<amt>", strprintf("Fee rates (in %s/kvB) smaller than this are considered zero fee for transaction creation (default: %s)",
                                                            CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-paytxfee=<amt>", strprintf("Fee rate (in %s/kvB) to add to transactions you send (default: %s)",
                                                            CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#ifdef ENABLE_EXTERNAL_SIGNER
    argsman.AddArg("-signer=<cmd>", "External signing tool, see doc/external-signer.md", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
    argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-wallet=<path>", "Specify wallet path to load at startup. Can be used multiple times to load multiple wallets. Path is to a directory containing wallet data and log files. If the path is not absolute, it is interpreted relative to <walletdir>. This only loads existing wallets and does not create new ones. For backwards compatibility this also accepts names of existing top-level data files in <walletdir>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
    argsman.AddArg("-walletbroadcast",  strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
    argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
#if HAVE_SYSTEM
    argsman.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes. %s in cmd is replaced by TxID, %w is replaced by wallet name, %b is replaced by the hash of the block including the transaction (set to 'unconfirmed' if the transaction is not included) and %h is replaced by the block height (-1 if not included). %w is not currently implemented on windows. On systems where %w is supported, it should NOT be quoted because this would break shell escaping used to invoke the command.", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
#endif
    argsman.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);

#ifdef USE_BDB
    argsman.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
    argsman.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
    argsman.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
#else
    argsman.AddHiddenArgs({"-dblogsize", "-flushwallet", "-privdb"});
#endif

#ifdef USE_SQLITE
    argsman.AddArg("-unsafesqlitesync", "Set SQLite synchronous=OFF to disable waiting for the database to sync to disk. This is unsafe and can cause data loss and corruption. This option is only used by tests to improve their performance (default: false)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
#else
    argsman.AddHiddenArgs({"-unsafesqlitesync"});
#endif

    argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);

    argsman.AddHiddenArgs({"-zapwallettxes"});
}

bool WalletInit::ParameterInteraction() const
{
#ifdef USE_BDB
     if (!BerkeleyDatabaseSanityCheck()) {
         return InitError(Untranslated("A version conflict was detected between the run-time BerkeleyDB library and the one used during compilation."));
     }
#endif
    if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        for (const std::string& wallet : gArgs.GetArgs("-wallet")) {
            LogPrintf("%s: parameter interaction: -disablewallet -> ignoring -wallet=%s\n", __func__, wallet);
        }

        return true;
    }

    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) {
        LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__);
    }

    if (gArgs.IsArgSet("-zapwallettxes")) {
        return InitError(Untranslated("-zapwallettxes has been removed. If you are attempting to remove a stuck transaction from your wallet, please use abandontransaction instead."));
    }

    if (gArgs.GetBoolArg("-sysperms", false))
        return InitError(Untranslated("-sysperms is not allowed in combination with enabled wallet functionality"));

    return true;
}

void WalletInit::Construct(NodeContext& node) const
{
    ArgsManager& args = *Assert(node.args);
    if (args.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
        LogPrintf("Wallet disabled!\n");
        return;
    }
    auto wallet_client = node.init->makeWalletClient(*node.chain);
    node.wallet_client = wallet_client.get();
    node.chain_clients.emplace_back(std::move(wallet_client));
}
<|endoftext|>


<commit_before>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#include <GL/glew.h>

#include "vvibrclient.h"
#include "vvibr.h"
#include "vvshaderfactory.h"
#include "vvshaderprogram.h"
#include "vvsocketio.h"
#include "vvdebugmsg.h"
#include "vvvoldesc.h"
#include "vvpthread.h"

#include "private/vvgltools.h"
#include "private/vvibrimage.h"

#include "gl/util.h"

#include <stdexcept>

using std::cerr;
using std::endl;

struct vvIbrClient::Thread
{
  pthread_t thread;               ///< list for threads of each server connection
  virvo::Mutex mutex;
  virvo::SyncedCondition imageRequest;
  bool newImage;
  bool cancel;

  Thread()
    : newImage(false)
    , cancel(false)
  {
  }
};

vvIbrClient::vvIbrClient(vvVolDesc *vd, vvRenderState renderState,
                         vvTcpSocket* socket, const std::string& filename)
  : vvRemoteClient(vd, renderState, socket, filename)
  , _thread(new Thread)
  , _shader(vvShaderFactory().createProgram("ibr", "", "ibr"))
{
  vvDebugMsg::msg(1, "vvIbrClient::vvIbrClient()");

  rendererType = REMOTE_IBR;

  glewInit();

  if (!GLEW_VERSION_1_5)
    throw std::runtime_error("OpenGL 1.5 or later required");

  if (!_shader)
    throw std::runtime_error("Could not find ibr shaders");

  glGenBuffers(1, &_pointVBO);
  glGenTextures(1, &_rgbaTex);
  glGenTextures(1, &_depthTex);

  createThreads();
}

vvIbrClient::~vvIbrClient()
{
  vvDebugMsg::msg(1, "vvIbrClient::~vvIbrClient()");

  destroyThreads();

  glDeleteBuffers(1, &_pointVBO);
  glDeleteTextures(1, &_rgbaTex);
  glDeleteTextures(1, &_depthTex);

  delete _shader;
}

vvRemoteClient::ErrorType vvIbrClient::render()
{
  vvDebugMsg::msg(1, "vvIbrClient::render()");

  // Request a new image
  this->_thread->imageRequest.signal();

  bool imageValid = false;
  bool imageNew = false;

  {
    virvo::ScopedLock lock(&this->_thread->mutex);

    imageNew = this->_thread->newImage;

    // If the image changed, update the textures/buffers
    if (this->_thread->newImage)
    {
      initIbrFrame();
      this->_thread->newImage = false;
    }

    imageValid = _image.get() && _image->width() > 0 && _image->height() > 0;
  }

  if (!imageValid)
    return VV_OK;

  // Draw boundary lines
  if (_boundaries)
  {
    const vvVector3 size(vd->getSize()); // volume size [world coordinates]
    drawBoundingBox(size, vd->pos, _boundColor);
  }

  vvMatrix currentMatrix = _currentPr * _currentMv;

  float drMin = 0.0f;
  float drMax = 0.0f;
  vvAABB aabb = vvAABB(vvVector3(), vvVector3());
  vd->getBoundingBox(aabb);
  vvIbr::calcDepthRange(_currentPr, _currentMv, aabb, drMin, drMax);
  const virvo::Viewport vp = vvGLTools::getViewport();
  vvMatrix currentImgMatrix = vvIbr::calcImgMatrix(_currentPr, _currentMv, vp, drMin, drMax);
  bool matrixChanged = (!currentImgMatrix.equal(_imgMatrix));

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // prepare VBOs
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glVertexPointer(3, GL_FLOAT, 0, NULL);
  glEnableClientState(GL_VERTEX_ARRAY);

  vvMatrix reprojectionMatrix;
  if (!matrixChanged)
  {
    reprojectionMatrix.identity();
  }
  else
  {
    vvMatrix invOld = _imgPr * _imgMv;
    invOld.invert();
    reprojectionMatrix = currentMatrix * invOld;
  }
  vvMatrix invMv = _currentMv;
  invMv.invert();
  vvVector4 viewerObj(0.f, 0.f, 0.f, 1.f);
  viewerObj.multiply(invMv);
  viewerObj.multiply(_imgMv);
  bool closer = viewerObj[2] > 0.f; // inverse render order if viewer has moved closer

  // project current viewer onto original image along its normal
  viewerObj.multiply(_imgPr);
  float splitX = (viewerObj[0]/viewerObj[3]+1.f)*_imgVp[2]*0.5f;
  float splitY = (viewerObj[1]/viewerObj[3]+1.f)*_imgVp[3]*0.5f;
  splitX = ts_clamp(splitX, 0.f, float(_imgVp[2]-1));
  splitY = ts_clamp(splitY, 0.f, float(_imgVp[3]-1));

  GLboolean depthMask = GL_TRUE;
  glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
  glDepthMask(GL_FALSE);
  GLboolean pointSmooth = GL_FALSE;
  glGetBooleanv(GL_POINT_SMOOTH, &pointSmooth);
  //glEnable(GL_POINT_SMOOTH);

  glEnable(GL_POINT_SPRITE);
  glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

  _shader->enable();

  _shader->setParameter1f("vpWidth", static_cast<float>(vp[2]));
  _shader->setParameter1f("vpHeight", static_cast<float>(vp[3]));
  _shader->setParameter1f("imageWidth", static_cast<float>(_imgVp[2]));
  _shader->setParameter1f("imageHeight", static_cast<float>(_imgVp[3]));
  _shader->setParameterTex2D("rgbaTex", _rgbaTex);
  _shader->setParameterTex2D("depthTex", _depthTex);
  _shader->setParameter1f("splitX", splitX);
  _shader->setParameter1f("splitY", splitY);
  _shader->setParameter1f("depthMin", _imgDepthRange[0]);
  _shader->setParameter1f("depthRange", _imgDepthRange[1]-_imgDepthRange[0]);
  _shader->setParameter1i("closer", closer);
  _shader->setParameterMatrix4f("reprojectionMatrix" , reprojectionMatrix);

  //// begin ellipsoid test code - temporary

  // hardwired parameters for now
/*  float v_i[16] = {
    0.70710678f, 0.70710678f, 0.0f, 0.0f,
   -0.70710678f, 0.70710678f, 0.0f, 0.0f,
           0.0f,        0.0f, 1.0f, 0.0f,
           0.0f,        0.0f, 0.0f, 1.0f
  };*/
  float v_i[16] = {
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f
  };
  vvMatrix V_i = vvMatrix(v_i);
  V_i.invert();

  _shader->setParameter1f("si", 1.0);
  _shader->setParameter1f("sj", 1.0);
  _shader->setParameter1f("sk", 1.0);
  _shader->setParameterMatrix4f("V_i" , V_i);
  //// end ellipsoid test code - temporary

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glDrawArrays(GL_POINTS, 0, _imgVp[2]*_imgVp[3]);

  _shader->disable();

  if(depthMask)
    glDepthMask(GL_TRUE);
  if(!pointSmooth)
    glDisable(GL_POINT_SMOOTH);

  glDisableClientState(GL_VERTEX_ARRAY);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  return VV_OK;
}

void vvIbrClient::initIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::initIbrFrame()");

  const int h = _image->height();
  const int w = _image->width();

  _imgPr = _image->projMatrix();
  _imgMv = _image->viewMatrix();
  _imgDepthRange[0] = _image->depthMin();
  _imgDepthRange[1] = _image->depthMax();
  _imgMatrix = vvIbr::calcImgMatrix(_imgPr, _imgMv, _image->viewport(), _imgDepthRange[0], _imgDepthRange[1]);

  // get pixel and depth-data
  virvo::PixelFormat cf = mapPixelFormat(_image->format());

  glBindTexture(GL_TEXTURE_2D, _rgbaTex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, 0, cf.internalFormat, w, h, 0, cf.format, cf.type, _image->data());

  glBindTexture(GL_TEXTURE_2D, _depthTex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

  virvo::PixelFormat df = mapPixelFormat(_image->depthBufferFormat());

  glTexImage2D(GL_TEXTURE_2D, 0, df.internalFormat, w, h, 0, df.format, df.type, _image->depthData());

  if(_imgVp[2] == w && _imgVp[3] == h)
      return;

  _imgVp = _image->viewport();

  std::vector<GLfloat> points(w*h*3);

  for(int y = 0; y<h; y++)
  {
    for(int x = 0; x<w; x++)
    {
      points[y*w*3+x*3]   = static_cast<float>(x);
      points[y*w*3+x*3+1] = static_cast<float>(y);
      points[y*w*3+x*3+2] = 0.f;
    }
  }

  // VBO for points
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void vvIbrClient::createThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::createThreads()");

  pthread_create(&_thread->thread, NULL, getImageFromSocket, this);
}

void vvIbrClient::destroyThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::destroyThreads()");

  this->_thread->cancel = true;
  this->_thread->imageRequest.signal(); // wake up the thread in case it's waiting...

  pthread_join(_thread->thread, NULL);
}

#define THREAD_FAILURE ((void*)-1)

void* vvIbrClient::getImageFromSocket(void* threadargs)
{
  vvDebugMsg::msg(1, "vvIbrClient::getImageFromSocket(): thread started");

  vvIbrClient *ibr = static_cast<vvIbrClient*>(threadargs);

  for (;;)
  {
    // Block until a new request arrives...
    ibr->_thread->imageRequest.wait();

    // Exit?
    if (ibr->_thread->cancel)
      break;

    // Send the request
    if (VV_OK != ibr->requestFrame())
      return THREAD_FAILURE;

    // Create a new image
    std::auto_ptr<virvo::IbrImage> image(new virvo::IbrImage);

    // Get the image
    if (vvSocket::VV_OK != ibr->_socketIO->getIbrImage(*image))
      return THREAD_FAILURE;

    // Decompress the image
    if (!image->decompress())
      return THREAD_FAILURE;

    virvo::ScopedLock lock(&ibr->_thread->mutex);

    ibr->_image.reset(image.release()); // Swap the images
    ibr->_thread->newImage = true;
  }

  return 0;
}
// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<commit_msg>Remove unused variable<commit_after>// Virvo - Virtual Reality Volume Rendering
// Copyright (C) 1999-2003 University of Stuttgart, 2004-2005 Brown University
// Contact: Jurgen P. Schulze, jschulze@ucsd.edu
//
// This file is part of Virvo.
//
// Virvo is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library (see license.txt); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

#include <GL/glew.h>

#include "vvibrclient.h"
#include "vvibr.h"
#include "vvshaderfactory.h"
#include "vvshaderprogram.h"
#include "vvsocketio.h"
#include "vvdebugmsg.h"
#include "vvvoldesc.h"
#include "vvpthread.h"

#include "private/vvgltools.h"
#include "private/vvibrimage.h"

#include "gl/util.h"

#include <stdexcept>

using std::cerr;
using std::endl;

struct vvIbrClient::Thread
{
  pthread_t thread;               ///< list for threads of each server connection
  virvo::Mutex mutex;
  virvo::SyncedCondition imageRequest;
  bool newImage;
  bool cancel;

  Thread()
    : newImage(false)
    , cancel(false)
  {
  }
};

vvIbrClient::vvIbrClient(vvVolDesc *vd, vvRenderState renderState,
                         vvTcpSocket* socket, const std::string& filename)
  : vvRemoteClient(vd, renderState, socket, filename)
  , _thread(new Thread)
  , _shader(vvShaderFactory().createProgram("ibr", "", "ibr"))
{
  vvDebugMsg::msg(1, "vvIbrClient::vvIbrClient()");

  rendererType = REMOTE_IBR;

  glewInit();

  if (!GLEW_VERSION_1_5)
    throw std::runtime_error("OpenGL 1.5 or later required");

  if (!_shader)
    throw std::runtime_error("Could not find ibr shaders");

  glGenBuffers(1, &_pointVBO);
  glGenTextures(1, &_rgbaTex);
  glGenTextures(1, &_depthTex);

  createThreads();
}

vvIbrClient::~vvIbrClient()
{
  vvDebugMsg::msg(1, "vvIbrClient::~vvIbrClient()");

  destroyThreads();

  glDeleteBuffers(1, &_pointVBO);
  glDeleteTextures(1, &_rgbaTex);
  glDeleteTextures(1, &_depthTex);

  delete _shader;
}

vvRemoteClient::ErrorType vvIbrClient::render()
{
  vvDebugMsg::msg(1, "vvIbrClient::render()");

  // Request a new image
  this->_thread->imageRequest.signal();

  bool imageValid = false;

  {
    virvo::ScopedLock lock(&this->_thread->mutex);

    // If the image changed, update the textures/buffers
    if (this->_thread->newImage)
    {
      initIbrFrame();
      this->_thread->newImage = false;
    }

    imageValid = _image.get() && _image->width() > 0 && _image->height() > 0;
  }

  if (!imageValid)
    return VV_OK;

  // Draw boundary lines
  if (_boundaries)
  {
    const vvVector3 size(vd->getSize()); // volume size [world coordinates]
    drawBoundingBox(size, vd->pos, _boundColor);
  }

  vvMatrix currentMatrix = _currentPr * _currentMv;

  float drMin = 0.0f;
  float drMax = 0.0f;
  vvAABB aabb = vvAABB(vvVector3(), vvVector3());
  vd->getBoundingBox(aabb);
  vvIbr::calcDepthRange(_currentPr, _currentMv, aabb, drMin, drMax);
  const virvo::Viewport vp = vvGLTools::getViewport();
  vvMatrix currentImgMatrix = vvIbr::calcImgMatrix(_currentPr, _currentMv, vp, drMin, drMax);
  bool matrixChanged = (!currentImgMatrix.equal(_imgMatrix));

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  // prepare VBOs
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glVertexPointer(3, GL_FLOAT, 0, NULL);
  glEnableClientState(GL_VERTEX_ARRAY);

  vvMatrix reprojectionMatrix;
  if (!matrixChanged)
  {
    reprojectionMatrix.identity();
  }
  else
  {
    vvMatrix invOld = _imgPr * _imgMv;
    invOld.invert();
    reprojectionMatrix = currentMatrix * invOld;
  }
  vvMatrix invMv = _currentMv;
  invMv.invert();
  vvVector4 viewerObj(0.f, 0.f, 0.f, 1.f);
  viewerObj.multiply(invMv);
  viewerObj.multiply(_imgMv);
  bool closer = viewerObj[2] > 0.f; // inverse render order if viewer has moved closer

  // project current viewer onto original image along its normal
  viewerObj.multiply(_imgPr);
  float splitX = (viewerObj[0]/viewerObj[3]+1.f)*_imgVp[2]*0.5f;
  float splitY = (viewerObj[1]/viewerObj[3]+1.f)*_imgVp[3]*0.5f;
  splitX = ts_clamp(splitX, 0.f, float(_imgVp[2]-1));
  splitY = ts_clamp(splitY, 0.f, float(_imgVp[3]-1));

  GLboolean depthMask = GL_TRUE;
  glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
  glDepthMask(GL_FALSE);
  GLboolean pointSmooth = GL_FALSE;
  glGetBooleanv(GL_POINT_SMOOTH, &pointSmooth);
  //glEnable(GL_POINT_SMOOTH);

  glEnable(GL_POINT_SPRITE);
  glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

  _shader->enable();

  _shader->setParameter1f("vpWidth", static_cast<float>(vp[2]));
  _shader->setParameter1f("vpHeight", static_cast<float>(vp[3]));
  _shader->setParameter1f("imageWidth", static_cast<float>(_imgVp[2]));
  _shader->setParameter1f("imageHeight", static_cast<float>(_imgVp[3]));
  _shader->setParameterTex2D("rgbaTex", _rgbaTex);
  _shader->setParameterTex2D("depthTex", _depthTex);
  _shader->setParameter1f("splitX", splitX);
  _shader->setParameter1f("splitY", splitY);
  _shader->setParameter1f("depthMin", _imgDepthRange[0]);
  _shader->setParameter1f("depthRange", _imgDepthRange[1]-_imgDepthRange[0]);
  _shader->setParameter1i("closer", closer);
  _shader->setParameterMatrix4f("reprojectionMatrix" , reprojectionMatrix);

  //// begin ellipsoid test code - temporary

  // hardwired parameters for now
/*  float v_i[16] = {
    0.70710678f, 0.70710678f, 0.0f, 0.0f,
   -0.70710678f, 0.70710678f, 0.0f, 0.0f,
           0.0f,        0.0f, 1.0f, 0.0f,
           0.0f,        0.0f, 0.0f, 1.0f
  };*/
  float v_i[16] = {
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f
  };
  vvMatrix V_i = vvMatrix(v_i);
  V_i.invert();

  _shader->setParameter1f("si", 1.0);
  _shader->setParameter1f("sj", 1.0);
  _shader->setParameter1f("sk", 1.0);
  _shader->setParameterMatrix4f("V_i" , V_i);
  //// end ellipsoid test code - temporary

  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  glDrawArrays(GL_POINTS, 0, _imgVp[2]*_imgVp[3]);

  _shader->disable();

  if(depthMask)
    glDepthMask(GL_TRUE);
  if(!pointSmooth)
    glDisable(GL_POINT_SMOOTH);

  glDisableClientState(GL_VERTEX_ARRAY);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  return VV_OK;
}

void vvIbrClient::initIbrFrame()
{
  vvDebugMsg::msg(1, "vvIbrClient::initIbrFrame()");

  const int h = _image->height();
  const int w = _image->width();

  _imgPr = _image->projMatrix();
  _imgMv = _image->viewMatrix();
  _imgDepthRange[0] = _image->depthMin();
  _imgDepthRange[1] = _image->depthMax();
  _imgMatrix = vvIbr::calcImgMatrix(_imgPr, _imgMv, _image->viewport(), _imgDepthRange[0], _imgDepthRange[1]);

  // get pixel and depth-data
  virvo::PixelFormat cf = mapPixelFormat(_image->format());

  glBindTexture(GL_TEXTURE_2D, _rgbaTex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glTexImage2D(GL_TEXTURE_2D, 0, cf.internalFormat, w, h, 0, cf.format, cf.type, _image->data());

  glBindTexture(GL_TEXTURE_2D, _depthTex);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

  virvo::PixelFormat df = mapPixelFormat(_image->depthBufferFormat());

  glTexImage2D(GL_TEXTURE_2D, 0, df.internalFormat, w, h, 0, df.format, df.type, _image->depthData());

  if(_imgVp[2] == w && _imgVp[3] == h)
      return;

  _imgVp = _image->viewport();

  std::vector<GLfloat> points(w*h*3);

  for(int y = 0; y<h; y++)
  {
    for(int x = 0; x<w; x++)
    {
      points[y*w*3+x*3]   = static_cast<float>(x);
      points[y*w*3+x*3+1] = static_cast<float>(y);
      points[y*w*3+x*3+2] = 0.f;
    }
  }

  // VBO for points
  glBindBuffer(GL_ARRAY_BUFFER, _pointVBO);
  glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void vvIbrClient::createThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::createThreads()");

  pthread_create(&_thread->thread, NULL, getImageFromSocket, this);
}

void vvIbrClient::destroyThreads()
{
  vvDebugMsg::msg(1, "vvIbrClient::destroyThreads()");

  this->_thread->cancel = true;
  this->_thread->imageRequest.signal(); // wake up the thread in case it's waiting...

  pthread_join(_thread->thread, NULL);
}

#define THREAD_FAILURE ((void*)-1)

void* vvIbrClient::getImageFromSocket(void* threadargs)
{
  vvDebugMsg::msg(1, "vvIbrClient::getImageFromSocket(): thread started");

  vvIbrClient *ibr = static_cast<vvIbrClient*>(threadargs);

  for (;;)
  {
    // Block until a new request arrives...
    ibr->_thread->imageRequest.wait();

    // Exit?
    if (ibr->_thread->cancel)
      break;

    // Send the request
    if (VV_OK != ibr->requestFrame())
      return THREAD_FAILURE;

    // Create a new image
    std::auto_ptr<virvo::IbrImage> image(new virvo::IbrImage);

    // Get the image
    if (vvSocket::VV_OK != ibr->_socketIO->getIbrImage(*image))
      return THREAD_FAILURE;

    // Decompress the image
    if (!image->decompress())
      return THREAD_FAILURE;

    virvo::ScopedLock lock(&ibr->_thread->mutex);

    ibr->_image.reset(image.release()); // Swap the images
    ibr->_thread->newImage = true;
  }

  return 0;
}
// vim: sw=2:expandtab:softtabstop=2:ts=2:cino=\:0g0t0
<|endoftext|>


<commit_before>#include <windowClass.h>

void Window::setupRender(){
	glClearColor(0,0,0,0); //set the background color

}

void Window::render(){

	glMatrixMode(GL_PROJECTION); //set the matrix mode as projection so we can set the ortho size and the camera settings later on
    glPushMatrix(); //load the settings into the matrix
    glLoadIdentity(); //save the matrix

	glOrtho(0,SCREEN_WIDTH, 0,SCREEN_HEIGHT, -1,1); //set the the size of the screen

    glMatrixMode(GL_MODELVIEW); //set the matrix to modelview so we can draw objects
    glPushMatrix(); //load
    glLoadIdentity(); //save

	glPushMatrix(); //start a new matrix
	glClear(GL_COLOR_BUFFER_BIT); //clear the screen

	/**************************
	**** RENDER STUFF HERE ****
	**************************/
	glColor3f(1.0f, 0.0f, 0.0f);
	glRectf(0,0, 50,50); //draw a test rectangle
	glColor3f(0.0f, 1.0f, 0.0f);
	glRectf(50,0, 100,50);
	glColor3f(0.0f, 0.0f, 1.0f);
	glRectf(100,0,150,50);
	/**************************
	****  CLOSE THE LOOP   ****
	**************************/

	glPopMatrix(); //see ya' matrix
	SDL_GL_SwapWindow(window); //give the render to SDL to display it
}<commit_msg>Re-Documented the render loop<commit_after>#include <windowClass.h>

void Window::setupRender(){
	glClearColor(0,0,0,0); //set the background color

}

void Window::render(){
								 //a matrix is a blank canvas for the computer to draw on, the matrices are stored in a "stack"
								 //GL_PROJECTION has 2 matrices
								 //GL_MODELVIEW has 32 matrices
	glMatrixMode(GL_PROJECTION); //set the matrix mode as projection so we can set the ortho size and the camera settings later on
    glPushMatrix(); //push the  matrix to the top of the matrix stack
    glLoadIdentity(); //replace the entire matrix stack with the updated GL_PROJECTION mode

	glOrtho(0,SCREEN_WIDTH, 0,SCREEN_HEIGHT, -1,1); //set the the size of the screen

    glMatrixMode(GL_MODELVIEW); //set the matrix to modelview so we can draw objects
    glPushMatrix(); //push the  matrix to the top of the matrix stack
    glLoadIdentity(); //replace the entire matrix stack with the updated GL_MODELVIEW mode

	glPushMatrix(); //basically here we put a blank canvas (new matrix) on the screen to draw on
	glClear(GL_COLOR_BUFFER_BIT); //clear the matrix on the top of the stack

	/**************************
	**** RENDER STUFF HERE ****
	**************************/
	glColor3f(1.0f, 0.0f, 0.0f); //color to red
	glRectf(0,0, 50,50); //draw a test rectangle
	glColor3f(0.0f, 1.0f, 0.0f); //color to blue
	glRectf(50,0, 100,50); //draw a test rectangle
	glColor3f(0.0f, 0.0f, 1.0f); //color to green
	glRectf(100,0,150,50); //draw a test rectangle
	/**************************
	****  CLOSE THE LOOP   ****
	**************************/

	glPopMatrix(); //take the matrix(s) off the stack to pass them to the renderer
	SDL_GL_SwapWindow(window); //give the stack to SDL to render it
}<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <pthread.h>
#include <chrono>
#include <random>
#include "pin.H"
#include "plr.h"
#include "plrLog.h"
#include "plrSharedData.h"

///////////////////////////////////////////////////////////////////////////////
// Global variables
perProcData_t *nextProcToFault = NULL;
ADDRINT plrLoAddr, plrHiAddr;
std::default_random_engine g_randGen;
std::normal_distribution<double> g_eventDist;
std::uniform_int_distribution<int> g_procDist;

///////////////////////////////////////////////////////////////////////////////
// Commandline switches
KNOB<BOOL> KnobTraceFaultMode(KNOB_MODE_WRITEONCE, "pintool",
    "t", "1", "Enable trace fault injection mode");

///////////////////////////////////////////////////////////////////////////////

static INT32 Usage() {
  PIN_ERROR("Pintool for injecting transient faults.\n"
            + KNOB_BASE::StringKnobSummary() + "\n");
  return -1;
}

///////////////////////////////////////////////////////////////////////////////

VOID getPLRShm() {
  // BANDAID: The pintool seems to access a different plrShm than the process it's
  // attached to. Until a way to access the process's own plrShm is found,
  // we can just acquire the shared data area again for this separate pointer.
  if (plrShm == NULL && plrSD_acquireSharedData() < 0) {
    plrlog(LOG_ERROR, "Error: plrSD_acquireSharedData() failed in pintool\n");
    exit(1);
  }
  if (plrShm == NULL) {
    plrlog(LOG_ERROR,  "[%d:pin] plrShm still NULL in pintool\n", PIN_GetPid());
    exit(1);
  }

  // Set myProcShm properly inside Pintool
  int myPid = PIN_GetPid();
  if (myProcShm == NULL || myProcShm->pid != myPid) {
    for (int i = 0; i < plrShm->nProc; ++i) {
      if (allProcShm[i].pid == myPid) {
        myProcShm = &allProcShm[i];
        break;
      }
    }
    if (myProcShm == NULL) {
      plrlog(LOG_ERROR, "[%d:pin] myProcShm still NULL in pintool\n", PIN_GetPid());
      exit(1);
    }
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID updateNextProcToFault(BOOL initialCall) {
  getPLRShm();

  if (initialCall) {
    pthread_mutex_lock(&plrShm->toolLock);
  }

  // Choose the next PID to inject a fault into
  int curFaultPid = plrShm->nextFaultPid;
  if (curFaultPid == 0 || !initialCall) {
    int idx = g_procDist(g_randGen);
    int nextPid = allProcShm[idx].pid;

    if (nextPid != curFaultPid && nextPid != 0) {
      plrShm->nextFaultPid = nextPid;
      plrShm->nextFaultIdx = idx;
      plrShm->processFaulted = 0;
      plrlog(LOG_DEBUG, "[%d:pin] Updated next proc to fault to pid %d (idx %d)\n", PIN_GetPid(), nextPid, idx);
    }
  }

  // Choose the event count for the next fault injection
  plrShm->eventCount = 0;
  plrShm->targetCount = g_eventDist(g_randGen);

  if (initialCall) {
    pthread_mutex_unlock(&plrShm->toolLock);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID injectFault_trace() {
  // Only update next fault process after that process has failed and been
  // replaced
  if (plrShm->processFaulted == 1) {
    pthread_mutex_lock(&plrShm->toolLock);
    if (allProcShm[plrShm->nextFaultIdx].pid != plrShm->nextFaultPid) {
      updateNextProcToFault(FALSE);
    }
    pthread_mutex_unlock(&plrShm->toolLock);
  }

  // Make sure that myProcShm is pointing to the right area
  getPLRShm();

  // Exit if this isn't the process to be faulted
  if (plrShm->nextFaultPid != PIN_GetPid()) {
    return;
  }

  // Exit if this process is inside PLR code
  // Even though plrPreload traces aren't instruments, we could be inside another
  // library function called from PLR. This avoids injecting faults in that case.
  if (myProcShm->insidePLR) {
    return;
  }

  // Increment event count, kill process if reached target
  plrShm->eventCount++;
  if (plrShm->eventCount >= plrShm->targetCount) {
    plrShm->processFaulted = 1;
    plrlog(LOG_DEBUG, "[%d:pin] Pintool killing process after %ld events\n", PIN_GetPid(), plrShm->eventCount);
    PIN_ExitApplication(2);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID ImageLoad(IMG img, VOID *v) {
  // Insert a call after plr_processInit to initialize which process will
  // have a fault injected
  RTN rtn = RTN_FindByName(img, "plr_processInit");
  if (RTN_Valid(rtn)) {
    RTN_Open(rtn);
    RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)updateNextProcToFault, IARG_BOOL, TRUE, IARG_END);
    RTN_Close(rtn);
  }

  string imageName = IMG_Name(img);
  string targetLib = "libplrPreload.so";
  if (imageName.length() >= targetLib.length()
      && imageName.substr(imageName.length()-targetLib.length()) == targetLib)
  {
    plrLoAddr = IMG_LowAddress(img);
    plrHiAddr = IMG_HighAddress(img);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID InstrumentTrace(TRACE trace, VOID *arg) {
  // plrLoAddr/plrHiAddr used to avoid instrumenting traces from plrPreload library
  ADDRINT addr = TRACE_Address(trace);
  if (TRACE_Original(trace) && (addr < plrLoAddr || addr > plrHiAddr)) {
    TRACE_InsertCall(trace, IPOINT_BEFORE, (AFUNPTR)injectFault_trace, IARG_END);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID ApplicationStart(VOID *arg) {
  // The "inside PLR" flag is initialized to true during PLR startup if running with the
  // fault injection Pintool, so that syscalls related to Pin startup aren't emulated.
  // This clears that initial flag.
  getPLRShm();
  plr_clearInsidePLR();

  g_procDist = std::uniform_int_distribution<int>(0, plrShm->nProc-1);
}

///////////////////////////////////////////////////////////////////////////////

int main(int argc, char *argv[]) {
  // PIN_InitSymbols is required to search RTNs by name in ImageLoad
  PIN_InitSymbols();
  // Initialize Pin
  if(PIN_Init(argc,argv)) {
    return Usage();
  }

  // Initialize random number generator/distributions
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count() + PIN_GetPid();
  g_randGen = std::default_random_engine(seed);
  if (KnobTraceFaultMode) {
    g_eventDist = std::normal_distribution<double>(500,100);

    TRACE_AddInstrumentFunction(InstrumentTrace, NULL);
  } else {
    plrlog(LOG_ERROR, "Error: Only trace fault injection mode is available ('-t' option)\n");
    PIN_ExitApplication(1);
  }

  IMG_AddInstrumentFunction(ImageLoad, NULL);
  PIN_AddApplicationStartFunction(ApplicationStart, NULL);

  // Start the program, never returns
  PIN_StartProgram();

  return 0;
}
<commit_msg>Use plr_refreshSharedData instead of local function in fault injection pintool<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <pthread.h>
#include <chrono>
#include <random>
#include "pin.H"
#include "plr.h"
#include "plrLog.h"
#include "plrSharedData.h"

///////////////////////////////////////////////////////////////////////////////
// Global variables
perProcData_t *nextProcToFault = NULL;
ADDRINT plrLoAddr, plrHiAddr;
std::default_random_engine g_randGen;
std::normal_distribution<double> g_eventDist;
std::uniform_int_distribution<int> g_procDist;

///////////////////////////////////////////////////////////////////////////////
// Commandline switches
KNOB<BOOL> KnobTraceFaultMode(KNOB_MODE_WRITEONCE, "pintool",
    "t", "1", "Enable trace fault injection mode");

///////////////////////////////////////////////////////////////////////////////

static INT32 Usage() {
  PIN_ERROR("Pintool for injecting transient faults.\n"
            + KNOB_BASE::StringKnobSummary() + "\n");
  return -1;
}

///////////////////////////////////////////////////////////////////////////////

VOID updateNextProcToFault(BOOL initialCall) {
  plr_refreshSharedData();

  if (initialCall) {
    pthread_mutex_lock(&plrShm->toolLock);
  }

  // Choose the next PID to inject a fault into
  int curFaultPid = plrShm->nextFaultPid;
  if (curFaultPid == 0 || !initialCall) {
    int idx = g_procDist(g_randGen);
    int nextPid = allProcShm[idx].pid;

    if (nextPid != curFaultPid && nextPid != 0) {
      plrShm->nextFaultPid = nextPid;
      plrShm->nextFaultIdx = idx;
      plrShm->processFaulted = 0;
      plrlog(LOG_DEBUG, "[%d:pin] Updated next proc to fault to pid %d (idx %d)\n", PIN_GetPid(), nextPid, idx);
    }
  }

  // Choose the event count for the next fault injection
  plrShm->eventCount = 0;
  plrShm->targetCount = g_eventDist(g_randGen);

  if (initialCall) {
    pthread_mutex_unlock(&plrShm->toolLock);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID injectFault_trace() {
  // Only update next fault process after that process has failed and been
  // replaced
  if (plrShm->processFaulted == 1) {
    pthread_mutex_lock(&plrShm->toolLock);
    if (allProcShm[plrShm->nextFaultIdx].pid != plrShm->nextFaultPid) {
      updateNextProcToFault(FALSE);
    }
    pthread_mutex_unlock(&plrShm->toolLock);
  }

  // Make sure that myProcShm is pointing to the right area
  plr_refreshSharedData();

  // Exit if this isn't the process to be faulted
  if (plrShm->nextFaultPid != PIN_GetPid()) {
    return;
  }

  // Exit if this process is inside PLR code
  // Even though plrPreload traces aren't instruments, we could be inside another
  // library function called from PLR. This avoids injecting faults in that case.
  if (myProcShm->insidePLR) {
    return;
  }

  // Increment event count, kill process if reached target
  plrShm->eventCount++;
  if (plrShm->eventCount >= plrShm->targetCount) {
    plrShm->processFaulted = 1;
    plrlog(LOG_DEBUG, "[%d:pin] Pintool killing process after %ld events\n", PIN_GetPid(), plrShm->eventCount);
    PIN_ExitApplication(2);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID ImageLoad(IMG img, VOID *v) {
  // Insert a call after plr_processInit to initialize which process will
  // have a fault injected
  RTN rtn = RTN_FindByName(img, "plr_processInit");
  if (RTN_Valid(rtn)) {
    RTN_Open(rtn);
    RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)updateNextProcToFault, IARG_BOOL, TRUE, IARG_END);
    RTN_Close(rtn);
  }

  string imageName = IMG_Name(img);
  string targetLib = "libplrPreload.so";
  if (imageName.length() >= targetLib.length()
      && imageName.substr(imageName.length()-targetLib.length()) == targetLib)
  {
    plrLoAddr = IMG_LowAddress(img);
    plrHiAddr = IMG_HighAddress(img);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID InstrumentTrace(TRACE trace, VOID *arg) {
  // plrLoAddr/plrHiAddr used to avoid instrumenting traces from plrPreload library
  ADDRINT addr = TRACE_Address(trace);
  if (TRACE_Original(trace) && (addr < plrLoAddr || addr > plrHiAddr)) {
    TRACE_InsertCall(trace, IPOINT_BEFORE, (AFUNPTR)injectFault_trace, IARG_END);
  }
}

///////////////////////////////////////////////////////////////////////////////

VOID ApplicationStart(VOID *arg) {
  // The "inside PLR" flag is initialized to true during PLR startup if running with the
  // fault injection Pintool, so that syscalls related to Pin startup aren't emulated.
  // This clears that initial flag.
  plr_refreshSharedData();
  plr_clearInsidePLR();

  g_procDist = std::uniform_int_distribution<int>(0, plrShm->nProc-1);
}

///////////////////////////////////////////////////////////////////////////////

int main(int argc, char *argv[]) {
  // PIN_InitSymbols is required to search RTNs by name in ImageLoad
  PIN_InitSymbols();
  // Initialize Pin
  if(PIN_Init(argc,argv)) {
    return Usage();
  }

  // Initialize random number generator/distributions
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count() + PIN_GetPid();
  g_randGen = std::default_random_engine(seed);
  if (KnobTraceFaultMode) {
    g_eventDist = std::normal_distribution<double>(500,100);

    TRACE_AddInstrumentFunction(InstrumentTrace, NULL);
  } else {
    plrlog(LOG_ERROR, "Error: Only trace fault injection mode is available ('-t' option)\n");
    PIN_ExitApplication(1);
  }

  IMG_AddInstrumentFunction(ImageLoad, NULL);
  PIN_AddApplicationStartFunction(ApplicationStart, NULL);

  // Start the program, never returns
  PIN_StartProgram();

  return 0;
}
<|endoftext|>


<commit_before>/**********************************************************************
 *
 *    FILE:            ReaderWriterdds.cpp
 *
 *    DESCRIPTION:    Class for reading a DDS file into an osg::Image.
 *
 *                    Example on reading a DDS file code can be found at:
 *                    http://developer.nvidia.com/docs/IO/1327/ATT/
 *                    ARB_texture_compression.pdf
 *                    Author: Sbastien Domin, NVIDIA Corporation
 *
 *    CREATED BY:        Rune Schmidt Jensen, rsj@uni-dk
 *
 *    HISTORY:        Created 31.03.2003
 *
  **********************************************************************/

#include <osg/Texture>
#include <osg/Notify>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

#include <stdio.h>

// NOTICE ON WIN32:
// typedef DWORD unsigned long;
// sizeof(DWORD) = 4
typedef struct _DDCOLORKEY
{
    unsigned long    dwColorSpaceLowValue;
    unsigned long    dwColorSpaceHighValue;
} DDCOLORKEY;

typedef struct _DDPIXELFORMAT
{
    unsigned long    dwSize;
    unsigned long    dwFlags;
    unsigned long    dwFourCC;
    union
    {
        unsigned long    dwRGBBitCount;
        unsigned long    dwYUVBitCount;
        unsigned long    dwZBufferBitDepth;
        unsigned long    dwAlphaBitDepth;
    };
    union
    {
        unsigned long    dwRBitMask;
        unsigned long    dwYBitMask;
    };
    union
    {
        unsigned long    dwGBitMask;
        unsigned long    dwUBitMask;
    };
    union
    {
        unsigned long    dwBBitMask;
        unsigned long    dwVBitMask;
    };
    union
    {
        unsigned long    dwRGBAlphaBitMask;
        unsigned long    dwYUVAlphaBitMask;
        unsigned long    dwRGBZBitMask;
        unsigned long    dwYUVZBitMask;
    };
} DDPIXELFORMAT;

typedef struct _DDSCAPS2
{
    unsigned long       dwCaps;
    unsigned long       dwCaps2;
    unsigned long       dwCaps3;
    union
    {
        unsigned long       dwCaps4;
        unsigned long       dwVolumeDepth;
    };
} DDSCAPS2;

typedef struct _DDSURFACEDESC2
{
    unsigned long         dwSize;
    unsigned long         dwFlags;
    unsigned long         dwHeight;
    unsigned long         dwWidth;
    union
    {
        long              lPitch;
        unsigned long     dwLinearSize;
    };
    unsigned long         dwBackBufferCount;
    union
    {
        unsigned long     dwMipMapCount;
        unsigned long     dwRefreshRate;
    };
    unsigned long         dwAlphaBitDepth;
    unsigned long         dwReserved;
    unsigned long*        lpSurface;
    DDCOLORKEY    ddckCKDestOverlay;
    DDCOLORKEY    ddckCKDestBlt;
    DDCOLORKEY    ddckCKSrcOverlay;
    DDCOLORKEY    ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2      ddsCaps;
    unsigned long         dwTextureStage;
} DDSURFACEDESC2;

#define DDPF_ALPHAPIXELS        0x00000001l
#define DDPF_FOURCC                0x00000004l
#define DDPF_RGB                0x00000040l

#ifndef MAKEFOURCC
    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
                ((unsigned long)(char)(ch0) | ((unsigned long)(char)(ch1) << 8) |   \
                ((unsigned long)(char)(ch2) << 16) | ((unsigned long)(char)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)

/*
 * FOURCC codes for DX compressed-texture pixel formats
 */
#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))

void shiftAlpha(int*imageData, int size){

    for(int i=0;i<size/4;i++){
        imageData[i] = imageData[i]<<8;
    }

}

osg::Image* ReadDDSFile(const char *filename)
{
    osg::Image* osgImage = new osg::Image();

    DDSURFACEDESC2 ddsd;

    char filecode[4];
    FILE *fp;

    // Open file.
    fp = fopen(filename, "rb");
    if (fp == NULL)
        return NULL;

    // Verify that this is a DDS file.
    fread(filecode, 1, 4, fp);
    if (strncmp(filecode, "DDS ", 4) != 0) {
        fclose(fp);
        return NULL;
    }

    // Get the surface desc.
    fread(&ddsd, sizeof(ddsd), 1, fp);

    // Read image data.
    unsigned int size = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize;
    unsigned char* imageData = new unsigned char [size];
    fread(imageData, 1, size, fp);
    // Close the file.
    fclose(fp);

    // Retreive image properties.
    int s = ddsd.dwWidth;
    int t = ddsd.dwHeight;
    int r = 1; // we're not a 3d texture...
    unsigned int dataType = GL_UNSIGNED_BYTE;
    unsigned int pixelFormat = 0;
    unsigned int internalFormat = 0;

    // Uncompressed formats will usually use DDPF_RGB to indicate an RGB format,
    // while compressed formats will use DDPF_FOURCC with a four-character code.

    // Uncompressed formats.
    if(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
    {
        bool usingAlpha = ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
        switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
        {
            case 32:
                internalFormat = usingAlpha ? 4 : 3;
                pixelFormat = usingAlpha ? GL_RGBA  : GL_RGB;
                break;
            case 24:
            case 16:
            default:
                delete [] imageData;
                return NULL;
        }
    }
    // Compressed formats.
    else if(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
    {
        switch(ddsd.ddpfPixelFormat.dwFourCC)
        {
            case FOURCC_DXT1:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            default:
                delete [] imageData;
                return NULL;
        }
    }
    else
    {
        osg::notify(osg::WARN)<<"Warning:: unhanlded pixel format in dds file, image not loaded."<<std::endl;
        delete [] imageData;
        return NULL;
    }

    // Take care of mipmaps if any.
    if (ddsd.dwMipMapCount>1)
    {
        // Now set mipmap data (offsets into image raw data).
        osg::Image::MipmapDataType mipmaps;
        // Number of offsets in osg is one less than num_mipmaps
        // because it's assumed that first offset is 0.
        mipmaps.resize(ddsd.dwMipMapCount-1);

        // Handle compressed mipmaps.
        if(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
        {
            int width = ddsd.dwWidth;
            int height = ddsd.dwHeight;
            int blockSize = (pixelFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
            int offset = 0;
            for (unsigned int k = 1; k < ddsd.dwMipMapCount && (width || height); ++k)
            {
                if (width == 0)
                    width = 1;
                if (height == 0)
                    height = 1;
                size = ((width+3)/4)*((height+3)/4)*blockSize;
                offset += size;
                mipmaps[k-1] = offset;
                width >>= 1;
                height >>= 1;
            }
            osgImage->setMipmapData(mipmaps);
        }
        // Handle uncompressed mipmaps
        if(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
        {
            int offset = 0;
            int width = ddsd.dwWidth;
            int height = ddsd.dwHeight;
            for (unsigned int k = 1; k < ddsd.dwMipMapCount && (width || height); ++k)
            {
                if (width == 0)
                    width = 1;
                if (height == 0)
                    height = 1;
                size = s*t*(ddsd.ddpfPixelFormat.dwRGBBitCount/8);
                offset += size;
                mipmaps[k-1] = offset;
                width >>= 1;
                height >>= 1;
            }
            osgImage->setMipmapData(mipmaps);
        }
    }

    // Set image data and properties.
    osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE);

    // Return Image.
    return osgImage;
}

class ReaderWriterDDS : public osgDB::ReaderWriter
{
    public:
        virtual const char* className()
        {
            return "DDS Image Reader";
        }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"dds");
        }

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*)
        {
            osg::Image* osgImage = ReadDDSFile(fileName.c_str());
            if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
            return osgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDDS> g_readerWriter_DDS_Proxy;
<commit_msg>Fixes to dds plugin from Rune.<commit_after>/**********************************************************************
 *
 *    FILE:            ReaderWriterdds.cpp
 *
 *    DESCRIPTION:    Class for reading a DDS file into an osg::Image.
 *
 *                    Example on reading a DDS file code can be found at:
 *                    http://developer.nvidia.com/docs/IO/1327/ATT/
 *                    ARB_texture_compression.pdf
 *                    Author: Sbastien Domin, NVIDIA Corporation
 *
 *    CREATED BY:        Rune Schmidt Jensen, rsj@uni-dk
 *
 *    HISTORY:        Created 31.03.2003
 *
  **********************************************************************/

#include <osg/Texture>
#include <osg/Notify>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

#include <stdio.h>

// NOTICE ON WIN32:
// typedef DWORD unsigned long;
// sizeof(DWORD) = 4
typedef struct _DDCOLORKEY
{
    unsigned long    dwColorSpaceLowValue;
    unsigned long    dwColorSpaceHighValue;
} DDCOLORKEY;

typedef struct _DDPIXELFORMAT
{
    unsigned long    dwSize;
    unsigned long    dwFlags;
    unsigned long    dwFourCC;
    union
    {
        unsigned long    dwRGBBitCount;
        unsigned long    dwYUVBitCount;
        unsigned long    dwZBufferBitDepth;
        unsigned long    dwAlphaBitDepth;
    };
    union
    {
        unsigned long    dwRBitMask;
        unsigned long    dwYBitMask;
    };
    union
    {
        unsigned long    dwGBitMask;
        unsigned long    dwUBitMask;
    };
    union
    {
        unsigned long    dwBBitMask;
        unsigned long    dwVBitMask;
    };
    union
    {
        unsigned long    dwRGBAlphaBitMask;
        unsigned long    dwYUVAlphaBitMask;
        unsigned long    dwRGBZBitMask;
        unsigned long    dwYUVZBitMask;
    };
} DDPIXELFORMAT;

typedef struct _DDSCAPS2
{
    unsigned long       dwCaps;
    unsigned long       dwCaps2;
    unsigned long       dwCaps3;
    union
    {
        unsigned long       dwCaps4;
        unsigned long       dwVolumeDepth;
    };
} DDSCAPS2;

typedef struct _DDSURFACEDESC2
{
    unsigned long         dwSize;
    unsigned long         dwFlags;
    unsigned long         dwHeight;
    unsigned long         dwWidth;
    union
    {
        long              lPitch;
        unsigned long     dwLinearSize;
    };
    unsigned long         dwBackBufferCount;
    union
    {
        unsigned long     dwMipMapCount;
        unsigned long     dwRefreshRate;
    };
    unsigned long         dwAlphaBitDepth;
    unsigned long         dwReserved;
    unsigned long*        lpSurface;
    DDCOLORKEY    ddckCKDestOverlay;
    DDCOLORKEY    ddckCKDestBlt;
    DDCOLORKEY    ddckCKSrcOverlay;
    DDCOLORKEY    ddckCKSrcBlt;
    DDPIXELFORMAT ddpfPixelFormat;
    DDSCAPS2      ddsCaps;
    unsigned long         dwTextureStage;
} DDSURFACEDESC2;

#define DDPF_ALPHAPIXELS        0x00000001l
#define DDPF_FOURCC                0x00000004l
#define DDPF_RGB                0x00000040l

#ifndef MAKEFOURCC
    #define MAKEFOURCC(ch0, ch1, ch2, ch3)                              \
                ((unsigned long)(char)(ch0) | ((unsigned long)(char)(ch1) << 8) |   \
                ((unsigned long)(char)(ch2) << 16) | ((unsigned long)(char)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)

/*
 * FOURCC codes for DX compressed-texture pixel formats
 */
#define FOURCC_DXT1  (MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT2  (MAKEFOURCC('D','X','T','2'))
#define FOURCC_DXT3  (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4  (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5  (MAKEFOURCC('D','X','T','5'))

osg::Image* ReadDDSFile(const char *filename)
{
    osg::Image* osgImage = new osg::Image();

    DDSURFACEDESC2 ddsd;

    char filecode[4];
    FILE *fp;

    // Open file.
    fp = fopen(filename, "rb");
    if (fp == NULL)
        return NULL;

    // Verify that this is a DDS file.
    fread(filecode, 1, 4, fp);
    if (strncmp(filecode, "DDS ", 4) != 0) {
        fclose(fp);
        return NULL;
    }

    // Get the surface desc.
    fread(&ddsd, sizeof(ddsd), 1, fp);

    // Read image data.
    unsigned int size = ddsd.dwMipMapCount > 1 ? ddsd.dwLinearSize * 2 : ddsd.dwLinearSize;
    unsigned char* imageData = new unsigned char [size];
    fread(imageData, 1, size, fp);
    // Close the file.
    fclose(fp);

    // Retreive image properties.
    int s = ddsd.dwWidth;
    int t = ddsd.dwHeight;
    int r = 1; // we're not a 3d texture...
    unsigned int dataType = GL_UNSIGNED_BYTE;
    unsigned int pixelFormat = 0;
    unsigned int internalFormat = 0;

    // Uncompressed formats will usually use DDPF_RGB to indicate an RGB format,
    // while compressed formats will use DDPF_FOURCC with a four-character code.

    // Uncompressed formats.
    if(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
    {
        bool usingAlpha = ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS;
        switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
        {
            case 32:
                internalFormat = usingAlpha ? 4 : 3;
                pixelFormat = usingAlpha ? GL_RGBA  : GL_RGB;
                break;
            case 24:
            case 16:
            default:
                osg::notify(osg::WARN)<<"Warning:: unhandled pixel format in dds file, image not loaded."<<std::endl;
                delete [] imageData;
                return NULL;
        }
    }
    // Compressed formats.
    else if(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
    {
        switch(ddsd.ddpfPixelFormat.dwFourCC)
        {
            case FOURCC_DXT1:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
                break;
            case FOURCC_DXT3:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
                break;
            case FOURCC_DXT5:
                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                pixelFormat    = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
                break;
            default:
                osg::notify(osg::WARN)<<"Warning:: unhandled pixel format in dds file, image not loaded."<<std::endl;
                delete [] imageData;
                return NULL;
        }
    }
    else
    {
        osg::notify(osg::WARN)<<"Warning:: unhandled pixel format in dds file, image not loaded."<<std::endl;
        delete [] imageData;
        return NULL;
    }

    // NOTE: We need to set the image data before setting the mipmap data, this
    // is because the setImage method clears the _mipmapdata vector in osg::Image.
    // Set image data and properties.
    osgImage->setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE);

    // Take care of mipmaps if any.
    if (ddsd.dwMipMapCount>1)
    {
        // Now set mipmap data (offsets into image raw data).
        osg::Image::MipmapDataType mipmaps;
        // Number of offsets in osg is one less than num_mipmaps
        // because it's assumed that first offset is 0.
        mipmaps.resize(ddsd.dwMipMapCount-1);

        // Handle compressed mipmaps.
        if(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
        {
            int width = ddsd.dwWidth;
            int height = ddsd.dwHeight;
            int blockSize = (pixelFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
            int offset = 0;
            for (unsigned int k = 1; k < ddsd.dwMipMapCount && (width || height); ++k)
            {
                if (width == 0)
                    width = 1;
                if (height == 0)
                    height = 1;
                size = ((width+3)/4)*((height+3)/4)*blockSize;
                offset += size;
                mipmaps[k-1] = offset;
                width >>= 1;
                height >>= 1;
            }
            osgImage->setMipmapData(mipmaps);
        }
        // Handle uncompressed mipmaps
        if(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
        {
            int offset = 0;
            int width = ddsd.dwWidth;
            int height = ddsd.dwHeight;
            for (unsigned int k = 1; k < ddsd.dwMipMapCount && (width || height); ++k)
            {
                if (width == 0)
                    width = 1;
                if (height == 0)
                    height = 1;
                size = width*height*(ddsd.ddpfPixelFormat.dwRGBBitCount/8);
                offset += size;
                mipmaps[k-1] = offset;
                width >>= 1;
                height >>= 1;
            }
            osgImage->setMipmapData(mipmaps);
        }
    }

    // Return Image.
    return osgImage;
}

class ReaderWriterDDS : public osgDB::ReaderWriter
{
    public:
        virtual const char* className()
        {
            return "DDS Image Reader";
        }

        virtual bool acceptsExtension(const std::string& extension)
        {
            return osgDB::equalCaseInsensitive(extension,"dds");
        }

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*)
        {
            osg::Image* osgImage = ReadDDSFile(fileName.c_str());
            if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
            return osgImage;

        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDDS> g_readerWriter_DDS_Proxy;
<|endoftext|>


<commit_before>#include <osg/Image>
#include "osg/Notify"
#include <osg/Geode>
#include <osg/GL>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

using namespace osg;

extern "C"
{
    #include <zlib.h>
    #include <png.h>
}

/* Transparency parameters */
#define PNG_ALPHA     -2         /* Use alpha channel in PNG file, if there is one */
#define PNG_SOLID     -1         /* No transparency                                */
#define PNG_STENCIL    0         /* Sets alpha to 0 for r=g=b=0, 1 otherwise       */

typedef struct
{
    unsigned int Width;
    unsigned int Height;
    unsigned int Depth;
    unsigned int Alpha;
} pngInfo;

class ReaderWriterPNG : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() { return "PNG Image Reader/Writer"; }
        virtual bool acceptsExtension(const std::string& extension) { return osgDB::equalCaseInsensitive(extension,"png"); }

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*)
        {

            if( !acceptsExtension(osgDB::getFileExtension(fileName) ))
                return ReadResult::FILE_NOT_HANDLED;

            int trans = PNG_ALPHA;
            FILE *fp = NULL;
            pngInfo pInfo;
            pngInfo *pinfo = &pInfo;

            unsigned char header[8];
            png_structp png;
            png_infop   info;
            png_infop   endinfo;
            png_bytep   data;    //, data2;
            png_bytep  *row_p;
            double  fileGamma;

            png_uint_32 width, height;
            int depth, color;

            png_uint_32 i;
            png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
            info = png_create_info_struct(png);
            endinfo = png_create_info_struct(png);

            fp = fopen(fileName.c_str(), "rb");
            if (fp && fread(header, 1, 8, fp) && png_check_sig(header, 8))
                png_init_io(png, fp);
            else
            {
                png_destroy_read_struct(&png, &info, &endinfo);
                return ReadResult::FILE_NOT_HANDLED;
            }
            png_set_sig_bytes(png, 8);

            png_read_info(png, info);
            png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

            if (pinfo != NULL)
            {
                pinfo->Width  = width;
                pinfo->Height = height;
                pinfo->Depth  = depth;
            }

            if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
                png_set_gray_to_rgb(png);

            if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA)
            {
                png_set_strip_alpha(png);
                color &= ~PNG_COLOR_MASK_ALPHA;
            }

            //	if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
            if (color == PNG_COLOR_TYPE_PALETTE)
                png_set_expand(png);

            /*--GAMMA--*/
            //	checkForGammaEnv();
            double screenGamma = 2.2 / 1.0;
            if (png_get_gAMA(png, info, &fileGamma))
                png_set_gamma(png, screenGamma, fileGamma);
            else
                png_set_gamma(png, screenGamma, 1.0/2.2);

            png_read_update_info(png, info);

            data = (png_bytep) new unsigned char [png_get_rowbytes(png, info)*height];
            row_p = new png_bytep [height];

            bool StandardOrientation = true;
            for (i = 0; i < height; i++)
            {
                if (StandardOrientation)
                    row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
                else
                    row_p[i] = &data[png_get_rowbytes(png, info)*i];
            }

            png_read_image(png, row_p);
            delete [] row_p;

            int iBitCount=0;

            if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA)
            {
                switch (color)
                {
                    case PNG_COLOR_TYPE_GRAY:
                    case PNG_COLOR_TYPE_RGB:
                    case PNG_COLOR_TYPE_PALETTE:
                        iBitCount = 24;
                        if (pinfo != NULL) pinfo->Alpha = 0;
                        break;

                    case PNG_COLOR_TYPE_GRAY_ALPHA:
                    case PNG_COLOR_TYPE_RGB_ALPHA:
                        iBitCount = 32;
                        if (pinfo != NULL) pinfo->Alpha = 8;
                        break;

                    default:
                        // error, will force return of ReadResult::FILE_NOT_HANDLED
                        // see below.
                        iBitCount = 0;
                }
            }

            png_read_end(png, endinfo);
            png_destroy_read_struct(&png, &info, &endinfo);

            //	delete [] data;

            if (fp)
                fclose(fp);

            if (iBitCount==0)
                return ReadResult::FILE_NOT_HANDLED;

            osg::Image* pOsgImage = new osg::Image();

            pOsgImage->setFileName(fileName.c_str());
            if (iBitCount == 24)
                pOsgImage->setImage(width, height, 1,
                    iBitCount / 8,// int internalFormat,
                    GL_RGB,      // unsigned int pixelFormat
                    GL_UNSIGNED_BYTE,// unsigned int dataType
                    data,
                    osg::Image::USE_NEW_DELETE);
            else
                pOsgImage->setImage(width, height, 1,
                    iBitCount / 8,// int internalFormat,
                    GL_RGBA,     // unsigned int pixelFormat
                    GL_UNSIGNED_BYTE,// unsigned int dataType
                    data,
                    osg::Image::USE_NEW_DELETE);
            return pOsgImage;
        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterPNG> g_readerWriter_PNG_Proxy;
<commit_msg>Fixed PNG plugin so it handles endianess correctly, and alpha/grey scale textures.<commit_after>#include <osg/Image>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/GL>
#include <osg/Endian>

#include <osgDB/Registry>
#include <osgDB/FileNameUtils>

using namespace osg;

extern "C"
{
    #include <zlib.h>
    #include <png.h>
}

/* Transparency parameters */
#define PNG_ALPHA     -2         /* Use alpha channel in PNG file, if there is one */
#define PNG_SOLID     -1         /* No transparency                                */
#define PNG_STENCIL    0         /* Sets alpha to 0 for r=g=b=0, 1 otherwise       */

typedef struct
{
    unsigned int Width;
    unsigned int Height;
    unsigned int Depth;
    unsigned int Alpha;
} pngInfo;

class ReaderWriterPNG : public osgDB::ReaderWriter
{
    public:
        virtual const char* className() { return "PNG Image Reader/Writer"; }
        virtual bool acceptsExtension(const std::string& extension) { return osgDB::equalCaseInsensitive(extension,"png"); }

        virtual ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options*)
        {

            if( !acceptsExtension(osgDB::getFileExtension(fileName) ))
                return ReadResult::FILE_NOT_HANDLED;

            int trans = PNG_ALPHA;
            FILE *fp = NULL;
            pngInfo pInfo;
            pngInfo *pinfo = &pInfo;

            unsigned char header[8];
            png_structp png;
            png_infop   info;
            png_infop   endinfo;
            png_bytep   data;    //, data2;
            png_bytep  *row_p;
            double  fileGamma;

            png_uint_32 width, height;
            int depth, color;

            png_uint_32 i;
            png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
            info = png_create_info_struct(png);
            endinfo = png_create_info_struct(png);

            fp = fopen(fileName.c_str(), "rb");
            if (fp && fread(header, 1, 8, fp) && png_check_sig(header, 8))
                png_init_io(png, fp);
            else
            {
                png_destroy_read_struct(&png, &info, &endinfo);
                return ReadResult::FILE_NOT_HANDLED;
            }
            png_set_sig_bytes(png, 8);

            png_read_info(png, info);
            png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

            if (pinfo != NULL)
            {
                pinfo->Width  = width;
                pinfo->Height = height;
                pinfo->Depth  = depth;
            }

            osg::notify(osg::INFO)<<"width="<<width<<" height="<<height<<" depth="<<depth<<std::endl;
            if ( color == PNG_COLOR_TYPE_RGB) osg::notify(osg::INFO) << "color == PNG_COLOR_TYPE_RGB "<<std::endl;
            if ( color == PNG_COLOR_TYPE_GRAY) osg::notify(osg::INFO) << "color == PNG_COLOR_TYPE_GRAY "<<std::endl;
            if ( color == PNG_COLOR_TYPE_GRAY_ALPHA) osg::notify(osg::INFO) << "color ==  PNG_COLOR_TYPE_GRAY_ALPHA"<<std::endl;

            // png default to big endian, so we'll need to swap bytes if on a little endian machine.
            if (depth>8 && getCpuByteOrder()==osg::LittleEndian)
                png_set_swap(png);

            if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
            {
                //png_set_gray_to_rgb(png);
            }

            if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA)
            {
                png_set_strip_alpha(png);
                color &= ~PNG_COLOR_MASK_ALPHA;
            }

            //	if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
            if (color == PNG_COLOR_TYPE_PALETTE)
                png_set_expand(png);

            /*--GAMMA--*/
            //	checkForGammaEnv();
            double screenGamma = 2.2 / 1.0;
            if (png_get_gAMA(png, info, &fileGamma))
                png_set_gamma(png, screenGamma, fileGamma);
            else
                png_set_gamma(png, screenGamma, 1.0/2.2);

            png_read_update_info(png, info);

            data = (png_bytep) new unsigned char [png_get_rowbytes(png, info)*height];
            row_p = new png_bytep [height];

            bool StandardOrientation = true;
            for (i = 0; i < height; i++)
            {
                if (StandardOrientation)
                    row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
                else
                    row_p[i] = &data[png_get_rowbytes(png, info)*i];
            }

            png_read_image(png, row_p);
            delete [] row_p;

            GLenum pixelFormat = 0;
            GLenum dataType = depth==8?GL_UNSIGNED_BYTE:GL_UNSIGNED_SHORT;
            switch(color)
            {
              case(PNG_SOLID): pixelFormat = GL_LUMINANCE; break;
              case(PNG_ALPHA): pixelFormat = GL_ALPHA; break;
              case(PNG_COLOR_TYPE_GRAY): pixelFormat =GL_LUMINANCE ; break;
              case(PNG_COLOR_TYPE_GRAY_ALPHA): pixelFormat = GL_LUMINANCE_ALPHA; break;
              case(PNG_COLOR_TYPE_RGB): pixelFormat = GL_RGB; break;
              case(PNG_COLOR_TYPE_RGB_ALPHA): pixelFormat = GL_RGBA; break;
              default: break;
            }

            int internalFormat = pixelFormat;

            png_read_end(png, endinfo);
            png_destroy_read_struct(&png, &info, &endinfo);

            //	delete [] data;

            if (fp)
                fclose(fp);

            if (pixelFormat==0)
                return ReadResult::FILE_NOT_HANDLED;

            osg::Image* pOsgImage = new osg::Image();

            pOsgImage->setFileName(fileName.c_str());
            pOsgImage->setImage(width, height, 1,
                internalFormat,
                pixelFormat,
                dataType,
                data,
                osg::Image::USE_NEW_DELETE);

            return pOsgImage;
        }
};

// now register with Registry to instantiate the above
// reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterPNG> g_readerWriter_PNG_Proxy;
<|endoftext|>


<commit_before>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_ENUM_REFLECTOR(osg::BarrierOperation::PreBlockOp)
	I_EnumLabel(osg::BarrierOperation::NO_OPERATION);
	I_EnumLabel(osg::BarrierOperation::GL_FLUSH);
	I_EnumLabel(osg::BarrierOperation::GL_FINISH);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::BarrierOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_ConstructorWithDefaults2(IN, int, numThreads, , IN, osg::BarrierOperation::PreBlockOp, op, osg::BarrierOperation::NO_OPERATION);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::Block)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor0();
	I_Method0(void, block);
	I_Method0(void, release);
	I_Method0(void, reset);
	I_Method1(void, set, IN, bool, doRelease);
	I_WriteOnlyProperty(bool, );
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread)
	I_BaseType(osg::Referenced);
	I_Constructor0();
	I_MethodWithDefaults2(void, add, IN, osg::GraphicsThread::Operation *, operation, , IN, bool, waitForCompletion, false);
	I_Method0(void, run);
	I_Method0(int, cancel);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread::Operation)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor2(IN, const std::string &, name, IN, bool, keep);
	I_Method1(void, setName, IN, const std::string &, name);
	I_Method0(const std::string &, getName);
	I_Method1(void, setKeep, IN, bool, keep);
	I_Method0(bool, getKeep);
	I_Property(bool, Keep);
	I_Property(const std::string &, Name);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::ReleaseContext_Block_MakeCurrentOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_BaseType(osg::Block);
	I_Constructor0();
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::SwapBuffersOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_Constructor0();
END_REFLECTOR

<commit_msg>Updated wrappers<commit_after>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/GraphicsContext>
#include <osg/GraphicsThread>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

BEGIN_ENUM_REFLECTOR(osg::BarrierOperation::PreBlockOp)
	I_EnumLabel(osg::BarrierOperation::NO_OPERATION);
	I_EnumLabel(osg::BarrierOperation::GL_FLUSH);
	I_EnumLabel(osg::BarrierOperation::GL_FINISH);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::BarrierOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_ConstructorWithDefaults2(IN, int, numThreads, , IN, osg::BarrierOperation::PreBlockOp, op, osg::BarrierOperation::NO_OPERATION);
	I_Method0(void, release);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::Block)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor0();
	I_Method0(void, block);
	I_Method0(void, release);
	I_Method0(void, reset);
	I_Method1(void, set, IN, bool, doRelease);
	I_WriteOnlyProperty(bool, );
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread)
	I_BaseType(osg::Referenced);
	I_Constructor0();
	I_MethodWithDefaults2(void, add, IN, osg::GraphicsThread::Operation *, operation, , IN, bool, waitForCompletion, false);
	I_Method1(void, remove, IN, osg::GraphicsThread::Operation *, operation);
	I_Method1(void, remove, IN, const std::string &, name);
	I_Method0(void, removeAllOperations);
	I_Method0(osg::ref_ptr< osg::GraphicsThread::Operation >, getCurrentOperation);
	I_Method0(void, run);
	I_Method1(void, setDone, IN, bool, done);
	I_Method0(bool, getDone);
	I_Method0(int, cancel);
	I_ReadOnlyProperty(osg::ref_ptr< osg::GraphicsThread::Operation >, CurrentOperation);
	I_Property(bool, Done);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::GraphicsThread::Operation)
	I_VirtualBaseType(osg::Referenced);
	I_Constructor2(IN, const std::string &, name, IN, bool, keep);
	I_Method1(void, setName, IN, const std::string &, name);
	I_Method0(const std::string &, getName);
	I_Method1(void, setKeep, IN, bool, keep);
	I_Method0(bool, getKeep);
	I_Method0(void, release);
	I_Property(bool, Keep);
	I_Property(const std::string &, Name);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::ReleaseContext_Block_MakeCurrentOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_BaseType(osg::Block);
	I_Constructor0();
	I_Method0(void, release);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::SwapBuffersOperation)
	I_BaseType(osg::GraphicsThread::Operation);
	I_Constructor0();
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::ref_ptr< osg::GraphicsThread::Operation >)
	I_Constructor0();
	I_Constructor1(IN, osg::GraphicsThread::Operation *, t);
	I_Constructor1(IN, const osg::ref_ptr< osg::GraphicsThread::Operation > &, rp);
	I_Method0(bool, valid);
	I_Method0(osg::GraphicsThread::Operation *, get);
	I_Method0(const osg::GraphicsThread::Operation *, get);
	I_Method0(osg::GraphicsThread::Operation *, take);
	I_Method0(osg::GraphicsThread::Operation *, release);
	I_ReadOnlyProperty(osg::GraphicsThread::Operation *, );
END_REFLECTOR

<|endoftext|>