// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#pragma once

#define _CRT_SECURE_NO_WARNINGS

#include "config.h"

/* size of screen tiles */
#define TILE_SIZE_X 8
#define TILE_SIZE_Y 8

/* vertex and triangle layout */
struct Vertex   { float x,y,z,r;  }; // FIXME: rename to Vertex4f
struct Triangle { int v0, v1, v2; };

/* include embree API */
#include "../../../include/embree2/rtcore.isph"

/* include optional vector library */
#include "../math/math.isph"
#include "../math/vec.isph"
#include "../math/affinespace.isph"
#include "../core/ray.isph"
#include "camera.isph"
#include "scene_device.isph"
#include "noise.isph"
#if !defined(ISPC)
#include "../../../common/algorithms/parallel_for.h"
#endif

enum Mode {
  MODE_NORMAL = 0,
  MODE_STREAM_COHERENT = 1,
  MODE_STREAM_INCOHERENT = 2
};

extern uniform Mode g_mode;

/* error reporting function */
unmasked void error_handler(const uniform RTCError code, const uniform int8* uniform str = NULL);

/* returns time stamp counter */
extern "C" uniform int64 get_tsc();

/* declare some standard library functions */
extern "C" void abort ();
extern "C" void exit(uniform int);
extern "C" uniform int puts ( const uniform int8* uniform str );
extern "C" uniform int putchar ( uniform int character );

/* face forward for shading normals */
inline Vec3f faceforward( const Vec3f& N, const Vec3f& I, const Vec3f& Ng ) {
  Vec3f NN = N; return dot(I, Ng) < 0 ? NN : neg(NN);
}

/* glut keys codes */
#if !defined(GLUT_KEY_F1)
#define GLUT_KEY_F1 1
#define GLUT_KEY_F2 2
#define GLUT_KEY_F3 3
#define GLUT_KEY_F4 4
#define GLUT_KEY_F5 5
#define GLUT_KEY_F6 6
#define GLUT_KEY_F7 7
#define GLUT_KEY_F8 8
#define GLUT_KEY_F9 9
#define GLUT_KEY_F10 10
#define GLUT_KEY_F11 11
#define GLUT_KEY_F12 12
#endif

/* standard shading function */
typedef void (* uniform renderTileFunc)(uniform int taskIndex,
                                        uniform int* uniform pixels,
                                        const uniform unsigned int width,
                                        const uniform unsigned int height,
                                        const uniform float time,
                                        const uniform ISPCCamera& camera,
                                        const uniform int numTilesX,
                                        const uniform int numTilesY);
extern renderTileFunc renderTile;

extern void device_key_pressed_default(uniform int key);
extern void (* uniform key_pressed_handler)(uniform int key);

void renderTileStandard(uniform int taskIndex,
                        uniform int* uniform pixels,
                        const uniform unsigned int width,
                        const uniform unsigned int height,
                        const uniform float time,
                        const uniform ISPCCamera& camera,
                        const uniform int numTilesX,
                        const uniform int numTilesY);

uniform unsigned int getNumHWThreads();

#if defined(ISPC)
#define ALIGNED_STRUCT
#define __aligned(x)
#define MAYBE_UNUSED
#endif

struct Sample3f
{
  Vec3f v;
  float pdf;
};

inline uniform Sample3f make_Sample3f(const uniform Vec3f& v, const uniform float pdf) {
  uniform Sample3f s; s.v = v; s.pdf = pdf; return s;
}

#if defined(ISPC)
inline Sample3f make_Sample3f(const Vec3f& v, const float pdf) {
  Sample3f s; s.v = v; s.pdf = pdf; return s;
}
#endif

/* draws progress bar */
extern "C" unmasked void progressStart();
extern "C" unmasked uniform bool progressMonitor(void* uniform ptr, const uniform double n);
extern "C" unmasked void progressEnd();

Vec2f  getTextureCoordinatesSubdivMesh(void* uniform mesh, const unsigned int primID, const float u, const float v);

float  getTextureTexel1f(const uniform Texture* uniform texture, float u, float v);
Vec3f  getTextureTexel3f(const uniform Texture* uniform texture, float u, float v);
