<commit_before>/*
 * This file is part of the µOS++ distribution.
 *   (https://github.com/micro-os-plus)
 * Copyright (c) 2015 Liviu Ionescu.
 *
 * µOS++ 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, version 3.
 *
 * µOS++ 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 program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "posix-drivers/CmsisUsartCharDevice.h"

#include "Driver_USART.h"

#include <cerrno>

// ----------------------------------------------------------------------------

namespace os
{
  namespace posix
  {
    // ------------------------------------------------------------------------

    CmsisUsartCharDevice::CmsisUsartCharDevice (
        const char* deviceName, ARM_DRIVER_USART* driver,
        ARM_USART_SignalEvent_t eventCallBack) :
        CharDevice (deviceName)
    {
      fDriver = driver;
      fEventCallBack = eventCallBack;

      fRxSem = nullptr;
      fTxSem = nullptr;
    }

    CmsisUsartCharDevice::~CmsisUsartCharDevice ()
    {
      ;
    }

    // ------------------------------------------------------------------------

#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

    int
    CmsisUsartCharDevice::do_vopen (const char* path, int oflag, va_list args)
    {
      if (fRxSem != nullptr)
        {
          errno = EEXIST; // Already opened
          return -1;
        }

      int32_t result;

      do
        {
          fRxSem = osSemaphoreCreate (osSemaphore(fRxSem), 1);
          fTxSem = osSemaphoreCreate (osSemaphore(fTxSem), 1);

          if (fRxSem == NULL || fTxSem == NULL)
            {
              result = ARM_DRIVER_ERROR;
              break;
            }

          osSemaphoreWait (fRxSem, 1);
          osSemaphoreWait (fTxSem, 1);

          if ((result = fDriver->Initialize (fEventCallBack)))
            break;

          if ((result = fDriver->PowerControl (ARM_POWER_FULL)))
            break;

          /* default configuration: 8 bits, no parity, 1 stop bit, no flow control, 115200 bps */
          if ((result = fDriver->Control (ARM_USART_MODE_ASYNCHRONOUS |
          ARM_USART_DATA_BITS_8 |
          ARM_USART_PARITY_NONE |
          ARM_USART_STOP_BITS_1 |
          ARM_USART_FLOW_CONTROL_NONE,
                                          115200)))
            break;

          /* enable TX output */
          if ((result = fDriver->Control (ARM_USART_CONTROL_TX, 1)))
            break;

          /* enable RX input */
          if ((result = fDriver->Control (ARM_USART_CONTROL_RX, 1)))
            break;

        }
      while (0);

      if (result != ARM_DRIVER_OK)
        {
          errno = ENOSR;
          return -1;
        }
      return 0;
    }

    int
    CmsisUsartCharDevice::do_close (void)
    {
      int32_t result;

      if (fRxSem == nullptr)
        {
          errno = EBADF; // Not opened.
          return -1;
        }

      osSemaphoreDelete (fRxSem);
      fRxSem = nullptr;

      osSemaphoreDelete (fTxSem);
      fTxSem = nullptr;

      do
        {
          /* disable TX output */
          if ((result = fDriver->Control (ARM_USART_CONTROL_TX, 0)))
            break;

          /* disable RX input */
          if ((result = fDriver->Control (ARM_USART_CONTROL_RX, 0)))
            break;

          if ((result = fDriver->PowerControl (ARM_POWER_OFF)))
            break;

          result = fDriver->Uninitialize ();
        }
      while (0);

      if (result != ARM_DRIVER_OK)
        {
          errno = EBUSY;
          return -1;
        }
      return 0;
    }

    ssize_t
    CmsisUsartCharDevice::do_read (void* buf, std::size_t nbyte)
    {
      ARM_USART_STATUS status;
      ssize_t count = -1;

      if ((fDriver->Receive ((void *) buf, nbyte)) == ARM_DRIVER_OK)
        {
          osSemaphoreWait (fRxSem, osWaitForever);
          status = fDriver->GetStatus ();
          if (!status.rx_framing_error)
            count = fDriver->GetRxCount ();
        }
      fDriver->Control (ARM_USART_ABORT_RECEIVE, 1);

      if (count == -1)
        {
          errno = EIO;
        }
      return count;
    }

    ssize_t
    CmsisUsartCharDevice::do_write (const void* buf, std::size_t nbyte)
    {
      ARM_USART_STATUS status;
      ssize_t count;

      status = fDriver->GetStatus ();
      if (status.tx_busy)
        osSemaphoreWait (fTxSem, osWaitForever);

      if ((count = fDriver->Send ((void *) buf, nbyte)) != ARM_DRIVER_OK)
        {
          count = -1;
          errno = EIO;
        }
      return count;
    }

    ssize_t
    CmsisUsartCharDevice::do_writev (const struct iovec* iov, int iovcnt)
    {
      errno = ENOSYS; // Not implemented
      return -1;
    }

    int
    CmsisUsartCharDevice::do_vioctl (int request, std::va_list args)
    {
      errno = ENOSYS; // Not implemented
      return -1;
    }

#if 0
    int
    CmsisUsartCharDevice::do_vfcntl (int cmd, std::va_list args)
      {
        errno = ENOSYS; // Not implemented
        return -1;
      }
#endif

    void
    CmsisUsartCharDevice::eventCallBack (uint32_t event)
    {
      if (event
          & (ARM_USART_EVENT_RX_TIMEOUT | ARM_USART_EVENT_RECEIVE_COMPLETE
              | ARM_USART_EVENT_RX_FRAMING_ERROR))
        osSemaphoreRelease (fRxSem);
      else if (event & ARM_USART_EVENT_TRANSFER_COMPLETE)
        osSemaphoreRelease (fTxSem);
    }

#pragma GCC diagnostic pop

  } /* namespace posix */
} /* namespace os */
<commit_msg>close() doesn't check for results anymore; read(): solved the case when more than one event per received block is issued by the cmsis driver.<commit_after>/*
 * This file is part of the µOS++ distribution.
 *   (https://github.com/micro-os-plus)
 * Copyright (c) 2015 Liviu Ionescu.
 *
 * µOS++ 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, version 3.
 *
 * µOS++ 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 program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "posix-drivers/CmsisUsartCharDevice.h"

#include "Driver_USART.h"

#include <cerrno>

// ----------------------------------------------------------------------------

namespace os
{
  namespace posix
  {
    // ------------------------------------------------------------------------

    CmsisUsartCharDevice::CmsisUsartCharDevice (
        const char* deviceName, ARM_DRIVER_USART* driver,
        ARM_USART_SignalEvent_t eventCallBack) :
        CharDevice (deviceName)
    {
      fDriver = driver;
      fEventCallBack = eventCallBack;

      fRxSem = nullptr;
      fTxSem = nullptr;
    }

    CmsisUsartCharDevice::~CmsisUsartCharDevice ()
    {
      ;
    }

    // ------------------------------------------------------------------------

#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

    int
    CmsisUsartCharDevice::do_vopen (const char* path, int oflag, va_list args)
    {
      if (fRxSem != nullptr)
        {
          errno = EEXIST; // Already opened
          return -1;
        }

      int32_t result;

      do
        {
          fRxSem = osSemaphoreCreate (osSemaphore(fRxSem), 1);
          fTxSem = osSemaphoreCreate (osSemaphore(fTxSem), 1);

          if (fRxSem == NULL || fTxSem == NULL)
            {
              result = ARM_DRIVER_ERROR;
              break;
            }

          osSemaphoreWait (fRxSem, 1);
          osSemaphoreWait (fTxSem, 1);

          if ((result = fDriver->Initialize (fEventCallBack)))
            break;

          if ((result = fDriver->PowerControl (ARM_POWER_FULL)))
            break;

          // default configuration: 8 bits, no parity, 1 stop bit,
          // no flow control, 115200 bps
          if ((result = fDriver->Control (ARM_USART_MODE_ASYNCHRONOUS |
          ARM_USART_DATA_BITS_8 |
          ARM_USART_PARITY_NONE |
          ARM_USART_STOP_BITS_1 |
          ARM_USART_FLOW_CONTROL_NONE,
                                          115200)))
            break;

          /* enable TX output */
          if ((result = fDriver->Control (ARM_USART_CONTROL_TX, 1)))
            break;

          /* enable RX input */
          if ((result = fDriver->Control (ARM_USART_CONTROL_RX, 1)))
            break;

        }
      while (0);

      if (result != ARM_DRIVER_OK)
        {
          errno = ENOSR;
          return -1;
        }
      return 0;
    }

    int
    CmsisUsartCharDevice::do_close (void)
    {
      if (fRxSem == nullptr)
        {
          errno = EBADF; // Not opened.
          return -1;
        }

      osSemaphoreDelete (fRxSem);
      fRxSem = nullptr;

      osSemaphoreDelete (fTxSem);
      fTxSem = nullptr;

      /* disable USART and I/O pins used */
      fDriver->Control (ARM_USART_CONTROL_TX, 0);
      fDriver->Control (ARM_USART_CONTROL_RX, 0);
      fDriver->PowerControl (ARM_POWER_OFF);
      fDriver->Uninitialize ();

      return 0;
    }

    ssize_t
    CmsisUsartCharDevice::do_read (void* buf, std::size_t nbyte)
    {
      ARM_USART_STATUS status;
      ssize_t count = -1;

      if ((fDriver->Receive ((void *) buf, nbyte)) == ARM_DRIVER_OK)
        {
          osSemaphoreWait (fRxSem, osWaitForever);
          status = fDriver->GetStatus ();
          if (!status.rx_framing_error)
            count = fDriver->GetRxCount ();
        }
      fDriver->Control (ARM_USART_ABORT_RECEIVE, 1);

      if (count == -1)
        {
          errno = EIO;
        }
      return count;
    }

    ssize_t
    CmsisUsartCharDevice::do_write (const void* buf, std::size_t nbyte)
    {
      ARM_USART_STATUS status;
      ssize_t count;

      status = fDriver->GetStatus ();
      if (status.tx_busy)
        osSemaphoreWait (fTxSem, osWaitForever);

      if ((fDriver->Send ((void *) buf, nbyte)) == ARM_DRIVER_OK)
        {
          osSemaphoreWait (fTxSem, osWaitForever);
          count = fDriver->GetTxCount ();
        }
      else
        {
          count = -1;
          errno = EIO;
        }
      return count;
    }

    ssize_t
    CmsisUsartCharDevice::do_writev (const struct iovec* iov, int iovcnt)
    {
      errno = ENOSYS; // Not implemented
      return -1;
    }

    int
    CmsisUsartCharDevice::do_vioctl (int request, std::va_list args)
    {
      errno = ENOSYS; // Not implemented
      return -1;
    }

#if 0
    int
    CmsisUsartCharDevice::do_vfcntl (int cmd, std::va_list args)
      {
        errno = ENOSYS; // Not implemented
        return -1;
      }
#endif

    void
    CmsisUsartCharDevice::eventCallBack (uint32_t event)
    {
      if ((event
          & (ARM_USART_EVENT_RECEIVE_COMPLETE | ARM_USART_EVENT_RX_FRAMING_ERROR))
          || ((event & ARM_USART_EVENT_RX_TIMEOUT) && fDriver->GetRxCount ()))
        osSemaphoreRelease (fRxSem);
      else if (event & ARM_USART_EVENT_TX_COMPLETE)
        osSemaphoreRelease (fTxSem);
    }

#pragma GCC diagnostic pop

  } /* namespace posix */
} /* namespace os */
<|endoftext|>


<commit_before>/**
 * @author Patryk Grudniewski <patgrudniewski@gmail.com>
 */
#include <vector>

#include "App.h"

using namespace Domino;
using namespace Domino::Exception;
using namespace std;
using namespace TCLAP;

const string App::VERSION = "0.0.1";

App::App()
{
    this->cli = new CmdLine("App for checking possible domino's tile sets for given domino's field size", ' ', App::VERSION);

    this->buildCliArgs();
}

App::~App()
{
    free(this->cli_args);
}

/**
 * @param int argc
 * @param char** argv
 * @return void
 */
void App::run(int argv, char** argc)
{
    try {
        int width, height;
        SetComposer *composer;
        vector<int> *hashes;

        this->cli->parse(argv, argc);

        width = ((UnlabeledValueArg<int>*) this->cli_args[0])->getValue();
        height = ((UnlabeledValueArg<int>*) this->cli_args[1])->getValue();

        composer = new SetComposer(new Board(width, height));
        hashes = composer->getAllPossibleCompositionHashes();
    } catch (ArgException &e) {
        cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
    } catch (InvalidBoardSizeException &e) {
        cerr << "Error: " << e.what() << endl;
    }
}

/**
 * @return void
 */
void App::buildCliArgs()
{
    int arg_count = 2;

    this->cli_args = (Arg**) malloc(arg_count * sizeof(Arg*));

    this->cli_args[0] = new UnlabeledValueArg<int>(
            "width",
            "Domino field's size",
            true,
            2,
            "width"
            );

    this->cli_args[1] = new UnlabeledValueArg<int>(
            "height",
            "Domino field's size",
            true,
            2,
            "height"
            );

    for (int i = 0; i < arg_count; i++) {
        this->cli->add(this->cli_args[i]);
    }
}
<commit_msg>todos<commit_after>/**
 * @author Patryk Grudniewski <patgrudniewski@gmail.com>
 */
#include <vector>

#include "App.h"

using namespace Domino;
using namespace Domino::Exception;
using namespace std;
using namespace TCLAP;

const string App::VERSION = "0.0.1";

App::App()
{
    this->cli = new CmdLine("App for checking possible domino's tile sets for given domino's field size", ' ', App::VERSION);

    this->buildCliArgs();
}

App::~App()
{
    free(this->cli_args);
}

/**
 * @param int argc
 * @param char** argv
 * @return void
 */
void App::run(int argv, char** argc)
{
    try {
        int width, height;
        SetComposer *composer;
        vector<int> *hashes;

        this->cli->parse(argv, argc);

        width = ((UnlabeledValueArg<int>*) this->cli_args[0])->getValue();
        height = ((UnlabeledValueArg<int>*) this->cli_args[1])->getValue();

        composer = new SetComposer(new Board(width, height));
        hashes = composer->getAllPossibleCompositionHashes();

        // @TODO: count hashes
        // @TODO: print number of correct hashes
    } catch (ArgException &e) {
        cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
    } catch (InvalidBoardSizeException &e) {
        cerr << "Error: " << e.what() << endl;
    }
}

/**
 * @return void
 */
void App::buildCliArgs()
{
    int arg_count = 2;

    this->cli_args = (Arg**) malloc(arg_count * sizeof(Arg*));

    this->cli_args[0] = new UnlabeledValueArg<int>(
            "width",
            "Domino field's size",
            true,
            2,
            "width"
            );

    this->cli_args[1] = new UnlabeledValueArg<int>(
            "height",
            "Domino field's size",
            true,
            2,
            "height"
            );

    for (int i = 0; i < arg_count; i++) {
        this->cli->add(this->cli_args[i]);
    }
}
<|endoftext|>


<commit_before>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>
#include <MusicBar.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
    #include <SDL.h>
    #include <SDL_thread.h>
    #include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
    #ifndef RUNNINGONINTEL
    #define RUNNINGONINTEL
    #endif
#else
    #ifndef RUNNINGONPI
    #define RUNNINGONPI
    #endif
    #include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

//attempting double buffer
IplImage threadImage1;
IplImage threadImage2;
IplImage threadImage3;
bool updatedImage = false;
int bufferNumber = 1;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
SDL_Rect musicBarRect;
int cameraHeight;
int cameraWidth;
int noSongs;

SDL_Thread* SDLCameraThread;

int quit;

SongPlayer musicPlayer;
MusicBar gordonMusic(&musicPlayer);
/***********************************************************************
/*                          SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
    bool success = true;

    if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_FULLSCREEN);
        if (window == NULL)
        {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else
        {
            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            if (renderer == NULL)
            {
                printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
                success = false;
            }
            else
            {
                SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
            }
        }
    }
    return success;
}

bool init_CameraSettings()
{
    int w, h;
    bool success = true;
    SDL_GetWindowSize(window, &w, &h);
    videoRect.x = 0;
    videoRect.y = 0;
    videoRect.w = w;
    videoRect.h = h-50; //change 50 to whatever height we want for the PI cam

    musicBarRect.x = 0;
    musicBarRect.y = h-49;
    musicBarRect.w = w;
    musicBarRect.h = 49;
    cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    printf("Camera Width %d, Camera Height %d \n",cameraWidth,cameraHeight);
    return success;
}

int cameraWorker(void* data)
{
    while (!quit)
    {
        cap >> frame;
        if(bufferNumber == 1)
        {
            threadImage2 = frame;
            bufferNumber = 2;
        }
        else if (bufferNumber == 2)
        {
            threadImage3 = frame;
            bufferNumber = 3;
        }
        else
        {
            threadImage1 = frame;
            bufferNumber = 1;
        }
        updatedImage = true;
    }
    return 0;
}

// Shows an individual frame of the supplied video
int show_Camera()
{
    if(updatedImage == true)
    {
        IplImage* img = NULL;
        updatedImage = false;
        if(bufferNumber == 1)
        {
            img = &threadImage1;
        }
        else if (bufferNumber == 2)
        {
            img = &threadImage2;
        }
        else
        {
            img = &threadImage3;
        }
        SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
            img->width,
            img->height,
            img->depth * img->nChannels,
            img->widthStep,
            0xff0000, 0x00ff00, 0x0000ff, 0
            );
        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
        surface = NULL;
        SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
        SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
        SDL_DestroyTexture(texture);
        return 1;
    }
    return 0;
}

void processEvents()
{
    SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    printf("SDL_QUIT was called\n");
                    signalToQuit();
                    close();
                    break;

                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:
                            printf("Esc was Pressed!\n");
                            signalToQuit();
                            close();
                            break;
                        case SDLK_LEFT:
                            printf("Left arrow was Pressed!\n");
                            musicPlayer.previousSong();
                            break;
                        case SDLK_RIGHT:
                            printf("Right arrow was Pressed!\n");
                            musicPlayer.nextSong();
                            break;
                        case SDLK_UP:
                            musicPlayer.changeVolume(0.1);
                            break;
                        case SDLK_DOWN:
                            musicPlayer.changeVolume(-0.1);
                            break;
                        case SDLK_SPACE:
                            printf("Space was pressed!\n");
                            musicPlayer.playPause();
                    }
            }
        }
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
    quit = true;
    musicPlayer.songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
    musicPlayer.closeSongPlayer();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    SDL_Quit();
    exit(0);
}

int main(int argc, char* argv[])
{
    if (!init_SDL())
    {
        fprintf(stderr, "Could not initialize SDL!\n");
        return -1;
    }
    if (!cap.isOpened())
    {
        fprintf(stderr, "Failed to load file!\n");
        return -1;
    }
    if (!init_CameraSettings())
    {
        printf("Failed to load settings!\n");

        return -1;
    }

    if (musicPlayer.initSongPlayer())
    {
        fprintf(stderr, "No SongLibrary Folder! Not creating Music Thread!\n");
    }
    else
    {
        musicPlayer.StartInternalThread();
    }

    //initSongPlayer();
    //noSongs = loadSong((char *)currentSong().c_str());

    SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
    //if (!noSongs)
        //SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

    int screenUpdate = 0;

    while (!quit)
    {
        screenUpdate = show_Camera();
        processEvents();
        if (screenUpdate == 1)
        {
            SDL_Surface* surfaceBar;
            gordonMusic.update();
            surfaceBar = gordonMusic.returnMusicBar();
            SDL_RendererFlip flip = SDL_FLIP_NONE;
            SDL_Texture* textureMusicBar = SDL_CreateTextureFromSurface(renderer, surfaceBar);
            SDL_RenderCopyEx(renderer, textureMusicBar, NULL, &musicBarRect ,0, NULL, flip);
            SDL_DestroyTexture(textureMusicBar);
            SDL_RenderPresent(renderer);
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
            SDL_RenderClear(renderer);
        }
    }

    musicPlayer.WaitForInternalThreadToExit();
    SDL_WaitThread(SDLCameraThread, NULL);
    return 0;
}
<commit_msg>Does not full screen anymore<commit_after>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include <SongLoader.h>
#include <SongPlayer.h>
#include <MusicBar.h>

//for the rasperry pi
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

extern "C" {
    #include <SDL.h>
    #include <SDL_thread.h>
    #include <SDL_ttf.h>
}

#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifdef __amd64__
    #ifndef RUNNINGONINTEL
    #define RUNNINGONINTEL
    #endif
#else
    #ifndef RUNNINGONPI
    #define RUNNINGONPI
    #endif
    #include <wiringPi.h>
#endif

using namespace cv;

#define SCREEN_HEIGHT 768
#define SCREEN_WIDTH 1232

int cameraWorker(void* data);
void processEvents();
void signalToQuit();
void close();

//attempting double buffer
IplImage threadImage1;
IplImage threadImage2;
IplImage threadImage3;
bool updatedImage = false;
int bufferNumber = 1;

VideoCapture cap(0);

Mat frame;
SDL_Renderer* renderer = NULL;
SDL_Window* window = NULL;

SDL_Rect videoRect;
SDL_Rect musicBarRect;
int cameraHeight;
int cameraWidth;
int noSongs;

SDL_Thread* SDLCameraThread;

int quit;

SongPlayer musicPlayer;
MusicBar gordonMusic(&musicPlayer);
/***********************************************************************
/*                          SDL functions
/***********************************************************************/
// Initializes SDL window / renderer for use

bool init_SDL()
{
    bool success = true;

    if (SDL_Init(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        window = SDL_CreateWindow("Video Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
        if (window == NULL)
        {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else
        {
            renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
            if (renderer == NULL)
            {
                printf("Renderer could not be created. SDL_Error: %s \n", SDL_GetError());
                success = false;
            }
            else
            {
                SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
            }
        }
    }
    return success;
}

bool init_CameraSettings()
{
    int w, h;
    bool success = true;
    SDL_GetWindowSize(window, &w, &h);
    videoRect.x = 0;
    videoRect.y = 0;
    videoRect.w = w;
    videoRect.h = h-50; //change 50 to whatever height we want for the PI cam

    musicBarRect.x = 0;
    musicBarRect.y = h-49;
    musicBarRect.w = w;
    musicBarRect.h = 49;
    cameraWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    cameraHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    printf("Camera Width %d, Camera Height %d \n",cameraWidth,cameraHeight);
    return success;
}

int cameraWorker(void* data)
{
    while (!quit)
    {
        cap >> frame;
        if(bufferNumber == 1)
        {
            threadImage2 = frame;
            bufferNumber = 2;
        }
        else if (bufferNumber == 2)
        {
            threadImage3 = frame;
            bufferNumber = 3;
        }
        else
        {
            threadImage1 = frame;
            bufferNumber = 1;
        }
        updatedImage = true;
    }
    return 0;
}

// Shows an individual frame of the supplied video
int show_Camera()
{
    if(updatedImage == true)
    {
        IplImage* img = NULL;
        updatedImage = false;
        if(bufferNumber == 1)
        {
            img = &threadImage1;
        }
        else if (bufferNumber == 2)
        {
            img = &threadImage2;
        }
        else
        {
            img = &threadImage3;
        }
        SDL_Surface* surface = SDL_CreateRGBSurfaceFrom((void*)img->imageData,
            img->width,
            img->height,
            img->depth * img->nChannels,
            img->widthStep,
            0xff0000, 0x00ff00, 0x0000ff, 0
            );
        SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
        SDL_FreeSurface(surface);
        surface = NULL;
        SDL_RendererFlip flip = SDL_FLIP_HORIZONTAL;
        SDL_RenderCopyEx(renderer, texture, NULL, &videoRect ,0, NULL, flip);
        SDL_DestroyTexture(texture);
        return 1;
    }
    return 0;
}

void processEvents()
{
    SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                    printf("SDL_QUIT was called\n");
                    signalToQuit();
                    close();
                    break;

                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE:
                            printf("Esc was Pressed!\n");
                            signalToQuit();
                            close();
                            break;
                        case SDLK_LEFT:
                            printf("Left arrow was Pressed!\n");
                            musicPlayer.previousSong();
                            break;
                        case SDLK_RIGHT:
                            printf("Right arrow was Pressed!\n");
                            musicPlayer.nextSong();
                            break;
                        case SDLK_UP:
                            musicPlayer.changeVolume(0.1);
                            break;
                        case SDLK_DOWN:
                            musicPlayer.changeVolume(-0.1);
                            break;
                        case SDLK_SPACE:
                            printf("Space was pressed!\n");
                            musicPlayer.playPause();
                    }
            }
        }
}

/* Signals all the threads to quit and then waits for the threads */
void signalToQuit()
{
    quit = true;
    musicPlayer.songQuit();
}

/* Cleans up and should free everything used in the program*/
void close()
{
    musicPlayer.closeSongPlayer();
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    SDL_Quit();
    exit(0);
}

int main(int argc, char* argv[])
{
    if (!init_SDL())
    {
        fprintf(stderr, "Could not initialize SDL!\n");
        return -1;
    }
    if (!cap.isOpened())
    {
        fprintf(stderr, "Failed to load file!\n");
        return -1;
    }
    if (!init_CameraSettings())
    {
        printf("Failed to load settings!\n");

        return -1;
    }

    if (musicPlayer.initSongPlayer())
    {
        fprintf(stderr, "No SongLibrary Folder! Not creating Music Thread!\n");
    }
    else
    {
        musicPlayer.StartInternalThread();
    }

    //initSongPlayer();
    //noSongs = loadSong((char *)currentSong().c_str());

    SDLCameraThread = SDL_CreateThread(cameraWorker, "Backup Camera Thread", NULL);
    //if (!noSongs)
        //SDLMusicThread = SDL_CreateThread(songThread, "Music Playing Thread", NULL);

    int screenUpdate = 0;

    while (!quit)
    {
        screenUpdate = show_Camera();
        processEvents();
        if (screenUpdate == 1)
        {
            SDL_Surface* surfaceBar;
            gordonMusic.update();
            surfaceBar = gordonMusic.returnMusicBar();
            SDL_RendererFlip flip = SDL_FLIP_NONE;
            SDL_Texture* textureMusicBar = SDL_CreateTextureFromSurface(renderer, surfaceBar);
            SDL_RenderCopyEx(renderer, textureMusicBar, NULL, &musicBarRect ,0, NULL, flip);
            SDL_DestroyTexture(textureMusicBar);
            SDL_RenderPresent(renderer);
            SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
            SDL_RenderClear(renderer);
        }
    }

    musicPlayer.WaitForInternalThreadToExit();
    SDL_WaitThread(SDLCameraThread, NULL);
    return 0;
}
<|endoftext|>


<commit_before>#include "photoeffects.hpp"

using namespace cv;

int tint(InputArray src, OutputArray dst,
        const Vec3b &colorTint, float density)
{
    CV_Assert(src.type() == CV_8UC3);
    CV_Assert(density >= 0.0f || density <= 1.0f);
    Mat image = src.getMat(), outputImage(image.size(), CV_8UC3);
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Vec3b colorDest = image.at<Vec3b>(i, j);
            colorDest = colorTint * density + (1 - density) * colorDest;
            outputImage.at<Vec3b>(i, j) = colorDest;
        }
    }
    outputImage.convertTo(dst, CV_8UC3);
    return 0;
}
<commit_msg>Correct the mistakes<commit_after>#include "photoeffects.hpp"

using namespace cv;

int tint(InputArray src, OutputArray dst,
        const Vec3b &colorTint, float density)
{
    CV_Assert(src.type() == CV_8UC3);
    CV_Assert(density >= 0.0f || density <= 1.0f);
    dst.create(src.size(), CV_8UC3);
    Mat image = src.getMat(), outputImage = dst.getMat();
    float negDen = 1 - density;
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Vec3b colorDest = image.at<Vec3b>(i, j);
            colorDest = colorTint * density + negDen * colorDest;
            outputImage.at<Vec3b>(i, j) = colorDest;
        }
    }
    outputImage.convertTo(dst, CV_8UC3);
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tile.h"

#include "util_algorithm.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
                         bool preserve_tile_device_, bool background_, int tile_order_, int num_devices_)
{
	progressive = progressive_;
	tile_size = tile_size_;
	tile_order = tile_order_;
	start_resolution = start_resolution_;
	num_devices = num_devices_;
	preserve_tile_device = preserve_tile_device_;
	background = background_;

	BufferParams buffer_params;
	reset(buffer_params, 0);
}

TileManager::~TileManager()
{
}

void TileManager::reset(BufferParams& params_, int num_samples_)
{
	params = params_;

	int divider = 1;
	int w = params.width, h = params.height;

	if(start_resolution != INT_MAX) {
		while(w*h > start_resolution*start_resolution) {
			w = max(1, w/2);
			h = max(1, h/2);

			divider *= 2;
		}
	}

	num_samples = num_samples_;

	state.buffer = BufferParams();
	state.sample = -1;
	state.num_tiles = 0;
	state.num_rendered_tiles = 0;
	state.num_samples = 0;
	state.resolution_divider = divider;
	state.tiles.clear();
}

void TileManager::set_samples(int num_samples_)
{
	num_samples = num_samples_;
}

/* splits image into tiles and assigns equal amount of tiles to every render device */
void TileManager::gen_tiles_global()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
	int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y;

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	int tiles_per_device = (tile_w * tile_h + num - 1) / num;
	int cur_device = 0, cur_tiles = 0;

	for(int tile_y = 0; tile_y < tile_h; tile_y++) {
		for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
			int x = tile_x * tile_size.x;
			int y = tile_y * tile_size.y;
			int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
			int h = (tile_y == tile_h-1)? image_h - y: tile_size.y;

			state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device));
			cur_tiles++;

			if(cur_tiles == tiles_per_device) {
				cur_tiles = 0;
				cur_device++;
			}
		}
	}
}

/* slices image into as much pieces as how many devices are rendering this image */
void TileManager::gen_tiles_sliced()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	for(int device = 0; device < num; device++) {
		int device_y = (image_h/num)*device;
		int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;

		int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
		int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;

		for(int tile_y = 0; tile_y < tile_h; tile_y++) {
			for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
				int x = tile_x * tile_size.x;
				int y = tile_y * tile_size.y;
				int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
				int h = (tile_y == tile_h-1)? device_h - y: tile_size.y;

				state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
			}
		}
	}
}

void TileManager::set_tiles()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	if(background)
		gen_tiles_global();
	else
		gen_tiles_sliced();

	state.num_tiles = state.tiles.size();

	state.buffer.width = image_w;
	state.buffer.height = image_h;

	state.buffer.full_x = params.full_x/resolution;
	state.buffer.full_y = params.full_y/resolution;
	state.buffer.full_width = max(1, params.full_width/resolution);
	state.buffer.full_height = max(1, params.full_height/resolution);
}

list<Tile>::iterator TileManager::next_viewport_tile(int device)
{
	list<Tile>::iterator iter;

	int logical_device = preserve_tile_device? device: 0;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false)
		return iter;
	}

	return state.tiles.end();
}

list<Tile>::iterator TileManager::next_background_tile(int device, int tile_order)
{
	list<Tile>::iterator iter, best = state.tiles.end();

	int resolution = state.resolution_divider;
	int logical_device = preserve_tile_device? device: 0;

	int64_t cordx = max(1, params.width/resolution);
	int64_t cordy = max(1, params.height/resolution);
	int64_t mindist = cordx * cordy;

	int64_t centx = cordx / 2, centy = cordy / 2;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false) {
			Tile &cur_tile = *iter;

			int64_t distx = cordx;
			int64_t disty = cordy;

			switch (tile_order) {
				case TileManager::CENTER:
					distx = centx - (cur_tile.x + cur_tile.w);
					disty = centy - (cur_tile.y + cur_tile.h);
					distx = (int64_t) sqrt((double)distx * distx + disty * disty);
					break;
				case TileManager::RIGHT_TO_LEFT:
					distx = cordx - cur_tile.x;
					break;
				case TileManager::LEFT_TO_RIGHT:
					distx = cordx + cur_tile.x;
					break;
				case TileManager::TOP_TO_BOTTOM:
					distx = cordx - cur_tile.y;
					break;
				case TileManager::BOTTOM_TO_TOP:
					distx = cordx + cur_tile.y;
					break;
				default:
					break;
			}

			if(distx < mindist) {
				best = iter;
				mindist = distx;
			}
		}
	}

	return best;
}

bool TileManager::next_tile(Tile& tile, int device)
{
	list<Tile>::iterator tile_it;

	if (background)
		tile_it = next_background_tile(device, tile_order);
	else
		tile_it = next_viewport_tile(device);

	if(tile_it != state.tiles.end()) {
		tile_it->rendering = true;
		tile = *tile_it;
		state.num_rendered_tiles++;

		return true;
	}

	return false;
}

bool TileManager::done()
{
	return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
}

bool TileManager::next()
{
	if(done())
		return false;

	if(progressive && state.resolution_divider > 1) {
		state.sample = 0;
		state.resolution_divider /= 2;
		state.num_samples = 1;
		set_tiles();
	}
	else {
		state.sample++;

		if(progressive)
			state.num_samples = 1;
		else
			state.num_samples = num_samples;

		state.resolution_divider = 1;
		set_tiles();
	}

	return true;
}

CCL_NAMESPACE_END

<commit_msg>Fix cycles not rendering with 1x1 resolution anymore, not so common for users but nice for debugging.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tile.h"

#include "util_algorithm.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
                         bool preserve_tile_device_, bool background_, int tile_order_, int num_devices_)
{
	progressive = progressive_;
	tile_size = tile_size_;
	tile_order = tile_order_;
	start_resolution = start_resolution_;
	num_devices = num_devices_;
	preserve_tile_device = preserve_tile_device_;
	background = background_;

	BufferParams buffer_params;
	reset(buffer_params, 0);
}

TileManager::~TileManager()
{
}

void TileManager::reset(BufferParams& params_, int num_samples_)
{
	params = params_;

	int divider = 1;
	int w = params.width, h = params.height;

	if(start_resolution != INT_MAX) {
		while(w*h > start_resolution*start_resolution) {
			w = max(1, w/2);
			h = max(1, h/2);

			divider *= 2;
		}
	}

	num_samples = num_samples_;

	state.buffer = BufferParams();
	state.sample = -1;
	state.num_tiles = 0;
	state.num_rendered_tiles = 0;
	state.num_samples = 0;
	state.resolution_divider = divider;
	state.tiles.clear();
}

void TileManager::set_samples(int num_samples_)
{
	num_samples = num_samples_;
}

/* splits image into tiles and assigns equal amount of tiles to every render device */
void TileManager::gen_tiles_global()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
	int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y;

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	int tiles_per_device = (tile_w * tile_h + num - 1) / num;
	int cur_device = 0, cur_tiles = 0;

	for(int tile_y = 0; tile_y < tile_h; tile_y++) {
		for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
			int x = tile_x * tile_size.x;
			int y = tile_y * tile_size.y;
			int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
			int h = (tile_y == tile_h-1)? image_h - y: tile_size.y;

			state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device));
			cur_tiles++;

			if(cur_tiles == tiles_per_device) {
				cur_tiles = 0;
				cur_device++;
			}
		}
	}
}

/* slices image into as much pieces as how many devices are rendering this image */
void TileManager::gen_tiles_sliced()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	state.tiles.clear();

	int num_logical_devices = preserve_tile_device? num_devices: 1;
	int num = min(image_h, num_logical_devices);
	int tile_index = 0;

	for(int device = 0; device < num; device++) {
		int device_y = (image_h/num)*device;
		int device_h = (device == num-1)? image_h - device*(image_h/num): image_h/num;

		int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x;
		int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y;

		for(int tile_y = 0; tile_y < tile_h; tile_y++) {
			for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
				int x = tile_x * tile_size.x;
				int y = tile_y * tile_size.y;
				int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
				int h = (tile_y == tile_h-1)? device_h - y: tile_size.y;

				state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
			}
		}
	}
}

void TileManager::set_tiles()
{
	int resolution = state.resolution_divider;
	int image_w = max(1, params.width/resolution);
	int image_h = max(1, params.height/resolution);

	if(background)
		gen_tiles_global();
	else
		gen_tiles_sliced();

	state.num_tiles = state.tiles.size();

	state.buffer.width = image_w;
	state.buffer.height = image_h;

	state.buffer.full_x = params.full_x/resolution;
	state.buffer.full_y = params.full_y/resolution;
	state.buffer.full_width = max(1, params.full_width/resolution);
	state.buffer.full_height = max(1, params.full_height/resolution);
}

list<Tile>::iterator TileManager::next_viewport_tile(int device)
{
	list<Tile>::iterator iter;

	int logical_device = preserve_tile_device? device: 0;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false)
		return iter;
	}

	return state.tiles.end();
}

list<Tile>::iterator TileManager::next_background_tile(int device, int tile_order)
{
	list<Tile>::iterator iter, best = state.tiles.end();

	int resolution = state.resolution_divider;
	int logical_device = preserve_tile_device? device: 0;

	int64_t cordx = max(1, params.width/resolution);
	int64_t cordy = max(1, params.height/resolution);
	int64_t mindist = INT_MAX;

	int64_t centx = cordx / 2, centy = cordy / 2;

	for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
		if(iter->device == logical_device && iter->rendering == false) {
			Tile &cur_tile = *iter;

			int64_t distx = cordx;
			int64_t disty = cordy;

			switch (tile_order) {
				case TileManager::CENTER:
					distx = centx - (cur_tile.x + cur_tile.w);
					disty = centy - (cur_tile.y + cur_tile.h);
					distx = (int64_t) sqrt((double)distx * distx + disty * disty);
					break;
				case TileManager::RIGHT_TO_LEFT:
					distx = cordx - cur_tile.x;
					break;
				case TileManager::LEFT_TO_RIGHT:
					distx = cordx + cur_tile.x;
					break;
				case TileManager::TOP_TO_BOTTOM:
					distx = cordx - cur_tile.y;
					break;
				case TileManager::BOTTOM_TO_TOP:
					distx = cordx + cur_tile.y;
					break;
				default:
					break;
			}

			if(distx < mindist) {
				best = iter;
				mindist = distx;
			}
		}
	}

	return best;
}

bool TileManager::next_tile(Tile& tile, int device)
{
	list<Tile>::iterator tile_it;

	if (background)
		tile_it = next_background_tile(device, tile_order);
	else
		tile_it = next_viewport_tile(device);

	if(tile_it != state.tiles.end()) {
		tile_it->rendering = true;
		tile = *tile_it;
		state.num_rendered_tiles++;

		return true;
	}

	return false;
}

bool TileManager::done()
{
	return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1);
}

bool TileManager::next()
{
	if(done())
		return false;

	if(progressive && state.resolution_divider > 1) {
		state.sample = 0;
		state.resolution_divider /= 2;
		state.num_samples = 1;
		set_tiles();
	}
	else {
		state.sample++;

		if(progressive)
			state.num_samples = 1;
		else
			state.num_samples = num_samples;

		state.resolution_divider = 1;
		set_tiles();
	}

	return true;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before><commit_msg>Planning: add more latency log and remove an unused variable<commit_after><|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Steven Bloemer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <mutex>
#include <thread>

#include "PetersonLock.h"
#include "EventBuffer.h"

static void yield()
{
    std::this_thread::yield();
}

static void dump_event_buffers(const EventBuffer event_buffer[2], Event::timestamp_t start_time);

template <bool fenced>
using LockType = PetersonLock<__typeof__(&yield), fenced>;

template <typename Lock>
void exercise_lock(unsigned loop_count)
{
    Lock lock(&yield);
    std::mutex require_mutex;
    std::thread thread[2];
    EventBuffer event_buffer[2];
    volatile int shared_value = 0;
    volatile bool start_running = false;
    volatile bool done_running[2] = {false,};
    const Event::timestamp_t start_time = mach_absolute_time();

#define REQUIRE(condition) do {                                                                     \
    if (!(condition)) {                                                                             \
        lock.release(tid);                                                                          \
        if (require_mutex.try_lock()) {                                                             \
            while (!done_running[!tid]) yield();                                                    \
            printf("Requirement \"" #condition "\" failed at line %u!\n", __LINE__);                \
            printf("shared_value: %u\n", shared_value);                                             \
            printf("Dumping event buffers:\n");                                                     \
            dump_event_buffers(event_buffer, start_time);                                           \
            require_mutex.unlock();                                                                 \
        }                                                                                \
        done_running[tid] = true;                                                                   \
        return;                                                                                \
    }                                                                                \
} while (0)

    for (unsigned tid = 0; tid < 2; ++tid) {
        thread[tid] = std::thread([&, tid]()
        {
            // Wait until the parent thread tells us to start
            while (!start_running) {
                yield();
            }

            EventBuffer &events = event_buffer[tid];

            for (unsigned i = 0; i < loop_count; ++i) {

                LOG(events, "Acquiring lock...");
                lock.acquire(bool(tid));
                LOG(events, "Acquiring lock...done");

                REQUIRE(++shared_value == 1);
                REQUIRE(--shared_value == 0);

                LOG(events, "Releasing lock");
                lock.release(bool(tid));
            }

            done_running[tid] = true;
        });
    }

    start_running = true;
#undef REQUIRE

    for (unsigned tid = 0; tid < 2; ++tid) {
        thread[tid].join();
    }

    printf("shared_value = %u\n", shared_value);
}

int main(int argc, const char * argv[])
{
    const unsigned loop_count = argc < 2 ? 10'000'000 : atoi(argv[1]);

    printf("Running with %u loops per thread\n", loop_count);

    printf("Exercising Peterson lock with fencing\n");
    exercise_lock<LockType<true>>(loop_count);

    printf("Exercising Peterson lock without fencing\n");
    exercise_lock<LockType<false>>(loop_count);

    return 0;
}

static void dump_event_buffers(const EventBuffer event_buffer[2], Event::timestamp_t start_time)
{
    const unsigned count = 2;

    // Go through the event buffers in parallel, always printing the entry with the latest timestamp
    EventBuffer::ConstReverseIterator itor[count];
    EventBuffer::ConstReverseIterator end[count];

    // Initialize our iterators
    for (unsigned i = 0; i < count; ++i) {
        itor[i] = event_buffer[i].rbegin();
        end[i]  = event_buffer[i].rend();
    }

    unsigned latest_itor = count;

    while (true)
    {
        Event::timestamp_t latest_timestamp = 0;

        // latest_itor remains set to count when all iterators are exhausted
        latest_itor = count;

        // Find the iterator containing the most recent timestamp
        for (unsigned i = 0; i < count; ++i)
        {
            if (itor[i] != end[i] &&
                *itor[i] &&
                itor[i]->timestamp >= latest_timestamp)
            {
                latest_itor = i;
                latest_timestamp = itor[i]->timestamp;
            }
        }

        if (latest_itor == count) {
            // All iterators are exhausted; we're done.
            break;
        }

        (itor[latest_itor]++)->print(latest_itor, start_time);
    }
}
<commit_msg>Use condition_variables to communicate conditions between threads.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Steven Bloemer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <mutex>
#include <thread>

#include "PetersonLock.h"
#include "EventBuffer.h"

static void yield()
{
    std::this_thread::yield();
}

static void dump_event_buffers(const EventBuffer event_buffer[2], Event::timestamp_t start_time);

template <bool fenced>
using LockType = PetersonLock<__typeof__(&yield), fenced>;

using std::mutex;
using unique_lock = std::unique_lock<std::mutex>;

template <typename Lock>
void exercise_lock(unsigned loop_count)
{
    Lock lock(&yield);
    mutex require_mutex;
    std::thread thread[2];
    EventBuffer event_buffer[2];
    volatile int shared_value = 0;
    volatile bool start_running = false;
    volatile bool done_running[2] = {false,};

    std::condition_variable start_running_cv,
                             done_running_cv;
    mutex start_running_mutex,
           done_running_mutex;

    const Event::timestamp_t start_time = mach_absolute_time();

#define REQUIRE(condition) do {                                                                     \
    if (!(condition)) {                                                                             \
        lock.release(tid);                                                                          \
        if (require_mutex.try_lock()) {                                                             \
            unique_lock done_running_lock(done_running_mutex);                                      \
            done_running_cv.wait(done_running_lock, [&done_running, tid]() { return done_running[!tid]; }); \
            done_running_lock.unlock();                                                             \
            printf("Requirement \"" #condition "\" failed at line %u!\n", __LINE__);                \
            printf("shared_value: %u\n", shared_value);                                             \
            printf("Dumping event buffers:\n");                                                     \
            dump_event_buffers(event_buffer, start_time);                                           \
            require_mutex.unlock();                                                                 \
        }                                                                                \
        done_running[tid] = true;                                                                   \
        done_running_cv.notify_all();                                                               \
        return;                                                                                \
    }                                                                                \
} while (0)

    for (unsigned tid = 0; tid < 2; ++tid) {
        thread[tid] = std::thread([&, tid]()
        {
            // Wait until the parent thread tells us to start
            {
                unique_lock startup_lock(start_running_mutex);
                start_running_cv.wait(startup_lock, [start_running]() { return start_running; });
            }

            EventBuffer &events = event_buffer[tid];

            for (unsigned i = 0; i < loop_count; ++i) {

                LOG(events, "Acquiring lock...");
                lock.acquire(bool(tid));
                LOG(events, "Acquiring lock...done");

                REQUIRE(++shared_value == 1);
                REQUIRE(--shared_value == 0);

                LOG(events, "Releasing lock");
                lock.release(bool(tid));
            }

            done_running[tid] = true;
            done_running_cv.notify_all();
        });
    }

    start_running = true;
    start_running_cv.notify_all();
#undef REQUIRE

    for (unsigned tid = 0; tid < 2; ++tid) {
        thread[tid].join();
    }

    printf("shared_value = %u\n", shared_value);
}

int main(int argc, const char * argv[])
{
    const unsigned loop_count = argc < 2 ? 10'000'000 : atoi(argv[1]);

    printf("Running with %u loops per thread\n", loop_count);

    printf("Exercising Peterson lock with fencing\n");
    exercise_lock<LockType<true>>(loop_count);

    printf("Exercising Peterson lock without fencing\n");
    exercise_lock<LockType<false>>(loop_count);

    return 0;
}

static void dump_event_buffers(const EventBuffer event_buffer[2], Event::timestamp_t start_time)
{
    const unsigned count = 2;

    // Go through the event buffers in parallel, always printing the entry with the latest timestamp
    EventBuffer::ConstReverseIterator itor[count];
    EventBuffer::ConstReverseIterator end[count];

    // Initialize our iterators
    for (unsigned i = 0; i < count; ++i) {
        itor[i] = event_buffer[i].rbegin();
        end[i]  = event_buffer[i].rend();
    }

    unsigned latest_itor = count;

    while (true)
    {
        Event::timestamp_t latest_timestamp = 0;

        // latest_itor remains set to count when all iterators are exhausted
        latest_itor = count;

        // Find the iterator containing the most recent timestamp
        for (unsigned i = 0; i < count; ++i)
        {
            if (itor[i] != end[i] &&
                *itor[i] &&
                itor[i]->timestamp >= latest_timestamp)
            {
                latest_itor = i;
                latest_timestamp = itor[i]->timestamp;
            }
        }

        if (latest_itor == count) {
            // All iterators are exhausted; we're done.
            break;
        }

        (itor[latest_itor]++)->print(latest_itor, start_time);
    }
}
<|endoftext|>


<commit_before>#ifndef SPARSEBENCH_BENCHMARKUTILS_HPP
#define SPARSEBENCH_BENCHMARKUTILS_HPP

#include <stdexcept>
#include <sstream>
#include <iostream>

namespace sparsebench {
namespace benchmarkutils {

void parseArgs(int argc, char** argv) {
  if (argc != 3) {
    std::stringstream ss;
    ss << "Usage " << argv[0] << " <matrix> <rhs>" <<std::endl;
    throw new std::invalid_argument(ss.str());
  }
}

void printSummary(
    double setupSeconds,
    int iterations,
    double solveSeconds
) {
  std::cout << "setup took       " << setupSeconds << std::endl;
  std::cout << "#iterations:     " << iterations << std::endl;
  std::cout << "Solve took       " << solveSeconds << std::endl;
}

}
}

#endif //SPARSEBENCH_BENCHMARKUTILS_HPP
<commit_msg>Fix exception throwing<commit_after>#ifndef SPARSEBENCH_BENCHMARKUTILS_HPP
#define SPARSEBENCH_BENCHMARKUTILS_HPP

#include <stdexcept>
#include <sstream>
#include <iostream>

namespace sparsebench {
namespace benchmarkutils {

void parseArgs(int argc, char** argv) {
  if (argc != 3) {
    std::stringstream ss;
    ss << "Usage " << argv[0] << " <matrix> <rhs>" <<std::endl;
    throw std::invalid_argument(ss.str());
  }
}

void printSummary(
    double setupSeconds,
    int iterations,
    double solveSeconds
) {
  std::cout << "setup took       " << setupSeconds << std::endl;
  std::cout << "#iterations:     " << iterations << std::endl;
  std::cout << "Solve took       " << solveSeconds << std::endl;
}

}
}

#endif //SPARSEBENCH_BENCHMARKUTILS_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2009 Colin Percival, 2011 ArtForz, 2012-2013 pooler
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file was originally written by Colin Percival as part of the Tarsnap
 * online backup system.
 */

#include "scrypt.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <openssl/sha.h>

#include <emmintrin.h>

static inline void xor_salsa8_sse2(__m128i B[4], const __m128i Bx[4])
{
	__m128i X0, X1, X2, X3;
	__m128i T;
	int i;

	X0 = B[0] = _mm_xor_si128(B[0], Bx[0]);
	X1 = B[1] = _mm_xor_si128(B[1], Bx[1]);
	X2 = B[2] = _mm_xor_si128(B[2], Bx[2]);
	X3 = B[3] = _mm_xor_si128(B[3], Bx[3]);

	for (i = 0; i < 8; i += 2) {
		/* Operate on "columns". */
		T = _mm_add_epi32(X0, X3);
		X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));
		X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));
		T = _mm_add_epi32(X1, X0);
		X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
		X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
		T = _mm_add_epi32(X2, X1);
		X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));
		X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));
		T = _mm_add_epi32(X3, X2);
		X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
		X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));

		/* Rearrange data. */
		X1 = _mm_shuffle_epi32(X1, 0x93);
		X2 = _mm_shuffle_epi32(X2, 0x4E);
		X3 = _mm_shuffle_epi32(X3, 0x39);

		/* Operate on "rows". */
		T = _mm_add_epi32(X0, X1);
		X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));
		X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));
		T = _mm_add_epi32(X3, X0);
		X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));
		X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));
		T = _mm_add_epi32(X2, X3);
		X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));
		X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));
		T = _mm_add_epi32(X1, X2);
		X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));
		X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));

		/* Rearrange data. */
		X1 = _mm_shuffle_epi32(X1, 0x39);
		X2 = _mm_shuffle_epi32(X2, 0x4E);
		X3 = _mm_shuffle_epi32(X3, 0x93);
	}

	B[0] = _mm_add_epi32(B[0], X0);
	B[1] = _mm_add_epi32(B[1], X1);
	B[2] = _mm_add_epi32(B[2], X2);
	B[3] = _mm_add_epi32(B[3], X3);
}

void scrypt_1024_1_1_256_sp_sse2(const char *input, char *output, char *scratchpad)
{
	uint8_t B[128];
	union {
		__m128i i128[8];
		uint32_t u32[32];
	} X;
	__m128i *V;
	uint32_t i, j, k;

	V = (__m128i *)(((uintptr_t)(scratchpad) + 63) & ~ (uintptr_t)(63));

	PBKDF2_SHA256((const uint8_t *)input, 80, (const uint8_t *)input, 80, 1, B, 128);

	for (k = 0; k < 2; k++) {
		for (i = 0; i < 16; i++) {
			X.u32[k * 16 + i] = le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
		}
	}

	for (i = 0; i < 1024; i++) {
		for (k = 0; k < 8; k++)
			V[i * 8 + k] = X.i128[k];
		xor_salsa8_sse2(&X.i128[0], &X.i128[4]);
		xor_salsa8_sse2(&X.i128[4], &X.i128[0]);
	}
	for (i = 0; i < 1024; i++) {
		j = 8 * (X.u32[16] & 1023);
		for (k = 0; k < 8; k++)
			X.i128[k] = _mm_xor_si128(X.i128[k], V[j + k]);
		xor_salsa8_sse2(&X.i128[0], &X.i128[4]);
		xor_salsa8_sse2(&X.i128[4], &X.i128[0]);
	}

	for (k = 0; k < 2; k++) {
		for (i = 0; i < 16; i++) {
			le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], X.u32[k * 16 + i]);
		}
	}

	PBKDF2_SHA256((const uint8_t *)input, 80, B, 128, 1, (uint8_t *)output, 32);
}
<commit_msg>scrypt: delete sse2 version.<commit_after><|endoftext|>


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

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <string>
#include <vector>

#include "nacl_io/ioctl.h"
#include "nacl_io/kernel_wrap.h"
#include "nacl_io/nacl_io.h"

#include "ppapi/c/ppb_var.h"

#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
#include "ppapi/cpp/touch_point.h"
#include "ppapi/cpp/var.h"

#include "ppapi_simple/ps_event.h"
#include "ppapi_simple/ps_instance.h"
#include "ppapi_simple/ps_interface.h"
#include "ppapi_simple/ps_main.h"

#if defined(WIN32)
#define open _open
#define dup2 _dup2
#endif

static PSInstance* s_InstanceObject = NULL;

PSInstance* PSInstance::GetInstance() {
  return s_InstanceObject;
}

struct StartInfo {
  PSInstance* inst_;
  uint32_t argc_;
  char** argv_;
};

// The starting point for 'main'.  We create this thread to hide the real
// main pepper thread which must never be blocked.
void* PSInstance::MainThreadThunk(void *info) {
  s_InstanceObject->Trace("Got MainThreadThunk.\n");
  StartInfo* si = static_cast<StartInfo*>(info);
  si->inst_->main_loop_ = new pp::MessageLoop(si->inst_);
  si->inst_->main_loop_->AttachToCurrentThread();

  int ret = si->inst_->MainThread(si->argc_, si->argv_);
  for (uint32_t i = 0; i < si->argc_; i++) {
    delete[] si->argv_[i];
  }
  delete[] si->argv_;
  delete si;

  // Exit the entire process once the 'main' thread returns.
  // The error code will be available to javascript via
  // the exitcode paramater of the crash event.
  exit(ret);
  return NULL;
}

// The default implementation supports running a 'C' main.
int PSInstance::MainThread(int argc, char *argv[]) {
  if (!main_cb_) {
    Error("No main defined.\n");
    return 0;
  }

  Trace("Starting MAIN.\n");
  int ret = main_cb_(argc, argv);
  Log("Main thread returned with %d.\n", ret);
  return ret;
}

PSInstance::PSInstance(PP_Instance instance)
    : pp::Instance(instance),
      pp::MouseLock(this),
      pp::Graphics3DClient(this),
      main_loop_(NULL),
      events_enabled_(PSE_NONE),
      verbosity_(PSV_WARN),
      fd_tty_(-1) {
  // Set the single Instance object
  s_InstanceObject = this;

#ifdef NACL_SDK_DEBUG
  SetVerbosity(PSV_LOG);
#endif

  RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
                     PP_INPUTEVENT_CLASS_KEYBOARD |
                     PP_INPUTEVENT_CLASS_WHEEL |
                     PP_INPUTEVENT_CLASS_TOUCH);
}

PSInstance::~PSInstance() {}

void PSInstance::SetMain(PSMainFunc_t main) {
  main_cb_ = main;
}

bool PSInstance::Init(uint32_t arg,
                      const char* argn[],
                      const char* argv[]) {
  StartInfo* si = new StartInfo;

  si->inst_ = this;
  si->argc_ = 1;
  si->argv_ = new char *[arg+1];
  si->argv_[0] = NULL;

  // Process embed attributes into the environment.
  // Converted the attribute names to uppercase as environment variables are
  // case sensitive but are almost universally uppercase in practice.
  for (uint32_t i = 0; i < arg; i++) {
    std::string key = argn[i];
    std::transform(key.begin(), key.end(), key.begin(), toupper);
    setenv(key.c_str(), argv[i], 1);
  }

  // Set a default value for SRC.
  setenv("SRC", "NMF?", 0);
  // Use the src tag name if ARG0 is not explicitly specified.
  setenv("ARG0", getenv("SRC"), 0);

  // Walk ARG0..ARGn populating argv until an argument is missing.
  for (;;) {
    std::ostringstream arg_stream;
    arg_stream << "ARG" << si->argc_;
    std::string arg_name = arg_stream.str();
    const char* next_arg = getenv(arg_name.c_str());
    if (NULL == next_arg)
      break;

    char* value = new char[strlen(next_arg) + 1];
    strcpy(value, next_arg);
    si->argv_[si->argc_++] = value;
  }

  PSInterfaceInit();
  bool props_processed = ProcessProperties();

  // Log arg values only once ProcessProperties has been
  // called so that the ps_verbosity attribute will be in
  // effect.
  for (uint32_t i = 0; i < arg; i++) {
    if (argv[i]) {
      Trace("attribs[%d] '%s=%s'\n", i, argn[i], argv[i]);
    } else {
      Trace("attribs[%d] '%s'\n", i, argn[i]);
    }
  }

  for (uint32_t i = 0; i < si->argc_; i++) {
    Trace("argv[%d] '%s'\n", i, si->argv_[i]);
  }

  if (!props_processed) {
    Warn("Skipping create thread.\n");
    return false;
  }

  pthread_t main_thread;
  int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si);
  Trace("Created thread: %d.\n", ret);
  return ret == 0;
}

// Processes the properties set at compile time via the
// initialization macro, or via dynamically set embed attributes
// through instance DidCreate.
bool PSInstance::ProcessProperties() {
  // Set default values
  setenv("PS_STDIN", "/dev/stdin", 0);
  setenv("PS_STDOUT", "/dev/stdout", 0);
  setenv("PS_STDERR", "/dev/console3", 0);

  // Reset verbosity if passed in
  const char* verbosity = getenv("PS_VERBOSITY");
  if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));

  // Enable NaCl IO to map STDIN, STDOUT, and STDERR
  nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
  int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
  dup2(fd0, 0);

  int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
  dup2(fd1, 1);

  int fd2 = open(getenv("PS_STDERR"), O_WRONLY);
  dup2(fd2, 2);

  const char* tty_prefix = getenv("PS_TTY_PREFIX");
  if (tty_prefix) {
    fd_tty_ = open("/dev/tty", O_WRONLY);
    if (fd_tty_ >= 0) {
      ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix));
    } else {
      Error("Failed to open /dev/tty.\n");
    }
  }

  // Set line buffering on stdout and stderr
#if !defined(WIN32)
  setvbuf(stderr, NULL, _IOLBF, 0);
  setvbuf(stdout, NULL, _IOLBF, 0);
#endif
  return true;
}

void PSInstance::SetVerbosity(Verbosity verbosity) {
  verbosity_ = verbosity;
}

void PSInstance::VALog(Verbosity verbosity, const char *fmt, va_list args) {
  if (verbosity <= verbosity_) {
    fprintf(stderr, "ps: ");
    vfprintf(stderr, fmt, args);
  }
}

void PSInstance::Trace(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_TRACE, fmt, ap);
  va_end(ap);
}

void PSInstance::Log(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_LOG, fmt, ap);
  va_end(ap);
}

void PSInstance::Warn(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_WARN, fmt, ap);
  va_end(ap);
}

void PSInstance::Error(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_ERROR, fmt, ap);
  va_end(ap);
}

void PSInstance::SetEnabledEvents(uint32_t mask) {
  events_enabled_ = mask;
}

void PSInstance::PostEvent(PSEventType type) {
  assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST == type ||
         PSE_MOUSELOCK_MOUSELOCKLOST == type);

  if (events_enabled_ & type) {
    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
    memset(env, 0, sizeof(*env));
    env->type = type;
    event_queue_.Enqueue(env);
  }
}

void PSInstance::PostEvent(PSEventType type, PP_Bool bool_value) {
  assert(PSE_INSTANCE_DIDCHANGEFOCUS == type);

  if (events_enabled_ & type) {
    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
    memset(env, 0, sizeof(*env));
    env->type = type;
    env->as_bool = bool_value;
    event_queue_.Enqueue(env);
  }
}

void PSInstance::PostEvent(PSEventType type, PP_Resource resource) {
  assert(PSE_INSTANCE_HANDLEINPUT == type ||
         PSE_INSTANCE_DIDCHANGEVIEW == type);

  if (events_enabled_ & type) {
    if (resource) {
      PSInterfaceCore()->AddRefResource(resource);
    }
    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
    memset(env, 0, sizeof(*env));
    env->type = type;
    env->as_resource = resource;
    event_queue_.Enqueue(env);
  }
}

void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
  assert(PSE_INSTANCE_HANDLEMESSAGE == type);

  // If the user has specified a tty_prefix_ (using ioctl), then we'll give the
  // tty node a chance to vacuum up any messages beginning with that prefix. If
  // the message does not start with the prefix, the ioctl call will return
  // ENOENT and we'll pass the message through to the event queue.
  if (fd_tty_ >= 0 && var.type == PP_VARTYPE_STRING) {
    uint32_t message_len;
    const char* message = PSInterfaceVar()->VarToUtf8(var, &message_len);
    std::string message_str(message, message + message_len);

    // Since our message may contain null characters, we can't send it as a
    // naked C string, so we package it up in this struct before sending it
    // to the ioctl.
    struct tioc_nacl_input_string ioctl_message;
    ioctl_message.length = message_len;
    ioctl_message.buffer = message_str.data();
    int ret =
      ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message));
    if (ret != 0 && errno != ENOTTY) {
      Error("ioctl returned unexpected error: %d.\n", ret);
    }

    return;
  }

  if (events_enabled_ & type) {
    PSInterfaceVar()->AddRef(var);
    PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
    memset(env, 0, sizeof(*env));
    env->type = type;
    env->as_var = var;
    event_queue_.Enqueue(env);
  }
}

PSEvent* PSInstance::TryAcquireEvent() {
  return event_queue_.Dequeue(false);
}

PSEvent* PSInstance::WaitAcquireEvent() {
  return event_queue_.Dequeue(true);
}

void PSInstance::ReleaseEvent(PSEvent* event) {
  if (event) {
    switch(event->type) {
      case PSE_INSTANCE_HANDLEMESSAGE:
        PSInterfaceVar()->Release(event->as_var);
        break;
      case PSE_INSTANCE_HANDLEINPUT:
      case PSE_INSTANCE_DIDCHANGEVIEW:
        if (event->as_resource) {
          PSInterfaceCore()->ReleaseResource(event->as_resource);
        }
        break;
      default:
        break;
    }
    free(event);
  }
}

void PSInstance::HandleMessage(const pp::Var& message) {
  Trace("Got Message\n");
  PostEvent(PSE_INSTANCE_HANDLEMESSAGE, message.pp_var());
}

bool PSInstance::HandleInputEvent(const pp::InputEvent& event) {
  PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource());
  return true;
}

void PSInstance::DidChangeView(const pp::View& view) {
  pp::Size new_size = view.GetRect().size();
  Log("Got View change: %d,%d\n", new_size.width(), new_size.height());
  PostEvent(PSE_INSTANCE_DIDCHANGEVIEW, view.pp_resource());
}

void PSInstance::DidChangeFocus(bool focus) {
  Log("Got Focus change: %s\n", focus ? "FOCUS ON" : "FOCUS OFF");
  PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE);
}

void PSInstance::Graphics3DContextLost() {
  Log("Graphics3DContextLost\n");
  PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
}

void PSInstance::MouseLockLost() {
  Log("MouseLockLost\n");
  PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
}
<commit_msg>Fix event race in ppapi simple framework. By default, all events are filtered out between the main thread and the application thread in ppapi simple.  Events are filtered out before inserting them into the FIFO queue between the threads.  In some cases, an app that enables PSEventSetFilter(PSE_ALL) will miss the first few events.  This change pushes all events into the FIFO queue, and does filtering when extracting them on the app thread.  While not ideal, it addresses the problem of an app potentially missing the first few events, which if they are DidChangeView or a message from JS could prevent the app from starting correctly.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <string>
#include <vector>

#include "nacl_io/ioctl.h"
#include "nacl_io/kernel_wrap.h"
#include "nacl_io/nacl_io.h"

#include "ppapi/c/ppb_var.h"

#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
#include "ppapi/cpp/touch_point.h"
#include "ppapi/cpp/var.h"

#include "ppapi_simple/ps_event.h"
#include "ppapi_simple/ps_instance.h"
#include "ppapi_simple/ps_interface.h"
#include "ppapi_simple/ps_main.h"

#if defined(WIN32)
#define open _open
#define dup2 _dup2
#endif

static PSInstance* s_InstanceObject = NULL;

PSInstance* PSInstance::GetInstance() {
  return s_InstanceObject;
}

struct StartInfo {
  PSInstance* inst_;
  uint32_t argc_;
  char** argv_;
};

// The starting point for 'main'.  We create this thread to hide the real
// main pepper thread which must never be blocked.
void* PSInstance::MainThreadThunk(void *info) {
  s_InstanceObject->Trace("Got MainThreadThunk.\n");
  StartInfo* si = static_cast<StartInfo*>(info);
  si->inst_->main_loop_ = new pp::MessageLoop(si->inst_);
  si->inst_->main_loop_->AttachToCurrentThread();

  int ret = si->inst_->MainThread(si->argc_, si->argv_);
  for (uint32_t i = 0; i < si->argc_; i++) {
    delete[] si->argv_[i];
  }
  delete[] si->argv_;
  delete si;

  // Exit the entire process once the 'main' thread returns.
  // The error code will be available to javascript via
  // the exitcode paramater of the crash event.
  exit(ret);
  return NULL;
}

// The default implementation supports running a 'C' main.
int PSInstance::MainThread(int argc, char *argv[]) {
  if (!main_cb_) {
    Error("No main defined.\n");
    return 0;
  }

  Trace("Starting MAIN.\n");
  int ret = main_cb_(argc, argv);
  Log("Main thread returned with %d.\n", ret);
  return ret;
}

PSInstance::PSInstance(PP_Instance instance)
    : pp::Instance(instance),
      pp::MouseLock(this),
      pp::Graphics3DClient(this),
      main_loop_(NULL),
      events_enabled_(PSE_NONE),
      verbosity_(PSV_WARN),
      fd_tty_(-1) {
  // Set the single Instance object
  s_InstanceObject = this;

#ifdef NACL_SDK_DEBUG
  SetVerbosity(PSV_LOG);
#endif

  RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
                     PP_INPUTEVENT_CLASS_KEYBOARD |
                     PP_INPUTEVENT_CLASS_WHEEL |
                     PP_INPUTEVENT_CLASS_TOUCH);
}

PSInstance::~PSInstance() {}

void PSInstance::SetMain(PSMainFunc_t main) {
  main_cb_ = main;
}

bool PSInstance::Init(uint32_t arg,
                      const char* argn[],
                      const char* argv[]) {
  StartInfo* si = new StartInfo;

  si->inst_ = this;
  si->argc_ = 1;
  si->argv_ = new char *[arg+1];
  si->argv_[0] = NULL;

  // Process embed attributes into the environment.
  // Converted the attribute names to uppercase as environment variables are
  // case sensitive but are almost universally uppercase in practice.
  for (uint32_t i = 0; i < arg; i++) {
    std::string key = argn[i];
    std::transform(key.begin(), key.end(), key.begin(), toupper);
    setenv(key.c_str(), argv[i], 1);
  }

  // Set a default value for SRC.
  setenv("SRC", "NMF?", 0);
  // Use the src tag name if ARG0 is not explicitly specified.
  setenv("ARG0", getenv("SRC"), 0);

  // Walk ARG0..ARGn populating argv until an argument is missing.
  for (;;) {
    std::ostringstream arg_stream;
    arg_stream << "ARG" << si->argc_;
    std::string arg_name = arg_stream.str();
    const char* next_arg = getenv(arg_name.c_str());
    if (NULL == next_arg)
      break;

    char* value = new char[strlen(next_arg) + 1];
    strcpy(value, next_arg);
    si->argv_[si->argc_++] = value;
  }

  PSInterfaceInit();
  bool props_processed = ProcessProperties();

  // Log arg values only once ProcessProperties has been
  // called so that the ps_verbosity attribute will be in
  // effect.
  for (uint32_t i = 0; i < arg; i++) {
    if (argv[i]) {
      Trace("attribs[%d] '%s=%s'\n", i, argn[i], argv[i]);
    } else {
      Trace("attribs[%d] '%s'\n", i, argn[i]);
    }
  }

  for (uint32_t i = 0; i < si->argc_; i++) {
    Trace("argv[%d] '%s'\n", i, si->argv_[i]);
  }

  if (!props_processed) {
    Warn("Skipping create thread.\n");
    return false;
  }

  pthread_t main_thread;
  int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si);
  Trace("Created thread: %d.\n", ret);
  return ret == 0;
}

// Processes the properties set at compile time via the
// initialization macro, or via dynamically set embed attributes
// through instance DidCreate.
bool PSInstance::ProcessProperties() {
  // Set default values
  setenv("PS_STDIN", "/dev/stdin", 0);
  setenv("PS_STDOUT", "/dev/stdout", 0);
  setenv("PS_STDERR", "/dev/console3", 0);

  // Reset verbosity if passed in
  const char* verbosity = getenv("PS_VERBOSITY");
  if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));

  // Enable NaCl IO to map STDIN, STDOUT, and STDERR
  nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
  int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
  dup2(fd0, 0);

  int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
  dup2(fd1, 1);

  int fd2 = open(getenv("PS_STDERR"), O_WRONLY);
  dup2(fd2, 2);

  const char* tty_prefix = getenv("PS_TTY_PREFIX");
  if (tty_prefix) {
    fd_tty_ = open("/dev/tty", O_WRONLY);
    if (fd_tty_ >= 0) {
      ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix));
    } else {
      Error("Failed to open /dev/tty.\n");
    }
  }

  // Set line buffering on stdout and stderr
#if !defined(WIN32)
  setvbuf(stderr, NULL, _IOLBF, 0);
  setvbuf(stdout, NULL, _IOLBF, 0);
#endif
  return true;
}

void PSInstance::SetVerbosity(Verbosity verbosity) {
  verbosity_ = verbosity;
}

void PSInstance::VALog(Verbosity verbosity, const char *fmt, va_list args) {
  if (verbosity <= verbosity_) {
    fprintf(stderr, "ps: ");
    vfprintf(stderr, fmt, args);
  }
}

void PSInstance::Trace(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_TRACE, fmt, ap);
  va_end(ap);
}

void PSInstance::Log(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_LOG, fmt, ap);
  va_end(ap);
}

void PSInstance::Warn(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_WARN, fmt, ap);
  va_end(ap);
}

void PSInstance::Error(const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  VALog(PSV_ERROR, fmt, ap);
  va_end(ap);
}

void PSInstance::SetEnabledEvents(uint32_t mask) {
  events_enabled_ = mask;
  if (mask == 0) {
    static bool warn_once = true;
    if (warn_once) {
      Warn("PSInstance::SetEnabledEvents(mask) where mask == 0 will block\n");
      Warn("all events. This can come from PSEventSetFilter(PSE_NONE);\n");
      warn_once = false;
    }
  }
}

void PSInstance::PostEvent(PSEventType type) {
  assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST == type ||
         PSE_MOUSELOCK_MOUSELOCKLOST == type);

  PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
  memset(env, 0, sizeof(*env));
  env->type = type;
  event_queue_.Enqueue(env);
}

void PSInstance::PostEvent(PSEventType type, PP_Bool bool_value) {
  assert(PSE_INSTANCE_DIDCHANGEFOCUS == type);

  PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
  memset(env, 0, sizeof(*env));
  env->type = type;
  env->as_bool = bool_value;
  event_queue_.Enqueue(env);
}

void PSInstance::PostEvent(PSEventType type, PP_Resource resource) {
  assert(PSE_INSTANCE_HANDLEINPUT == type ||
         PSE_INSTANCE_DIDCHANGEVIEW == type);

  if (resource) {
    PSInterfaceCore()->AddRefResource(resource);
  }
  PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
  memset(env, 0, sizeof(*env));
  env->type = type;
  env->as_resource = resource;
  event_queue_.Enqueue(env);
}

void PSInstance::PostEvent(PSEventType type, const PP_Var& var) {
  assert(PSE_INSTANCE_HANDLEMESSAGE == type);

  // If the user has specified a tty_prefix_ (using ioctl), then we'll give the
  // tty node a chance to vacuum up any messages beginning with that prefix. If
  // the message does not start with the prefix, the ioctl call will return
  // ENOENT and we'll pass the message through to the event queue.
  if (fd_tty_ >= 0 && var.type == PP_VARTYPE_STRING) {
    uint32_t message_len;
    const char* message = PSInterfaceVar()->VarToUtf8(var, &message_len);
    std::string message_str(message, message + message_len);

    // Since our message may contain null characters, we can't send it as a
    // naked C string, so we package it up in this struct before sending it
    // to the ioctl.
    struct tioc_nacl_input_string ioctl_message;
    ioctl_message.length = message_len;
    ioctl_message.buffer = message_str.data();
    int ret =
      ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message));
    if (ret != 0 && errno != ENOTTY) {
      Error("ioctl returned unexpected error: %d.\n", ret);
    }

    return;
  }

  PSInterfaceVar()->AddRef(var);
  PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent));
  memset(env, 0, sizeof(*env));
  env->type = type;
  env->as_var = var;
  event_queue_.Enqueue(env);
}

PSEvent* PSInstance::TryAcquireEvent() {
  PSEvent* event;
  while(true) {
    event = event_queue_.Dequeue(false);
    if (NULL == event)
      break;
    if (events_enabled_ & event->type)
      break;
    // Release filtered events & continue to acquire.
    ReleaseEvent(event);
  }
  return event;
}

PSEvent* PSInstance::WaitAcquireEvent() {
  PSEvent* event;
  while(true) {
    event = event_queue_.Dequeue(true);
    if (events_enabled_ & event->type)
      break;
    // Release filtered events & continue to acquire.
    ReleaseEvent(event);
  }
  return event;
}

void PSInstance::ReleaseEvent(PSEvent* event) {
  if (event) {
    switch(event->type) {
      case PSE_INSTANCE_HANDLEMESSAGE:
        PSInterfaceVar()->Release(event->as_var);
        break;
      case PSE_INSTANCE_HANDLEINPUT:
      case PSE_INSTANCE_DIDCHANGEVIEW:
        if (event->as_resource) {
          PSInterfaceCore()->ReleaseResource(event->as_resource);
        }
        break;
      default:
        break;
    }
    free(event);
  }
}

void PSInstance::HandleMessage(const pp::Var& message) {
  Trace("Got Message\n");
  PostEvent(PSE_INSTANCE_HANDLEMESSAGE, message.pp_var());
}

bool PSInstance::HandleInputEvent(const pp::InputEvent& event) {
  PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource());
  return true;
}

void PSInstance::DidChangeView(const pp::View& view) {
  pp::Size new_size = view.GetRect().size();
  Log("Got View change: %d,%d\n", new_size.width(), new_size.height());
  PostEvent(PSE_INSTANCE_DIDCHANGEVIEW, view.pp_resource());
}

void PSInstance::DidChangeFocus(bool focus) {
  Log("Got Focus change: %s\n", focus ? "FOCUS ON" : "FOCUS OFF");
  PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE);
}

void PSInstance::Graphics3DContextLost() {
  Log("Graphics3DContextLost\n");
  PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST);
}

void PSInstance::MouseLockLost() {
  Log("MouseLockLost\n");
  PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST);
}
<|endoftext|>