Add files
This commit is contained in:
25
Kinc/Sources/kinc/audio1/a1unit.c
Normal file
25
Kinc/Sources/kinc/audio1/a1unit.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "audio.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct kinc_a1_channel {
|
||||
kinc_a1_sound_t *sound;
|
||||
float position;
|
||||
bool loop;
|
||||
volatile float volume;
|
||||
float pitch;
|
||||
};
|
||||
|
||||
struct kinc_a1_stream_channel {
|
||||
kinc_a1_sound_stream_t *stream;
|
||||
int position;
|
||||
};
|
||||
|
||||
struct kinc_internal_video_channel {
|
||||
struct kinc_internal_video_sound_stream *stream;
|
||||
int position;
|
||||
};
|
||||
|
||||
#include "audio.c.h"
|
||||
#include "sound.c.h"
|
||||
#include "soundstream.c.h"
|
||||
239
Kinc/Sources/kinc/audio1/audio.c.h
Normal file
239
Kinc/Sources/kinc/audio1/audio.c.h
Normal file
@ -0,0 +1,239 @@
|
||||
#include "audio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kinc/audio2/audio.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/threads/atomic.h>
|
||||
#include <kinc/threads/mutex.h>
|
||||
#include <kinc/video.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static kinc_mutex_t mutex;
|
||||
|
||||
#define CHANNEL_COUNT 16
|
||||
static kinc_a1_channel_t channels[CHANNEL_COUNT];
|
||||
static kinc_a1_stream_channel_t streamchannels[CHANNEL_COUNT];
|
||||
static kinc_internal_video_channel_t videos[CHANNEL_COUNT];
|
||||
|
||||
static float sampleLinear(int16_t *data, float position) {
|
||||
int pos1 = (int)position;
|
||||
int pos2 = (int)(position + 1);
|
||||
float sample1 = data[pos1] / 32767.0f;
|
||||
float sample2 = data[pos2] / 32767.0f;
|
||||
float a = position - pos1;
|
||||
return sample1 * (1 - a) + sample2 * a;
|
||||
}
|
||||
|
||||
/*float sampleHermite4pt3oX(s16* data, float position) {
|
||||
float s0 = data[(int)(position - 1)] / 32767.0f;
|
||||
float s1 = data[(int)(position + 0)] / 32767.0f;
|
||||
float s2 = data[(int)(position + 1)] / 32767.0f;
|
||||
float s3 = data[(int)(position + 2)] / 32767.0f;
|
||||
|
||||
float x = position - (int)(position);
|
||||
|
||||
// 4-point, 3rd-order Hermite (x-form)
|
||||
float c0 = s1;
|
||||
float c1 = 0.5f * (s2 - s0);
|
||||
float c2 = s0 - 2.5f * s1 + 2 * s2 - 0.5f * s3;
|
||||
float c3 = 0.5f * (s3 - s0) + 1.5f * (s1 - s2);
|
||||
return ((c3 * x + c2) * x + c1) * x + c0;
|
||||
}*/
|
||||
|
||||
void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples) {
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
bool left = (i % 2) == 0;
|
||||
float value = 0;
|
||||
#if 0
|
||||
__m128 sseSamples[4];
|
||||
for (int i = 0; i < channelCount; i += 4) {
|
||||
s16 data[4];
|
||||
for (int i2 = 0; i2 < 4; ++i2) {
|
||||
if (channels[i + i2].sound != nullptr) {
|
||||
data[i2] = *(s16*)&channels[i + i2].sound->data[channels[i + i2].position];
|
||||
channels[i + i2].position += 2;
|
||||
if (channels[i + i2].position >= channels[i + i2].sound->size) channels[i + i2].sound = nullptr;
|
||||
}
|
||||
else {
|
||||
data[i2] = 0;
|
||||
}
|
||||
}
|
||||
sseSamples[i / 4] = _mm_set_ps(data[3] / 32767.0f, data[2] / 32767.0f, data[1] / 32767.0f, data[0] / 32767.0f);
|
||||
}
|
||||
__m128 a = _mm_add_ps(sseSamples[0], sseSamples[1]);
|
||||
__m128 b = _mm_add_ps(sseSamples[2], sseSamples[3]);
|
||||
__m128 c = _mm_add_ps(a, b);
|
||||
value = c.m128_f32[0] + c.m128_f32[1] + c.m128_f32[2] + c.m128_f32[3];
|
||||
value = max(min(value, 1.0f), -1.0f);
|
||||
#else
|
||||
kinc_mutex_lock(&mutex);
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (channels[i].sound != NULL) {
|
||||
// value += *(s16*)&channels[i].sound->data[(int)channels[i].position] / 32767.0f * channels[i].sound->volume();
|
||||
if (left)
|
||||
value += sampleLinear(channels[i].sound->left, channels[i].position) * channels[i].volume * channels[i].volume;
|
||||
else
|
||||
value += sampleLinear(channels[i].sound->right, channels[i].position) * channels[i].volume * channels[i].volume;
|
||||
value = kinc_max(kinc_min(value, 1.0f), -1.0f);
|
||||
if (!left)
|
||||
channels[i].position += channels[i].pitch / channels[i].sound->sample_rate_pos;
|
||||
// channels[i].position += 2;
|
||||
if (channels[i].position + 1 >= channels[i].sound->size) {
|
||||
if (channels[i].loop) {
|
||||
channels[i].position = 0;
|
||||
}
|
||||
else {
|
||||
channels[i].sound = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (streamchannels[i].stream != NULL) {
|
||||
value += kinc_a1_sound_stream_next_sample(streamchannels[i].stream) * kinc_a1_sound_stream_volume(streamchannels[i].stream);
|
||||
value = kinc_max(kinc_min(value, 1.0f), -1.0f);
|
||||
if (kinc_a1_sound_stream_ended(streamchannels[i].stream))
|
||||
streamchannels[i].stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (videos[i].stream != NULL) {
|
||||
value += kinc_internal_video_sound_stream_next_sample(videos[i].stream);
|
||||
value = kinc_max(kinc_min(value, 1.0f), -1.0f);
|
||||
if (kinc_internal_video_sound_stream_ended(videos[i].stream)) {
|
||||
videos[i].stream = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinc_mutex_unlock(&mutex);
|
||||
#endif
|
||||
*(float *)&buffer->data[buffer->write_location] = value;
|
||||
buffer->write_location += 4;
|
||||
if (buffer->write_location >= buffer->data_size)
|
||||
buffer->write_location = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_a1_init(void) {
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
channels[i].sound = NULL;
|
||||
channels[i].position = 0;
|
||||
}
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
streamchannels[i].stream = NULL;
|
||||
streamchannels[i].position = 0;
|
||||
}
|
||||
kinc_mutex_init(&mutex);
|
||||
|
||||
kinc_a2_init();
|
||||
kinc_a2_set_callback(kinc_a1_mix);
|
||||
}
|
||||
|
||||
kinc_a1_channel_t *kinc_a1_play_sound(kinc_a1_sound_t *sound, bool loop, float pitch, bool unique) {
|
||||
kinc_a1_channel_t *channel = NULL;
|
||||
kinc_mutex_lock(&mutex);
|
||||
bool found = false;
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (channels[i].sound == sound) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found || !unique) {
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (channels[i].sound == NULL) {
|
||||
channels[i].sound = sound;
|
||||
channels[i].position = 0;
|
||||
channels[i].loop = loop;
|
||||
channels[i].pitch = pitch;
|
||||
channels[i].volume = sound->volume;
|
||||
channel = &channels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
kinc_mutex_unlock(&mutex);
|
||||
return channel;
|
||||
}
|
||||
|
||||
void kinc_a1_stop_sound(kinc_a1_sound_t *sound) {
|
||||
kinc_mutex_lock(&mutex);
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (channels[i].sound == sound) {
|
||||
channels[i].sound = NULL;
|
||||
channels[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void kinc_a1_play_sound_stream(kinc_a1_sound_stream_t *stream) {
|
||||
kinc_mutex_lock(&mutex);
|
||||
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (streamchannels[i].stream == stream) {
|
||||
streamchannels[i].stream = NULL;
|
||||
streamchannels[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (streamchannels[i].stream == NULL) {
|
||||
streamchannels[i].stream = stream;
|
||||
streamchannels[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void kinc_a1_stop_sound_stream(kinc_a1_sound_stream_t *stream) {
|
||||
kinc_mutex_lock(&mutex);
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (streamchannels[i].stream == stream) {
|
||||
streamchannels[i].stream = NULL;
|
||||
streamchannels[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void kinc_internal_play_video_sound_stream(struct kinc_internal_video_sound_stream *stream) {
|
||||
kinc_mutex_lock(&mutex);
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (videos[i].stream == NULL) {
|
||||
videos[i].stream = stream;
|
||||
videos[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void kinc_internal_stop_video_sound_stream(struct kinc_internal_video_sound_stream *stream) {
|
||||
kinc_mutex_lock(&mutex);
|
||||
for (int i = 0; i < CHANNEL_COUNT; ++i) {
|
||||
if (videos[i].stream == stream) {
|
||||
videos[i].stream = NULL;
|
||||
videos[i].position = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
kinc_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
float kinc_a1_channel_get_volume(kinc_a1_channel_t *channel) {
|
||||
return channel->volume;
|
||||
}
|
||||
|
||||
void kinc_a1_channel_set_volume(kinc_a1_channel_t *channel, float volume) {
|
||||
KINC_ATOMIC_EXCHANGE_FLOAT(&channel->volume, volume);
|
||||
}
|
||||
95
Kinc/Sources/kinc/audio1/audio.h
Normal file
95
Kinc/Sources/kinc/audio1/audio.h
Normal file
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "sound.h"
|
||||
#include "soundstream.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file audio.h
|
||||
\brief Audio1 is a high-level audio-API that lets you directly play audio-files. Depending on the target-system it either sits directly on a high-level
|
||||
system audio-API or is implemented based on Audio2.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_internal_video_sound_stream;
|
||||
|
||||
struct kinc_a1_channel;
|
||||
typedef struct kinc_a1_channel kinc_a1_channel_t;
|
||||
|
||||
struct kinc_a1_stream_channel;
|
||||
typedef struct kinc_a1_stream_channel kinc_a1_stream_channel_t;
|
||||
|
||||
struct kinc_internal_video_channel;
|
||||
typedef struct kinc_internal_video_channel kinc_internal_video_channel_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Audio1-API.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_a1_init(void);
|
||||
|
||||
/// <summary>
|
||||
/// Plays a sound immediately.
|
||||
/// </summary>
|
||||
/// <param name="sound">The sound to play</param>
|
||||
/// <param name="loop">Whether or not to automatically loop the sound</param>
|
||||
/// <param name="pitch">Changes the pitch by providing a value that's not 1.0f</param>
|
||||
/// <param name="unique">Makes sure that a sound is not played more than once at the same time</param>
|
||||
/// <returns>A channel object that can be used to control the playing sound. Please be aware that NULL is returned when the maximum number of simultaneously
|
||||
/// played channels was reached.</returns>
|
||||
KINC_FUNC kinc_a1_channel_t *kinc_a1_play_sound(kinc_a1_sound_t *sound, bool loop, float pitch, bool unique);
|
||||
|
||||
/// <summary>
|
||||
/// Stops the sound from playing.
|
||||
/// </summary>
|
||||
/// <param name="sound">The sound to stop</param>
|
||||
KINC_FUNC void kinc_a1_stop_sound(kinc_a1_sound_t *sound);
|
||||
|
||||
/// <summary>
|
||||
/// Starts playing a sound-stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to play</param>
|
||||
KINC_FUNC void kinc_a1_play_sound_stream(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Stops a sound-stream from playing.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to stop.</param>
|
||||
KINC_FUNC void kinc_a1_stop_sound_stream(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current volume of a channel. Only works correctly if the channel is still playing.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel to get the volume from</param>
|
||||
/// <returns>The volume</returns>
|
||||
KINC_FUNC float kinc_a1_channel_get_volume(kinc_a1_channel_t *channel);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current volume of a channel. Only works correctly if the channel is still playing.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel to set the volume for</param>
|
||||
/// <param name="volume">The volume to set</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_a1_channel_set_volume(kinc_a1_channel_t *channel, float volume);
|
||||
|
||||
/// <summary>
|
||||
/// Mixes audio into the provided buffer. kinc_a1_init sets this as the callback for a2
|
||||
/// but you can also call it manually to mix a1-audio with your own audio. To do that,
|
||||
/// first call kinc_a1_init, then call kinc_a2_set_callback to set it to your own callback
|
||||
/// and call kinc_a1_mix from within that callback. Please be aware that the callback
|
||||
/// will run in a separate audio-thread.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The audio-buffer to be filled</param>
|
||||
/// <param name="samples">The number of samples to be filled in</param>
|
||||
KINC_FUNC void kinc_a1_mix(kinc_a2_buffer_t *buffer, int samples);
|
||||
|
||||
void kinc_internal_play_video_sound_stream(struct kinc_internal_video_sound_stream *stream);
|
||||
void kinc_internal_stop_video_sound_stream(struct kinc_internal_video_sound_stream *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
222
Kinc/Sources/kinc/audio1/sound.c.h
Normal file
222
Kinc/Sources/kinc/audio1/sound.c.h
Normal file
@ -0,0 +1,222 @@
|
||||
#include "sound.h"
|
||||
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#include <kinc/libs/stb_vorbis.c>
|
||||
|
||||
#include <kinc/audio2/audio.h>
|
||||
#include <kinc/error.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
struct WaveData {
|
||||
uint16_t audioFormat;
|
||||
uint16_t numChannels;
|
||||
uint32_t sampleRate;
|
||||
uint32_t bytesPerSecond;
|
||||
uint16_t bitsPerSample;
|
||||
uint32_t dataSize;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
static void checkFOURCC(uint8_t **data, const char *fourcc) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
kinc_affirm(**data == fourcc[i]);
|
||||
++*data;
|
||||
}
|
||||
}
|
||||
|
||||
static void readFOURCC(uint8_t **data, char *fourcc) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
fourcc[i] = **data;
|
||||
++*data;
|
||||
}
|
||||
fourcc[4] = 0;
|
||||
}
|
||||
|
||||
static void readChunk(uint8_t **data, struct WaveData *wave) {
|
||||
char fourcc[5];
|
||||
readFOURCC(data, fourcc);
|
||||
uint32_t chunksize = kinc_read_u32le(*data);
|
||||
*data += 4;
|
||||
if (strcmp(fourcc, "fmt ") == 0) {
|
||||
wave->audioFormat = kinc_read_u16le(*data + 0);
|
||||
wave->numChannels = kinc_read_u16le(*data + 2);
|
||||
wave->sampleRate = kinc_read_u32le(*data + 4);
|
||||
wave->bytesPerSecond = kinc_read_u32le(*data + 8);
|
||||
wave->bitsPerSample = kinc_read_u16le(*data + 14);
|
||||
*data += chunksize;
|
||||
}
|
||||
else if (strcmp(fourcc, "data") == 0) {
|
||||
wave->dataSize = chunksize;
|
||||
wave->data = (uint8_t *)malloc(chunksize * sizeof(uint8_t));
|
||||
kinc_affirm(wave->data != NULL);
|
||||
memcpy(wave->data, *data, chunksize);
|
||||
*data += chunksize;
|
||||
}
|
||||
else {
|
||||
*data += chunksize;
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t convert8to16(uint8_t sample) {
|
||||
return (sample - 127) << 8;
|
||||
}
|
||||
|
||||
static void splitStereo8(uint8_t *data, int size, int16_t *left, int16_t *right) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
left[i] = convert8to16(data[i * 2 + 0]);
|
||||
right[i] = convert8to16(data[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void splitStereo16(int16_t *data, int size, int16_t *left, int16_t *right) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
left[i] = data[i * 2 + 0];
|
||||
right[i] = data[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
static void splitMono8(uint8_t *data, int size, int16_t *left, int16_t *right) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
left[i] = convert8to16(data[i]);
|
||||
right[i] = convert8to16(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void splitMono16(int16_t *data, int size, int16_t *left, int16_t *right) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
left[i] = data[i];
|
||||
right[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define MAXIMUM_SOUNDS 4096
|
||||
static kinc_a1_sound_t sounds[MAXIMUM_SOUNDS] = {0};
|
||||
|
||||
static kinc_a1_sound_t *find_sound(void) {
|
||||
for (int i = 0; i < MAXIMUM_SOUNDS; ++i) {
|
||||
if (!sounds[i].in_use) {
|
||||
return &sounds[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kinc_a1_sound_t *kinc_a1_sound_create(const char *filename) {
|
||||
kinc_a1_sound_t *sound = find_sound();
|
||||
assert(sound != NULL);
|
||||
sound->in_use = true;
|
||||
sound->volume = 1.0f;
|
||||
sound->size = 0;
|
||||
sound->left = NULL;
|
||||
sound->right = NULL;
|
||||
size_t filenameLength = strlen(filename);
|
||||
uint8_t *data = NULL;
|
||||
|
||||
if (strncmp(&filename[filenameLength - 4], ".ogg", 4) == 0) {
|
||||
kinc_file_reader_t file;
|
||||
if (!kinc_file_reader_open(&file, filename, KINC_FILE_TYPE_ASSET)) {
|
||||
sound->in_use = false;
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *filedata = (uint8_t *)malloc(kinc_file_reader_size(&file));
|
||||
kinc_file_reader_read(&file, filedata, kinc_file_reader_size(&file));
|
||||
kinc_file_reader_close(&file);
|
||||
|
||||
int samples =
|
||||
stb_vorbis_decode_memory(filedata, (int)kinc_file_reader_size(&file), &sound->format.channels, &sound->format.samples_per_second, (short **)&data);
|
||||
sound->size = samples * 2 * sound->format.channels;
|
||||
sound->format.bits_per_sample = 16;
|
||||
free(filedata);
|
||||
}
|
||||
else if (strncmp(&filename[filenameLength - 4], ".wav", 4) == 0) {
|
||||
struct WaveData wave = {0};
|
||||
{
|
||||
kinc_file_reader_t file;
|
||||
if (!kinc_file_reader_open(&file, filename, KINC_FILE_TYPE_ASSET)) {
|
||||
sound->in_use = false;
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *filedata = (uint8_t *)malloc(kinc_file_reader_size(&file));
|
||||
kinc_file_reader_read(&file, filedata, kinc_file_reader_size(&file));
|
||||
kinc_file_reader_close(&file);
|
||||
uint8_t *data = filedata;
|
||||
|
||||
checkFOURCC(&data, "RIFF");
|
||||
uint32_t filesize = kinc_read_u32le(data);
|
||||
data += 4;
|
||||
checkFOURCC(&data, "WAVE");
|
||||
while (data + 8 - filedata < (intptr_t)filesize) {
|
||||
readChunk(&data, &wave);
|
||||
}
|
||||
|
||||
free(filedata);
|
||||
}
|
||||
|
||||
sound->format.bits_per_sample = wave.bitsPerSample;
|
||||
sound->format.channels = wave.numChannels;
|
||||
sound->format.samples_per_second = wave.sampleRate;
|
||||
data = wave.data;
|
||||
sound->size = wave.dataSize;
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (sound->format.channels == 1) {
|
||||
if (sound->format.bits_per_sample == 8) {
|
||||
sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
splitMono8(data, sound->size, sound->left, sound->right);
|
||||
}
|
||||
else if (sound->format.bits_per_sample == 16) {
|
||||
sound->size /= 2;
|
||||
sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
splitMono16((int16_t *)data, sound->size, sound->left, sound->right);
|
||||
}
|
||||
else {
|
||||
kinc_affirm(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Left and right channel are in s16 audio stream, alternating.
|
||||
if (sound->format.bits_per_sample == 8) {
|
||||
sound->size /= 2;
|
||||
sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
splitStereo8(data, sound->size, sound->left, sound->right);
|
||||
}
|
||||
else if (sound->format.bits_per_sample == 16) {
|
||||
sound->size /= 4;
|
||||
sound->left = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
sound->right = (int16_t *)malloc(sound->size * sizeof(int16_t));
|
||||
splitStereo16((int16_t *)data, sound->size, sound->left, sound->right);
|
||||
}
|
||||
else {
|
||||
kinc_affirm(false);
|
||||
}
|
||||
}
|
||||
sound->sample_rate_pos = 44100 / (float)sound->format.samples_per_second;
|
||||
free(data);
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
void kinc_a1_sound_destroy(kinc_a1_sound_t *sound) {
|
||||
free(sound->left);
|
||||
free(sound->right);
|
||||
sound->left = NULL;
|
||||
sound->right = NULL;
|
||||
sound->in_use = false;
|
||||
}
|
||||
|
||||
float kinc_a1_sound_volume(kinc_a1_sound_t *sound) {
|
||||
return sound->volume;
|
||||
}
|
||||
|
||||
void kinc_a1_sound_set_volume(kinc_a1_sound_t *sound, float value) {
|
||||
sound->volume = value;
|
||||
}
|
||||
56
Kinc/Sources/kinc/audio1/sound.h
Normal file
56
Kinc/Sources/kinc/audio1/sound.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/audio2/audio.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file sound.h
|
||||
\brief Sounds are pre-decoded on load and therefore primarily useful for playing sound-effects.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_a1_sound {
|
||||
kinc_a2_buffer_format_t format;
|
||||
int16_t *left;
|
||||
int16_t *right;
|
||||
int size;
|
||||
float sample_rate_pos;
|
||||
float volume;
|
||||
bool in_use;
|
||||
} kinc_a1_sound_t;
|
||||
|
||||
/// <summary>
|
||||
/// Create a sound from a wav file.
|
||||
/// </summary>
|
||||
/// <param name="filename">Path to a wav file</param>
|
||||
/// <returns>The newly created sound</returns>
|
||||
KINC_FUNC kinc_a1_sound_t *kinc_a1_sound_create(const char *filename);
|
||||
|
||||
/// <summary>
|
||||
/// Destroy a sound.
|
||||
/// </summary>
|
||||
/// <param name="sound">The sound to destroy.</param>
|
||||
KINC_FUNC void kinc_a1_sound_destroy(kinc_a1_sound_t *sound);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current volume-multiplicator that's used when playing the sound.
|
||||
/// </summary>
|
||||
/// <param name="sound">The sound to query</param>
|
||||
/// <returns>The volume-multiplicator</returns>
|
||||
KINC_FUNC float kinc_a1_sound_volume(kinc_a1_sound_t *sound);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume-multiplicator that's used when playing the sound.
|
||||
/// </summary>
|
||||
/// <param name="sound">The sound to modify</param>
|
||||
/// <param name="value">The volume-multiplicator to set</param>
|
||||
KINC_FUNC void kinc_a1_sound_set_volume(kinc_a1_sound_t *sound, float value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
135
Kinc/Sources/kinc/audio1/soundstream.c.h
Normal file
135
Kinc/Sources/kinc/audio1/soundstream.c.h
Normal file
@ -0,0 +1,135 @@
|
||||
#include "soundstream.h"
|
||||
|
||||
#define STB_VORBIS_HEADER_ONLY
|
||||
#include <kinc/libs/stb_vorbis.c>
|
||||
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static kinc_a1_sound_stream_t streams[256];
|
||||
static int nextStream = 0;
|
||||
static uint8_t buffer[1024 * 10];
|
||||
static int bufferIndex;
|
||||
|
||||
kinc_a1_sound_stream_t *kinc_a1_sound_stream_create(const char *filename, bool looping) {
|
||||
kinc_a1_sound_stream_t *stream = &streams[nextStream];
|
||||
stream->decoded = false;
|
||||
stream->myLooping = looping;
|
||||
stream->myVolume = 1;
|
||||
stream->rateDecodedHack = false;
|
||||
stream->end = false;
|
||||
kinc_file_reader_t file;
|
||||
kinc_file_reader_open(&file, filename, KINC_FILE_TYPE_ASSET);
|
||||
stream->buffer = &buffer[bufferIndex];
|
||||
bufferIndex += (int)kinc_file_reader_size(&file);
|
||||
uint8_t *filecontent = (uint8_t *)malloc(kinc_file_reader_size(&file));
|
||||
kinc_file_reader_read(&file, filecontent, kinc_file_reader_size(&file));
|
||||
kinc_file_reader_close(&file);
|
||||
memcpy(stream->buffer, filecontent, kinc_file_reader_size(&file));
|
||||
free(filecontent);
|
||||
stream->vorbis = stb_vorbis_open_memory(buffer, (int)kinc_file_reader_size(&file), NULL, NULL);
|
||||
if (stream->vorbis != NULL) {
|
||||
stb_vorbis_info info = stb_vorbis_get_info(stream->vorbis);
|
||||
stream->chans = info.channels;
|
||||
stream->rate = info.sample_rate;
|
||||
}
|
||||
else {
|
||||
stream->chans = 2;
|
||||
stream->rate = 22050;
|
||||
}
|
||||
++nextStream;
|
||||
return stream;
|
||||
}
|
||||
|
||||
int kinc_a1_sound_stream_channels(kinc_a1_sound_stream_t *stream) {
|
||||
return stream->chans;
|
||||
}
|
||||
|
||||
int kinc_a1_sound_stream_sample_rate(kinc_a1_sound_stream_t *stream) {
|
||||
return stream->rate;
|
||||
}
|
||||
|
||||
bool kinc_a1_sound_stream_looping(kinc_a1_sound_stream_t *stream) {
|
||||
return stream->myLooping;
|
||||
}
|
||||
|
||||
void kinc_a1_sound_stream_set_looping(kinc_a1_sound_stream_t *stream, bool loop) {
|
||||
stream->myLooping = loop;
|
||||
}
|
||||
|
||||
float kinc_a1_sound_stream_volume(kinc_a1_sound_stream_t *stream) {
|
||||
return stream->myVolume;
|
||||
}
|
||||
|
||||
void kinc_a1_sound_stream_set_volume(kinc_a1_sound_stream_t *stream, float value) {
|
||||
stream->myVolume = value;
|
||||
}
|
||||
|
||||
bool kinc_a1_sound_stream_ended(kinc_a1_sound_stream_t *stream) {
|
||||
return stream->end;
|
||||
}
|
||||
|
||||
float kinc_a1_sound_stream_length(kinc_a1_sound_stream_t *stream) {
|
||||
if (stream->vorbis == NULL)
|
||||
return 0;
|
||||
return stb_vorbis_stream_length_in_seconds(stream->vorbis);
|
||||
}
|
||||
|
||||
float kinc_a1_sound_stream_position(kinc_a1_sound_stream_t *stream) {
|
||||
if (stream->vorbis == NULL)
|
||||
return 0;
|
||||
return stb_vorbis_get_sample_offset(stream->vorbis) / stb_vorbis_stream_length_in_samples(stream->vorbis) * kinc_a1_sound_stream_length(stream);
|
||||
}
|
||||
|
||||
void kinc_a1_sound_stream_reset(kinc_a1_sound_stream_t *stream) {
|
||||
if (stream->vorbis != NULL)
|
||||
stb_vorbis_seek_start(stream->vorbis);
|
||||
stream->end = false;
|
||||
stream->rateDecodedHack = false;
|
||||
stream->decoded = false;
|
||||
}
|
||||
|
||||
float kinc_a1_sound_stream_next_sample(kinc_a1_sound_stream_t *stream) {
|
||||
if (stream->vorbis == NULL)
|
||||
return 0;
|
||||
if (stream->rate == 22050) {
|
||||
if (stream->rateDecodedHack) {
|
||||
if (stream->decoded) {
|
||||
stream->decoded = false;
|
||||
return stream->samples[0];
|
||||
}
|
||||
else {
|
||||
stream->rateDecodedHack = false;
|
||||
stream->decoded = true;
|
||||
return stream->samples[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream->decoded) {
|
||||
stream->decoded = false;
|
||||
if (stream->chans == 1) {
|
||||
return stream->samples[0];
|
||||
}
|
||||
else {
|
||||
return stream->samples[1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
int read = stb_vorbis_get_samples_float_interleaved(stream->vorbis, stream->chans, &stream->samples[0], stream->chans);
|
||||
if (read == 0) {
|
||||
if (kinc_a1_sound_stream_looping(stream)) {
|
||||
stb_vorbis_seek_start(stream->vorbis);
|
||||
stb_vorbis_get_samples_float_interleaved(stream->vorbis, stream->chans, &stream->samples[0], stream->chans);
|
||||
}
|
||||
else {
|
||||
stream->end = true;
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
stream->decoded = true;
|
||||
stream->rateDecodedHack = true;
|
||||
return stream->samples[0];
|
||||
}
|
||||
}
|
||||
117
Kinc/Sources/kinc/audio1/soundstream.h
Normal file
117
Kinc/Sources/kinc/audio1/soundstream.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file soundstream.h
|
||||
\brief Sound-Streams are decoded while playing and as such are useful for large audio-files like music or speech.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct stb_vorbis;
|
||||
|
||||
typedef struct kinc_a1_sound_stream {
|
||||
struct stb_vorbis *vorbis;
|
||||
int chans;
|
||||
int rate;
|
||||
bool myLooping;
|
||||
float myVolume;
|
||||
bool decoded;
|
||||
bool rateDecodedHack;
|
||||
bool end;
|
||||
float samples[2];
|
||||
uint8_t *buffer;
|
||||
} kinc_a1_sound_stream_t;
|
||||
|
||||
/// <summary>
|
||||
/// Create a sound-stream from a wav file.
|
||||
/// </summary>
|
||||
/// <param name="filename">A path to a wav file</param>
|
||||
/// <param name="looping">Defines whether the stream will be looped automatically</param>
|
||||
/// <returns>The newly created sound-stream</returns>
|
||||
KINC_FUNC kinc_a1_sound_stream_t *kinc_a1_sound_stream_create(const char *filename, bool looping);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next audio-sample in the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to extract the sample from</param>
|
||||
/// <returns>The next sample</returns>
|
||||
KINC_FUNC float kinc_a1_sound_stream_next_sample(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of audio-channels the stream uses.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to extract the number of channels from</param>
|
||||
/// <returns>The number of audio-channels</returns>
|
||||
KINC_FUNC int kinc_a1_sound_stream_channels(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sample-rate used by the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to extract the sample-rate from</param>
|
||||
/// <returns>The sample-rate of the stream</returns>
|
||||
KINC_FUNC int kinc_a1_sound_stream_sample_rate(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the stream loops automatically.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to extract the looping-information from</param>
|
||||
/// <returns>Whether the stream loops</returns>
|
||||
KINC_FUNC bool kinc_a1_sound_stream_looping(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Changes whether the stream is looped automatically.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to change</param>
|
||||
/// <param name="loop">The new loop value to set</param>
|
||||
KINC_FUNC void kinc_a1_sound_stream_set_looping(kinc_a1_sound_stream_t *stream, bool loop);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the stream finished playing.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to query</param>
|
||||
/// <returns>Whether the stream finished playing</returns>
|
||||
KINC_FUNC bool kinc_a1_sound_stream_ended(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to query</param>
|
||||
/// <returns>The length of the stream in seconds</returns>
|
||||
KINC_FUNC float kinc_a1_sound_stream_length(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current playing-position of the stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to query</param>
|
||||
/// <returns>The current playing-position in seconds</returns>
|
||||
KINC_FUNC float kinc_a1_sound_stream_position(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the stream to its start-position.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to change</param>
|
||||
KINC_FUNC void kinc_a1_sound_stream_reset(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the stream's volume-multiplicator.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to query</param>
|
||||
/// <returns>The volume-multiplicator</returns>
|
||||
KINC_FUNC float kinc_a1_sound_stream_volume(kinc_a1_sound_stream_t *stream);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the stream's volume-multiplicator.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to change</param>
|
||||
/// <param name="value">The volume-multiplicator</param>
|
||||
KINC_FUNC void kinc_a1_sound_stream_set_volume(kinc_a1_sound_stream_t *stream, float value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
3
Kinc/Sources/kinc/audio2/audio.c
Normal file
3
Kinc/Sources/kinc/audio2/audio.c
Normal file
@ -0,0 +1,3 @@
|
||||
#define KINC_IMPLEMENTATION_AUDIO2
|
||||
|
||||
#include "audio.h"
|
||||
77
Kinc/Sources/kinc/audio2/audio.h
Normal file
77
Kinc/Sources/kinc/audio2/audio.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file audio.h
|
||||
\brief Audio2 is a low-level audio-API that allows you to directly provide a stream of audio-samples.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_a2_buffer_format {
|
||||
int channels;
|
||||
int samples_per_second;
|
||||
int bits_per_sample;
|
||||
} kinc_a2_buffer_format_t;
|
||||
|
||||
typedef struct kinc_a2_buffer {
|
||||
kinc_a2_buffer_format_t format;
|
||||
uint8_t *data;
|
||||
int data_size;
|
||||
int read_location;
|
||||
int write_location;
|
||||
} kinc_a2_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Audio2-API.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_a2_init(void);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the callback that's used to provide audio-samples. This is the primary method of operation for Audio2. The callback is expected to write the requested
|
||||
/// number of samples into the ring-buffer. The callback is typically called from the system's audio-thread to minimize audio-latency.
|
||||
/// </summary>
|
||||
/// <param name="kinc_a2_audio_callback">The callback to set</param>
|
||||
KINC_FUNC void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples));
|
||||
|
||||
/// <summary>
|
||||
/// Sets a callback that's called when the system's sample-rate changes.
|
||||
/// </summary>
|
||||
/// <param name="kinc_a2_sample_rate_callback">The callback to set</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_a2_set_sample_rate_callback(void (*kinc_a2_sample_rate_callback)(void));
|
||||
|
||||
/// <summary>
|
||||
/// The current sample-rate of the system.
|
||||
/// </summary>
|
||||
KINC_FUNC extern int kinc_a2_samples_per_second;
|
||||
|
||||
/// <summary>
|
||||
/// kinc_a2_update should be called every frame. It is required by some systems to pump their audio-loops but on most systems it is a no-op.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_a2_update(void);
|
||||
|
||||
/// <summary>
|
||||
/// Shuts down the Audio2-API.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_a2_shutdown(void);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_AUDIO2
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
int kinc_a2_samples_per_second = 44100;
|
||||
|
||||
// BACKENDS-PLACEHOLDER
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
46
Kinc/Sources/kinc/color.h
Normal file
46
Kinc/Sources/kinc/color.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file color.h
|
||||
\brief Provides some utility functionality for handling 32 bit ARGB color values.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Splits up an 32 bit ARGB color value into its components.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_color_components(uint32_t color, float *red, float *green, float *blue, float *alpha);
|
||||
|
||||
#define KINC_COLOR_BLACK 0xff000000
|
||||
#define KINC_COLOR_WHITE 0xffffffff
|
||||
#define KINC_COLOR_RED 0xffff0000
|
||||
#define KINC_COLOR_BLUE 0xff0000ff
|
||||
#define KINC_COLOR_GREEN 0xff00ff00
|
||||
#define KINC_COLOR_MAGENTA 0xffff00ff
|
||||
#define KINC_COLOR_YELLOW 0xffffff00
|
||||
#define KINC_COLOR_CYAN 0xff00ffff
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
void kinc_color_components(uint32_t color, float *red, float *green, float *blue, float *alpha) {
|
||||
*alpha = ((color & 0xff000000) >> 24) / 255.0f;
|
||||
*red = ((color & 0x00ff0000) >> 16) / 255.0f;
|
||||
*green = ((color & 0x0000ff00) >> 8) / 255.0f;
|
||||
*blue = (color & 0x000000ff) / 255.0f;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
86
Kinc/Sources/kinc/display.h
Normal file
86
Kinc/Sources/kinc/display.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file display.h
|
||||
\brief Provides information for the active displays.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_display_mode {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int pixels_per_inch;
|
||||
int frequency;
|
||||
int bits_per_pixel;
|
||||
} kinc_display_mode_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allows retrieval of display values prior to the kinc_init call.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_display_init(void);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the index of the primary display.
|
||||
/// </summary>
|
||||
/// <returns>The index of the primary display</returns>
|
||||
KINC_FUNC int kinc_primary_display(void);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the number of displays connected to the system.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All indices from 0 to kinc_count_displays() - 1 are legal display indices.
|
||||
/// </remarks>
|
||||
/// <returns>The number of displays connected to the system</returns>
|
||||
KINC_FUNC int kinc_count_displays(void);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the display index points to an available display.
|
||||
/// </summary>
|
||||
/// <param name="display_index">Index of the display to check</param>
|
||||
/// <returns>
|
||||
/// Returns true if the index points to an available display,
|
||||
/// false otherwise
|
||||
/// </returns>
|
||||
KINC_FUNC bool kinc_display_available(int display_index);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the system name of a display.
|
||||
/// </summary>
|
||||
/// <param name="display_index">Index of the display to retrieve the name from</param>
|
||||
/// <returns>The system name of the display</returns>
|
||||
KINC_FUNC const char *kinc_display_name(int display_index);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the current mode of a display.
|
||||
/// </summary>
|
||||
/// <param name="display_index">Index of the display to retrieve the mode from</param>
|
||||
/// <returns>The current display mode</returns>
|
||||
KINC_FUNC kinc_display_mode_t kinc_display_current_mode(int display_index);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the number of available modes of a display.
|
||||
/// </summary>
|
||||
/// <param name="display_index">Index of the display to retrieve the modes count from</param>
|
||||
/// <returns>The number of available modes of the display</returns>
|
||||
KINC_FUNC int kinc_display_count_available_modes(int display_index);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a specific mode of a display.
|
||||
/// </summary>
|
||||
/// <param name="display_index">Index of the display to retrieve the mode from</param>
|
||||
/// <param name="mode_index">Index of the mode to retrieve</param>
|
||||
/// <returns>The display mode</returns>
|
||||
KINC_FUNC kinc_display_mode_t kinc_display_available_mode(int display_index, int mode_index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
200
Kinc/Sources/kinc/error.h
Normal file
200
Kinc/Sources/kinc/error.h
Normal file
@ -0,0 +1,200 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*! \file error.h
|
||||
\brief Contains functionality to stop the program in case of an error and create a user-visible error message.
|
||||
|
||||
The affirm and error functions print an error message and then exit the program. Error messages can be made
|
||||
visible to the user (unless a console window is active this is only implemented for Windows).
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Exits the program when a condition is untrue and shows
|
||||
/// a generic error message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is an alternative to assert which also persists in release
|
||||
/// builds. Use this instead of assert in situations where you want
|
||||
/// your users to see what's going wrong.
|
||||
/// This uses Kinc's log and error functionality to make errors
|
||||
/// visible.
|
||||
/// </remarks>
|
||||
/// <param name="condition">
|
||||
/// Exits the program if condition is false,
|
||||
/// otherwise does nothing.
|
||||
/// </param>
|
||||
KINC_FUNC void kinc_affirm(bool condition);
|
||||
|
||||
/// <summary>
|
||||
/// Exits the program when a condition is untrue and shows
|
||||
/// a provided error message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is equivalent to kinc_affirm() but uses the provided message
|
||||
/// instead of a generic one.
|
||||
/// </remarks>
|
||||
/// <param name="condition">
|
||||
/// Exits the program if condition is false,
|
||||
/// otherwise does nothing.
|
||||
/// </param>
|
||||
/// <param name="format">
|
||||
/// The parameter is equivalent to the first printf parameter.
|
||||
/// </param>
|
||||
/// <param name="...">
|
||||
/// The parameter is equivalent to the second printf parameter.
|
||||
/// </param>
|
||||
KINC_FUNC void kinc_affirm_message(bool condition, const char *format, ...);
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to kinc_affirm_message but uses a va_list parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You will need this if you want to provide the parameters using va_start/va_end.
|
||||
/// </remarks>
|
||||
/// <param name="condition">
|
||||
/// Exits the program if condition is false,
|
||||
/// otherwise does nothing.
|
||||
/// </param>
|
||||
/// <param name="format">
|
||||
/// The parameter is equivalent to the first vprintf parameter.
|
||||
/// </param>
|
||||
/// <param name="...">
|
||||
/// The parameter is equivalent to the second vprintf parameter.
|
||||
/// </param>
|
||||
KINC_FUNC void kinc_affirm_args(bool condition, const char *format, va_list args);
|
||||
|
||||
/// <summary>
|
||||
/// Exits the program and shows a generic error message
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Mainly this just calls exit(EXIT_FAILURE) but will also use
|
||||
/// Kore's log function and on Windows show an error message box.
|
||||
/// </remarks>
|
||||
KINC_FUNC void kinc_error(void);
|
||||
|
||||
/// <summary>
|
||||
/// Exits the program and shows a provided error message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is equivalent to kinc_error() but uses the provided message
|
||||
/// instead of a generic one.
|
||||
/// </remarks>
|
||||
/// <param name="format">
|
||||
/// The parameter is equivalent to the first printf parameter.
|
||||
/// </param>
|
||||
/// <param name="...">
|
||||
/// The parameter is equivalent to the second printf parameter.
|
||||
/// </param>
|
||||
KINC_FUNC void kinc_error_message(const char *format, ...);
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to kinc_error_message but uses a va_list parameter.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You will need this if you want to provide the parameters using va_start/va_end.
|
||||
/// </remarks>
|
||||
/// <param name="format">
|
||||
/// The parameter is equivalent to the first vprintf parameter.
|
||||
/// </param>
|
||||
/// <param name="...">
|
||||
/// The parameter is equivalent to the second vprintf parameter.
|
||||
/// </param>
|
||||
KINC_FUNC void kinc_error_args(const char *format, va_list args);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#ifndef KINC_IMPLEMENTATION_ROOT
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#endif
|
||||
#include <kinc/log.h>
|
||||
#ifndef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
|
||||
#include <kinc/backend/MiniWindows.h>
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#endif
|
||||
|
||||
void kinc_affirm(bool condition) {
|
||||
if (!condition) {
|
||||
kinc_error();
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_affirm_message(bool condition, const char *format, ...) {
|
||||
if (!condition) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
kinc_error_args(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_affirm_args(bool condition, const char *format, va_list args) {
|
||||
if (!condition) {
|
||||
kinc_error_args(format, args);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_error(void) {
|
||||
kinc_error_message("Unknown error");
|
||||
}
|
||||
|
||||
void kinc_error_message(const char *format, ...) {
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
kinc_log_args(KINC_LOG_LEVEL_ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
wchar_t buffer[4096];
|
||||
kinc_microsoft_format(format, args, buffer);
|
||||
MessageBoxW(NULL, buffer, L"Error", 0);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef KINC_NO_CLIB
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_error_args(const char *format, va_list args) {
|
||||
kinc_log_args(KINC_LOG_LEVEL_ERROR, format, args);
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
wchar_t buffer[4096];
|
||||
kinc_microsoft_format(format, args, buffer);
|
||||
MessageBoxW(NULL, buffer, L"Error", 0);
|
||||
#endif
|
||||
|
||||
#ifndef KINC_NO_CLIB
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
156
Kinc/Sources/kinc/global.h
Normal file
156
Kinc/Sources/kinc/global.h
Normal file
@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
|
||||
/*! \file global.h
|
||||
\brief Provides basic functionality that's used all over the place. There's usually no need to manually include this.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(KORE_PPC)
|
||||
#define KORE_BIG_ENDIAN
|
||||
#else
|
||||
#define KORE_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#if defined(KORE_PPC)
|
||||
#define KINC_BIG_ENDIAN
|
||||
#else
|
||||
#define KINC_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define KINC_INLINE static __forceinline
|
||||
#else
|
||||
#define KINC_INLINE static __attribute__((always_inline)) inline
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define KINC_MICROSOFT
|
||||
#define KORE_MICROSOFT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(KORE_WINDOWSAPP)
|
||||
|
||||
#define KINC_WINDOWSAPP
|
||||
#define KINC_WINRT
|
||||
#define KORE_WINRT
|
||||
|
||||
#else
|
||||
|
||||
#ifndef KORE_CONSOLE
|
||||
#define KINC_WINDOWS
|
||||
#define KORE_WINDOWS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
#if defined(KORE_TVOS)
|
||||
#define KINC_TVOS
|
||||
#else
|
||||
#define KINC_IOS
|
||||
#define KORE_IOS
|
||||
#endif
|
||||
|
||||
#define KINC_APPLE_SOC
|
||||
|
||||
#else
|
||||
|
||||
#define KINC_MACOS
|
||||
#define KORE_MACOS
|
||||
|
||||
#if defined(__arm64__)
|
||||
#define KINC_APPLE_SOC
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define KINC_POSIX
|
||||
#define KORE_POSIX
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
#if !defined(KORE_ANDROID)
|
||||
#define KINC_LINUX
|
||||
#define KORE_LINUX
|
||||
#endif
|
||||
|
||||
#define KINC_POSIX
|
||||
#define KORE_POSIX
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
#if defined(KINC_DYNAMIC)
|
||||
#define KINC_FUNC __declspec(dllimport)
|
||||
#elif defined(KINC_DYNAMIC_COMPILE)
|
||||
#define KINC_FUNC __declspec(dllexport)
|
||||
#else
|
||||
#define KINC_FUNC
|
||||
#endif
|
||||
#else
|
||||
#define KINC_FUNC
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace Kore {
|
||||
typedef unsigned char u8; // 1 Byte
|
||||
typedef unsigned short u16; // 2 Byte
|
||||
typedef unsigned int u32; // 4 Byte
|
||||
|
||||
#if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
|
||||
#define KORE_64
|
||||
#endif
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
typedef unsigned __int64 u64; // 8 Byte
|
||||
#else
|
||||
typedef unsigned long long u64;
|
||||
#endif
|
||||
typedef char s8; // 1 Byte
|
||||
typedef short s16; // 2 Byte
|
||||
typedef int s32; // 4 Byte
|
||||
#ifdef KORE_WINDOWS
|
||||
typedef __int64 s64; // 8 Byte
|
||||
#else
|
||||
typedef long long s64;
|
||||
#endif
|
||||
|
||||
typedef u32 uint; // 4 Byte
|
||||
typedef s32 sint; // 4 Byte
|
||||
|
||||
#ifdef KORE_64
|
||||
typedef s64 spint;
|
||||
typedef u64 upint;
|
||||
#else
|
||||
typedef s32 spint;
|
||||
typedef u32 upint;
|
||||
#endif
|
||||
}
|
||||
|
||||
// pseudo C++11
|
||||
#if !defined(_MSC_VER) && __cplusplus <= 199711L
|
||||
#define nullptr 0
|
||||
#define override
|
||||
#endif
|
||||
|
||||
#define Noexcept throw()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int kickstart(int argc, char **argv);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
175
Kinc/Sources/kinc/graphics1/graphics.c
Normal file
175
Kinc/Sources/kinc/graphics1/graphics.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#ifdef KINC_KONG
|
||||
#include <kong.h>
|
||||
#endif
|
||||
|
||||
#ifndef KINC_KONG
|
||||
static kinc_g4_shader_t vertexShader;
|
||||
static kinc_g4_shader_t fragmentShader;
|
||||
static kinc_g4_pipeline_t pipeline;
|
||||
static kinc_g4_texture_unit_t tex;
|
||||
#endif
|
||||
static kinc_g4_vertex_buffer_t vb;
|
||||
static kinc_g4_index_buffer_t ib;
|
||||
static kinc_g4_texture_t texture;
|
||||
|
||||
uint32_t *kinc_internal_g1_image;
|
||||
int kinc_internal_g1_w, kinc_internal_g1_h, kinc_internal_g1_tex_width;
|
||||
|
||||
void kinc_g1_begin(void) {
|
||||
kinc_g4_begin(0);
|
||||
kinc_internal_g1_image = (uint32_t *)kinc_g4_texture_lock(&texture);
|
||||
}
|
||||
|
||||
void kinc_g1_end(void) {
|
||||
kinc_internal_g1_image = NULL;
|
||||
kinc_g4_texture_unlock(&texture);
|
||||
|
||||
kinc_g4_clear(KINC_G4_CLEAR_COLOR, 0xff000000, 0.0f, 0);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
kinc_g4_set_pipeline(&kinc_g1_pipeline);
|
||||
#else
|
||||
kinc_g4_set_pipeline(&pipeline);
|
||||
#endif
|
||||
|
||||
#ifndef KINC_KONG
|
||||
kinc_g4_set_texture(tex, &texture);
|
||||
#endif
|
||||
kinc_g4_set_vertex_buffer(&vb);
|
||||
kinc_g4_set_index_buffer(&ib);
|
||||
kinc_g4_draw_indexed_vertices();
|
||||
|
||||
kinc_g4_end(0);
|
||||
kinc_g4_swap_buffers();
|
||||
}
|
||||
|
||||
void kinc_g1_init(int width, int height) {
|
||||
kinc_internal_g1_w = width;
|
||||
kinc_internal_g1_h = height;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
{
|
||||
kinc_file_reader_t file;
|
||||
kinc_file_reader_open(&file, "g1.vert", KINC_FILE_TYPE_ASSET);
|
||||
void *data = malloc(kinc_file_reader_size(&file));
|
||||
kinc_file_reader_read(&file, data, kinc_file_reader_size(&file));
|
||||
kinc_file_reader_close(&file);
|
||||
kinc_g4_shader_init(&vertexShader, data, kinc_file_reader_size(&file), KINC_G4_SHADER_TYPE_VERTEX);
|
||||
free(data);
|
||||
}
|
||||
|
||||
{
|
||||
kinc_file_reader_t file;
|
||||
kinc_file_reader_open(&file, "g1.frag", KINC_FILE_TYPE_ASSET);
|
||||
void *data = malloc(kinc_file_reader_size(&file));
|
||||
kinc_file_reader_read(&file, data, kinc_file_reader_size(&file));
|
||||
kinc_file_reader_close(&file);
|
||||
kinc_g4_shader_init(&fragmentShader, data, kinc_file_reader_size(&file), KINC_G4_SHADER_TYPE_FRAGMENT);
|
||||
free(data);
|
||||
}
|
||||
|
||||
kinc_g4_vertex_structure_t structure;
|
||||
kinc_g4_vertex_structure_init(&structure);
|
||||
kinc_g4_vertex_structure_add(&structure, "pos", KINC_G4_VERTEX_DATA_F32_3X);
|
||||
kinc_g4_vertex_structure_add(&structure, "tex", KINC_G4_VERTEX_DATA_F32_2X);
|
||||
kinc_g4_pipeline_init(&pipeline);
|
||||
pipeline.input_layout[0] = &structure;
|
||||
pipeline.input_layout[1] = NULL;
|
||||
pipeline.vertex_shader = &vertexShader;
|
||||
pipeline.fragment_shader = &fragmentShader;
|
||||
kinc_g4_pipeline_compile(&pipeline);
|
||||
|
||||
tex = kinc_g4_pipeline_get_texture_unit(&pipeline, "texy");
|
||||
#endif
|
||||
|
||||
kinc_g4_texture_init(&texture, width, height, KINC_IMAGE_FORMAT_RGBA32);
|
||||
kinc_internal_g1_tex_width = texture.tex_width;
|
||||
|
||||
kinc_internal_g1_image = (uint32_t *)kinc_g4_texture_lock(&texture);
|
||||
int stride = kinc_g4_texture_stride(&texture) / 4;
|
||||
for (int y = 0; y < texture.tex_height; ++y) {
|
||||
for (int x = 0; x < texture.tex_width; ++x) {
|
||||
kinc_internal_g1_image[y * stride + x] = 0;
|
||||
}
|
||||
}
|
||||
kinc_g4_texture_unlock(&texture);
|
||||
|
||||
// Correct for the difference between the texture's desired size and the actual power of 2 size
|
||||
float xAspect = (float)width / texture.tex_width;
|
||||
float yAspect = (float)height / texture.tex_height;
|
||||
|
||||
#ifdef KINC_KONG
|
||||
kinc_g4_vertex_buffer_init(&vb, 4, &kinc_g1_vertex_in_structure, KINC_G4_USAGE_STATIC, 0);
|
||||
#else
|
||||
kinc_g4_vertex_buffer_init(&vb, 4, &structure, KINC_G4_USAGE_STATIC, 0);
|
||||
#endif
|
||||
float *v = kinc_g4_vertex_buffer_lock_all(&vb);
|
||||
{
|
||||
int i = 0;
|
||||
v[i++] = -1;
|
||||
v[i++] = 1;
|
||||
v[i++] = 0.5;
|
||||
v[i++] = 0;
|
||||
v[i++] = 0;
|
||||
v[i++] = 1;
|
||||
v[i++] = 1;
|
||||
v[i++] = 0.5;
|
||||
v[i++] = xAspect;
|
||||
v[i++] = 0;
|
||||
v[i++] = 1;
|
||||
v[i++] = -1;
|
||||
v[i++] = 0.5;
|
||||
v[i++] = xAspect;
|
||||
v[i++] = yAspect;
|
||||
v[i++] = -1;
|
||||
v[i++] = -1;
|
||||
v[i++] = 0.5;
|
||||
v[i++] = 0;
|
||||
v[i++] = yAspect;
|
||||
}
|
||||
kinc_g4_vertex_buffer_unlock_all(&vb);
|
||||
|
||||
kinc_g4_index_buffer_init(&ib, 6, KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC);
|
||||
uint32_t *ii = (uint32_t *)kinc_g4_index_buffer_lock_all(&ib);
|
||||
{
|
||||
int i = 0;
|
||||
ii[i++] = 0;
|
||||
ii[i++] = 1;
|
||||
ii[i++] = 3;
|
||||
ii[i++] = 1;
|
||||
ii[i++] = 2;
|
||||
ii[i++] = 3;
|
||||
}
|
||||
kinc_g4_index_buffer_unlock_all(&ib);
|
||||
}
|
||||
|
||||
#if defined(KINC_DYNAMIC_COMPILE) || defined(KINC_DYNAMIC)
|
||||
|
||||
void kinc_g1_set_pixel(int x, int y, float red, float green, float blue) {
|
||||
if (x < 0 || x >= kinc_internal_g1_w || y < 0 || y >= kinc_internal_g1_h)
|
||||
return;
|
||||
int r = (int)(red * 255);
|
||||
int g = (int)(green * 255);
|
||||
int b = (int)(blue * 255);
|
||||
kinc_internal_g1_image[y * kinc_internal_g1_tex_width + x] = 0xff << 24 | b << 16 | g << 8 | r;
|
||||
}
|
||||
|
||||
int kinc_g1_width() {
|
||||
return kinc_internal_g1_w;
|
||||
}
|
||||
|
||||
int kinc_g1_height() {
|
||||
return kinc_internal_g1_h;
|
||||
}
|
||||
|
||||
#endif
|
||||
86
Kinc/Sources/kinc/graphics1/graphics.h
Normal file
86
Kinc/Sources/kinc/graphics1/graphics.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/color.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*! \file graphics.h
|
||||
\brief Supports a very basic pixel-setting API.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the G1-API.
|
||||
/// </summary>
|
||||
/// <param name="width">The width to be used by the G1-API - typically the window-width</param>
|
||||
/// <param name="height">The height to be used by the G1-API - typically the window-height</param>
|
||||
KINC_FUNC void kinc_g1_init(int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Typically called once per frame before other G1-functions are called.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g1_begin(void);
|
||||
|
||||
/// <summary>
|
||||
/// Typically called once per frame after all G1-drawing is finished. This also swaps the framebuffers
|
||||
/// so an equivalent call to kinc_g4_swap_buffers is not needed.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g1_end(void);
|
||||
|
||||
extern uint32_t *kinc_internal_g1_image;
|
||||
extern int kinc_internal_g1_w, kinc_internal_g1_h, kinc_internal_g1_tex_width;
|
||||
|
||||
#if defined(KINC_DYNAMIC_COMPILE) || defined(KINC_DYNAMIC) || defined(KINC_DOCS)
|
||||
|
||||
/// <summary>
|
||||
/// Sets a single pixel to a color.
|
||||
/// </summary>
|
||||
/// <param name="x">The x-component of the pixel-coordinate to set</param>
|
||||
/// <param name="y">The y-component of the pixel-coordinate to set</param>
|
||||
/// <param name="red">The red-component between 0 and 1</param>
|
||||
/// <param name="green">The green-component between 0 and 1</param>
|
||||
/// <param name="blue">The blue-component between 0 and 1</param>
|
||||
KINC_FUNC void kinc_g1_set_pixel(int x, int y, float red, float green, float blue);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the width used by G1.
|
||||
/// </summary>
|
||||
/// <returns>The width</returns>
|
||||
KINC_FUNC int kinc_g1_width(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the height used by G1.
|
||||
/// </summary>
|
||||
/// <returns>The height</returns>
|
||||
KINC_FUNC int kinc_g1_height(void);
|
||||
|
||||
#else
|
||||
|
||||
// implementation moved to the header to allow easy inlining
|
||||
|
||||
static inline void kinc_g1_set_pixel(int x, int y, float red, float green, float blue) {
|
||||
assert(x >= 0 && x < kinc_internal_g1_w && y >= 0 && y < kinc_internal_g1_h);
|
||||
int r = (int)(red * 255);
|
||||
int g = (int)(green * 255);
|
||||
int b = (int)(blue * 255);
|
||||
kinc_internal_g1_image[y * kinc_internal_g1_tex_width + x] = 0xff << 24 | b << 16 | g << 8 | r;
|
||||
}
|
||||
|
||||
static inline int kinc_g1_width(void) {
|
||||
return kinc_internal_g1_w;
|
||||
}
|
||||
|
||||
static inline int kinc_g1_height(void) {
|
||||
return kinc_internal_g1_h;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
26
Kinc/Sources/kinc/graphics2/graphics.h
Normal file
26
Kinc/Sources/kinc/graphics2/graphics.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
/*! \file graphics.h
|
||||
\brief This is still in progress, please don't use it.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void kinc_g2_init(int screen_width, int screen_height);
|
||||
void kinc_g2_begin(void);
|
||||
void kinc_g2_end(void);
|
||||
void kinc_g2_clear(float r, float g, float b);
|
||||
void kinc_g2_draw_image(kinc_image_t *img, float x, float y);
|
||||
// void drawScaledSubImage(Graphics4::Texture *img, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh);
|
||||
void kinc_g2_set_rotation(float angle, float centerx, float centery);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
44
Kinc/Sources/kinc/graphics2/graphics_kore.cpp
Normal file
44
Kinc/Sources/kinc/graphics2/graphics_kore.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <kinc/graphics1/graphics.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if 0
|
||||
#include <Kore/Graphics2/Graphics.h>
|
||||
|
||||
static Kore::Graphics2::Graphics2 *kinc_kore_g2;
|
||||
|
||||
static kinc_matrix3x3_t transformation;
|
||||
|
||||
static Kore::Graphics4::Texture *tex;
|
||||
|
||||
void kinc_g2_init(int screen_width, int screen_height) {
|
||||
tex = new Kore::Graphics4::Texture(32, 32, Kore::Graphics1::Image::RGBA32);
|
||||
kinc_kore_g2 = new Kore::Graphics2::Graphics2(screen_width, screen_height);
|
||||
}
|
||||
|
||||
void kinc_g2_begin(void) {
|
||||
kinc_kore_g2->begin();
|
||||
}
|
||||
|
||||
void kinc_g2_end(void) {
|
||||
kinc_kore_g2->end();
|
||||
}
|
||||
|
||||
void kinc_g2_draw_image(kinc_g4_texture_t *img, float x, float y) {
|
||||
tex->kincTexture = *img;
|
||||
tex->width = img->tex_width;
|
||||
tex->height = img->tex_height;
|
||||
tex->texWidth = img->tex_width;
|
||||
tex->texHeight = img->tex_height;
|
||||
kinc_kore_g2->drawImage(tex, x, y);
|
||||
}
|
||||
|
||||
void kinc_g2_set_rotation(float angle, float centerx, float centery) {
|
||||
kinc_kore_g2->transformation = (Kore::mat3::Translation(centerx, centery) * Kore::mat3::RotationZ(angle)) * Kore::mat3::Translation(-centerx, -centery);
|
||||
}
|
||||
#endif
|
||||
285
Kinc/Sources/kinc/graphics2/graphics_soft.c
Normal file
285
Kinc/Sources/kinc/graphics2/graphics_soft.c
Normal file
@ -0,0 +1,285 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <kinc/graphics1/graphics.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static kinc_matrix3x3_t transform;
|
||||
|
||||
void kinc_g2_init(int screen_width, int screen_height) {
|
||||
kinc_g1_init(screen_width, screen_height);
|
||||
transform = kinc_matrix3x3_identity();
|
||||
}
|
||||
|
||||
void kinc_g2_begin(void) {
|
||||
kinc_g1_begin();
|
||||
}
|
||||
|
||||
void kinc_g2_end(void) {
|
||||
kinc_g1_end();
|
||||
}
|
||||
|
||||
void kinc_g2_clear(float r, float g, float b) {
|
||||
memset(kinc_internal_g1_image, 0, kinc_internal_g1_tex_width * kinc_internal_g1_h * 4);
|
||||
}
|
||||
|
||||
/*void kinc_g2_draw_image(kinc_image_t *img, float x, float y) {
|
||||
int xi = (int)kinc_round(x);
|
||||
int yi = (int)kinc_round(y);
|
||||
uint32_t *data = (uint32_t *)img->data;
|
||||
|
||||
for (int yy = yi; yy < yi + img->height; ++yy) {
|
||||
for (int xx = xi; xx < xi + img->width; ++xx) {
|
||||
uint32_t pixel = data[(yy - yi) * img->width + (xx - xi)];
|
||||
uint32_t alpha = pixel >> 24;
|
||||
uint32_t blue = (pixel >> 16) & 0xff;
|
||||
uint32_t green = (pixel >> 8) & 0xff;
|
||||
uint32_t red = pixel & 0xff;
|
||||
|
||||
float rf = red / 255.0f;
|
||||
float gf = green / 255.0f;
|
||||
float bf = blue / 255.0f;
|
||||
|
||||
if (alpha == 0) {
|
||||
// nothing
|
||||
}
|
||||
else if (alpha == 255) {
|
||||
kinc_g1_set_pixel(xx, yy, rf, gf, bf);
|
||||
}
|
||||
else {
|
||||
float a = alpha / 255.0f;
|
||||
uint32_t old = kinc_internal_g1_image[(yy - yi) * kinc_internal_g1_tex_width + (xx - xi)];
|
||||
float oldblue = ((old >> 16) & 0xff) / 255.0f;
|
||||
float oldgreen = ((old >> 8) & 0xff) / 255.0f;
|
||||
float oldred = (old & 0xff) / 255.0f;
|
||||
|
||||
kinc_g1_set_pixel(xx, yy, rf * a + oldred * (1.0f - a), gf * a + oldgreen * (1.0f - a), bf * a + oldblue * (1.0f - a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
static void draw_pixel_point(kinc_image_t *img, int frame_x, int frame_y, float u, float v) {
|
||||
// int xi = (int)kinc_round(x);
|
||||
// int yi = (int)kinc_round(y);
|
||||
uint32_t *data = (uint32_t *)img->data;
|
||||
|
||||
int image_x = (int)kinc_round(u * (img->width - 1));
|
||||
int image_y = (int)kinc_round(v * (img->height - 1));
|
||||
|
||||
uint32_t pixel = data[image_y * img->width + image_x];
|
||||
uint32_t alpha = pixel >> 24;
|
||||
uint32_t blue = (pixel >> 16) & 0xff;
|
||||
uint32_t green = (pixel >> 8) & 0xff;
|
||||
uint32_t red = pixel & 0xff;
|
||||
|
||||
float rf = red / 255.0f;
|
||||
float gf = green / 255.0f;
|
||||
float bf = blue / 255.0f;
|
||||
|
||||
if (alpha == 0) {
|
||||
// nothing
|
||||
}
|
||||
else if (alpha == 255) {
|
||||
kinc_g1_set_pixel(frame_x, frame_y, rf, gf, bf);
|
||||
}
|
||||
else {
|
||||
float a = alpha / 255.0f;
|
||||
uint32_t old = kinc_internal_g1_image[frame_y * kinc_internal_g1_tex_width + frame_x];
|
||||
float oldblue = ((old >> 16) & 0xff) / 255.0f;
|
||||
float oldgreen = ((old >> 8) & 0xff) / 255.0f;
|
||||
float oldred = (old & 0xff) / 255.0f;
|
||||
|
||||
kinc_g1_set_pixel(frame_x, frame_y, rf * a + oldred * (1.0f - a), gf * a + oldgreen * (1.0f - a), bf * a + oldblue * (1.0f - a));
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void draw_pixel_bilinear(kinc_image_t *img, int frame_x, int frame_y, float u, float v) {
|
||||
// int xi = (int)kinc_round(x);
|
||||
// int yi = (int)kinc_round(y);
|
||||
uint32_t *data = (uint32_t *)img->data;
|
||||
|
||||
int image_x0 = (int)kinc_floor(u * (img->width - 1));
|
||||
int image_y0 = (int)kinc_floor(v * (img->height - 1));
|
||||
int image_x1 = kinc_mini(image_x0 + 1, img->width - 1);
|
||||
int image_y1 = kinc_mini(image_y0 + 1, img->height - 1);
|
||||
|
||||
uint32_t pixel00 = data[image_y0 * img->width + image_x0];
|
||||
uint32_t pixel01 = data[image_y1 * img->width + image_x0];
|
||||
uint32_t pixel10 = data[image_y0 * img->width + image_x1];
|
||||
uint32_t pixel11 = data[image_y1 * img->width + image_x1];
|
||||
|
||||
float alpha00 = (pixel00 >> 24) / 255.0f;
|
||||
float blue00 = ((pixel00 >> 16) & 0xff) / 255.0f;
|
||||
float green00 = ((pixel00 >> 8) & 0xff) / 255.0f;
|
||||
float red00 = (pixel00 & 0xff) / 255.0f;
|
||||
|
||||
float alpha01 = (pixel01 >> 24) / 255.0f;
|
||||
float blue01 = ((pixel01 >> 16) & 0xff) / 255.0f;
|
||||
float green01 = ((pixel01 >> 8) & 0xff) / 255.0f;
|
||||
float red01 = (pixel01 & 0xff) / 255.0f;
|
||||
|
||||
float alpha10 = (pixel10 >> 24) / 255.0f;
|
||||
float blue10 = ((pixel10 >> 16) & 0xff) / 255.0f;
|
||||
float green10 = ((pixel10 >> 8) & 0xff) / 255.0f;
|
||||
float red10 = (pixel10 & 0xff) / 255.0f;
|
||||
|
||||
float alpha11 = (pixel11 >> 24) / 255.0f;
|
||||
float blue11 = ((pixel11 >> 16) & 0xff) / 255.0f;
|
||||
float green11 = ((pixel11 >> 8) & 0xff) / 255.0f;
|
||||
float red11 = (pixel11 & 0xff) / 255.0f;
|
||||
|
||||
float xx = (u * (img->width - 1)) - image_x0;
|
||||
|
||||
float alpha0 = alpha00 * xx + alpha10 * (1.0f - xx);
|
||||
float blue0 = blue00 * xx + blue10 * (1.0f - xx);
|
||||
float green0 = green00 * xx + green10 * (1.0f - xx);
|
||||
float red0 = red00 * xx + red10 * (1.0f - xx);
|
||||
|
||||
float alpha1 = alpha01 * xx + alpha11 * (1.0f - xx);
|
||||
float blue1 = blue01 * xx + blue11 * (1.0f - xx);
|
||||
float green1 = green01 * xx + green11 * (1.0f - xx);
|
||||
float red1 = red01 * xx + red11 * (1.0f - xx);
|
||||
|
||||
float yy = (v * (img->height - 1)) - image_y0;
|
||||
|
||||
float a = alpha0 * yy + alpha1 * (1.0f - yy);
|
||||
float rf = red0 * yy + red1 * (1.0f - yy);
|
||||
float gf = green0 * yy + green1 * (1.0f - yy);
|
||||
float bf = blue0 * yy + blue1 * (1.0f - yy);
|
||||
|
||||
// float rf = red / 255.0f;
|
||||
// float gf = green / 255.0f;
|
||||
// float bf = blue / 255.0f;
|
||||
|
||||
if (a == 0.0f) {
|
||||
// nothing
|
||||
}
|
||||
else if (a == 1.0f) {
|
||||
kinc_g1_set_pixel(frame_x, frame_y, rf, gf, bf);
|
||||
}
|
||||
else {
|
||||
// float a = alpha / 255.0f;
|
||||
uint32_t old = kinc_internal_g1_image[frame_y * kinc_internal_g1_tex_width + frame_x];
|
||||
float oldblue = ((old >> 16) & 0xff) / 255.0f;
|
||||
float oldgreen = ((old >> 8) & 0xff) / 255.0f;
|
||||
float oldred = (old & 0xff) / 255.0f;
|
||||
|
||||
kinc_g1_set_pixel(frame_x, frame_y, rf * a + oldred * (1.0f - a), gf * a + oldgreen * (1.0f - a), bf * a + oldblue * (1.0f - a));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void draw_pixel(kinc_image_t *img, int frame_x, int frame_y, float u, float v) {
|
||||
draw_pixel_point(img, frame_x, frame_y, u, v);
|
||||
}
|
||||
|
||||
typedef struct Point2D {
|
||||
int x, y;
|
||||
} Point2D_t;
|
||||
|
||||
static int orient2d(Point2D_t a, Point2D_t b, Point2D_t c) {
|
||||
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
|
||||
}
|
||||
|
||||
static int min4(int a, int b, int c, int d) {
|
||||
return kinc_mini(kinc_mini(a, b), kinc_mini(c, d));
|
||||
}
|
||||
|
||||
static int max4(int a, int b, int c, int d) {
|
||||
return kinc_maxi(kinc_maxi(a, b), kinc_maxi(c, d));
|
||||
}
|
||||
|
||||
static void drawQuad(kinc_image_t *img, Point2D_t v0, Point2D_t v1, Point2D_t v2, Point2D_t v3) {
|
||||
// Compute triangle bounding box
|
||||
int minX = min4(v0.x, v1.x, v2.x, v3.x);
|
||||
int minY = min4(v0.y, v1.y, v2.y, v3.y);
|
||||
int maxX = max4(v0.x, v1.x, v2.x, v3.x);
|
||||
int maxY = max4(v0.y, v1.y, v2.y, v3.y);
|
||||
|
||||
// Clip against screen bounds
|
||||
minX = kinc_maxi(minX, 0);
|
||||
minY = kinc_maxi(minY, 0);
|
||||
maxX = kinc_mini(maxX, kinc_internal_g1_w - 1);
|
||||
maxY = kinc_mini(maxY, kinc_internal_g1_h - 1);
|
||||
|
||||
// v1 - v0
|
||||
int x1 = v1.x - v0.x;
|
||||
int x2 = v1.y - v0.y;
|
||||
|
||||
// v2 - v1
|
||||
int y1 = v2.x - v1.x;
|
||||
int y2 = v2.y - v1.y;
|
||||
|
||||
int area = x1 * y2 - x2 * y1;
|
||||
|
||||
// Rasterize
|
||||
Point2D_t p;
|
||||
for (p.y = minY; p.y <= maxY; p.y++) {
|
||||
for (p.x = minX; p.x <= maxX; p.x++) {
|
||||
// Determine barycentric coordinates
|
||||
int w0 = orient2d(v0, v1, p);
|
||||
int w1 = orient2d(v1, v2, p);
|
||||
// int w2 = orient2d(v2, v3, p);
|
||||
// int w3 = orient2d(v3, v0, p);
|
||||
|
||||
float u = w0 / (float)area; //(w0 + w2);
|
||||
float v = w1 / (float)area; //(w1 + w3);
|
||||
|
||||
// If p is on or inside all edges, render pixel.
|
||||
// if (w0 >= 0 && w1 >= 0 && w2 >= 0 && w3 >= 0) {
|
||||
if (u >= 0.0f && u <= 1.0f && v >= 0.0f && v <= 1.0f) {
|
||||
// renderPixel(p, w0, w1, w2);
|
||||
// kinc_g1_set_pixel(p.x, p.y, u, v, 0.0f);
|
||||
draw_pixel(img, p.x, p.y, u, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g2_draw_image(kinc_image_t *img, float x, float y) {
|
||||
kinc_vector3_t _0;
|
||||
_0.x = x;
|
||||
_0.y = y;
|
||||
_0.z = 1.0f;
|
||||
kinc_vector3_t _1;
|
||||
_1.x = x + img->width;
|
||||
_1.y = y;
|
||||
_1.z = 1.0f;
|
||||
kinc_vector3_t _2;
|
||||
_2.x = x + img->width;
|
||||
_2.y = y + img->height;
|
||||
_2.z = 1.0f;
|
||||
kinc_vector3_t _3;
|
||||
_3.x = x;
|
||||
_3.y = y + img->height;
|
||||
_3.z = 1.0f;
|
||||
|
||||
_0 = kinc_matrix3x3_multiply_vector(&transform, _0);
|
||||
_1 = kinc_matrix3x3_multiply_vector(&transform, _1);
|
||||
_2 = kinc_matrix3x3_multiply_vector(&transform, _2);
|
||||
_3 = kinc_matrix3x3_multiply_vector(&transform, _3);
|
||||
|
||||
Point2D_t v0, v1, v2, v3;
|
||||
v0.x = (int)kinc_round(_0.x);
|
||||
v0.y = (int)kinc_round(_0.y);
|
||||
v1.x = (int)kinc_round(_1.x);
|
||||
v1.y = (int)kinc_round(_1.y);
|
||||
v2.x = (int)kinc_round(_2.x);
|
||||
v2.y = (int)kinc_round(_2.y);
|
||||
v3.x = (int)kinc_round(_3.x);
|
||||
v3.y = (int)kinc_round(_3.y);
|
||||
drawQuad(img, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
void kinc_g2_set_rotation(float angle, float centerx, float centery) {
|
||||
kinc_matrix3x3_t translation1 = kinc_matrix3x3_translation(centerx, centery);
|
||||
kinc_matrix3x3_t rotation = kinc_matrix3x3_rotation_z(angle);
|
||||
kinc_matrix3x3_t translation2 = kinc_matrix3x3_translation(-centerx, -centery);
|
||||
kinc_matrix3x3_t transformation1 = kinc_matrix3x3_multiply(&translation1, &rotation);
|
||||
transform = kinc_matrix3x3_multiply(&transformation1, &translation2);
|
||||
}
|
||||
226
Kinc/Sources/kinc/graphics4/compute.h
Normal file
226
Kinc/Sources/kinc/graphics4/compute.h
Normal file
@ -0,0 +1,226 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/compute.h>
|
||||
#ifdef KORE_OPENGL
|
||||
#include <kinc/backend/graphics4/ShaderStorageBufferImpl.h>
|
||||
#endif
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
/*! \file compute.h
|
||||
\brief Provides support for running compute-shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g4_texture;
|
||||
struct kinc_g4_render_target;
|
||||
|
||||
typedef struct kinc_compute_constant_location {
|
||||
kinc_compute_constant_location_impl_t impl;
|
||||
} kinc_compute_constant_location_t;
|
||||
|
||||
typedef struct kinc_compute_texture_unit {
|
||||
kinc_compute_texture_unit_impl_t impl;
|
||||
} kinc_compute_texture_unit_t;
|
||||
|
||||
typedef struct kinc_compute_shader {
|
||||
kinc_compute_shader_impl_t impl;
|
||||
} kinc_compute_shader_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a compute-shader from system-specific shader-data.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader-object to initialize</param>
|
||||
/// <param name="source">A pointer to system-specific shader-data</param>
|
||||
/// <param name="length">Length of the shader-data in bytes</param>
|
||||
KINC_FUNC void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *source, int length);
|
||||
|
||||
/// <summary>
|
||||
/// Destroy a shader-object
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader-object to destroy</param>
|
||||
KINC_FUNC void kinc_compute_shader_destroy(kinc_compute_shader_t *shader);
|
||||
|
||||
#ifndef KINC_KONG
|
||||
/// <summary>
|
||||
/// Finds the location of a constant/uniform inside of a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to look into</param>
|
||||
/// <param name="name">The constant/uniform-name to look for</param>
|
||||
/// <returns>The found constant-location</returns>
|
||||
KINC_FUNC kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name);
|
||||
|
||||
/// <summary>
|
||||
/// Finds a texture-unit inside of a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to look into</param>
|
||||
/// <param name="name">The texture-name to look for</param>
|
||||
/// <returns>The found texture-unit</returns>
|
||||
KINC_FUNC kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name);
|
||||
#endif
|
||||
|
||||
#ifdef KORE_OPENGL
|
||||
typedef struct kinc_shader_storage_buffer {
|
||||
kinc_compute_shader_storage_buffer_impl_t impl;
|
||||
} kinc_shader_storage_buffer_t;
|
||||
|
||||
KINC_FUNC void kinc_shader_storage_buffer_init(kinc_shader_storage_buffer_t *buffer, int count, kinc_g4_vertex_data_t type);
|
||||
KINC_FUNC void kinc_shader_storage_buffer_destroy(kinc_shader_storage_buffer_t *buffer);
|
||||
KINC_FUNC int *kinc_shader_storage_buffer_lock(kinc_shader_storage_buffer_t *buffer);
|
||||
KINC_FUNC void kinc_shader_storage_buffer_unlock(kinc_shader_storage_buffer_t *buffer);
|
||||
KINC_FUNC int kinc_shader_storage_buffer_count(kinc_shader_storage_buffer_t *buffer);
|
||||
KINC_FUNC void kinc_shader_storage_buffer_internal_set(kinc_shader_storage_buffer_t *buffer);
|
||||
#endif
|
||||
|
||||
typedef enum kinc_compute_access { KINC_COMPUTE_ACCESS_READ, KINC_COMPUTE_ACCESS_WRITE, KINC_COMPUTE_ACCESS_READ_WRITE } kinc_compute_access_t;
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bool-value to a constant/uniform. The constant/uniform has to be declared as a bool in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
/// <param name="value">The value to set the location to</param>
|
||||
KINC_FUNC void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns an int-value to a constant/uniform. The constant/uniform has to be declared as an int in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
/// <param name="value">The value to set the location to</param>
|
||||
KINC_FUNC void kinc_compute_set_int(kinc_compute_constant_location_t location, int value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a float-value to a constant/uniform. The constant/uniform has to be declared as a float in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
/// <param name="value">The value to set the location to</param>
|
||||
KINC_FUNC void kinc_compute_set_float(kinc_compute_constant_location_t location, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns two float-values to a constant/uniform. The constant/uniform has to be declared as a vec2 in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns three float-values to a constant/uniform. The constant/uniform has to be declared as a vec3 in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns four float-values to a constant/uniform. The constant/uniform has to be declared as a vec4 in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns an array of float-values to a constant/uniform. The constant/uniform has to be declared as a float-array in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 4x4-matrix-value to a constant/uniform. The constant/uniform has to be declared as a mat4 in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 3x3-matrix-value to a constant/uniform. The constant/uniform has to be declared as a mat3 in the shader.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to set</param>
|
||||
KINC_FUNC void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value);
|
||||
|
||||
#ifdef KORE_OPENGL
|
||||
KINC_FUNC void kinc_compute_set_buffer(kinc_shader_storage_buffer_t *buffer, int index);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for direct access.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture, kinc_compute_access_t access);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a render-target to a texture-unit for direct access.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *texture, kinc_compute_access_t access);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for samples access.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a render-target to a texture-unit for samples access.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the depth-component of a render-target to a texture-unit for samples access.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the mode for accessing a texture outside of the 0 to 1-range for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the magnification-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the minification-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mipmap-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns the mode for accessing a texture outside of the 0 to 1-range for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir,
|
||||
kinc_g4_texture_addressing_t addressing);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the magnification-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the minification-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mipmap-mode for a texture-unit.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a shader for the next compute-run.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to use</param>
|
||||
KINC_FUNC void kinc_compute_set_shader(kinc_compute_shader_t *shader);
|
||||
|
||||
/// <summary>
|
||||
/// Fire off a compute-run on x * y * z elements.
|
||||
/// </summary>
|
||||
/// <param name="x">The x-size for the compute-run</param>
|
||||
/// <param name="y">The y-size for the compute-run</param>
|
||||
/// <param name="z">The z-size for the compute-run</param>
|
||||
KINC_FUNC void kinc_compute(int x, int y, int z);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
77
Kinc/Sources/kinc/graphics4/constantbuffer.h
Normal file
77
Kinc/Sources/kinc/graphics4/constantbuffer.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics4/constantbuffer.h>
|
||||
|
||||
#include <kinc/math/matrix.h>
|
||||
#include <kinc/math/vector.h>
|
||||
|
||||
/*! \file constantbuffer.h
|
||||
\brief Provides support for managing buffers of constant-data for shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g4_constant_buffer {
|
||||
kinc_g4_constant_buffer_impl impl;
|
||||
} kinc_g4_constant_buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="size">The size of the constant-data in the buffer in bytes</param>
|
||||
KINC_FUNC void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks all of a constant-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the buffer</returns>
|
||||
KINC_FUNC uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a constant-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The offset of where to start the lock in bytes</param>
|
||||
/// <param name="count">The number of bytes to lock</param>
|
||||
/// <returns>The contents of the buffer, starting at start</returns>
|
||||
KINC_FUNC uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a constant-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks parts of a constant-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
/// /// <param name="count">The number of bytes to unlock, starting from the start-index from the previous lock-call</param>
|
||||
KINC_FUNC void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out the size of the constant-data in the buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the size for</param>
|
||||
/// <returns>Returns the size of the constant-data in the buffer in bytes</returns>
|
||||
KINC_FUNC size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
22
Kinc/Sources/kinc/graphics4/constantlocation.h
Normal file
22
Kinc/Sources/kinc/graphics4/constantlocation.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
#include <kinc/backend/graphics4/shader.h>
|
||||
|
||||
/*! \file constantlocation.h
|
||||
\brief Provides the constant_location-struct which is used for setting constants/uniforms in a shader.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g4_constant_location {
|
||||
kinc_g4_constant_location_impl_t impl;
|
||||
} kinc_g4_constant_location_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
4
Kinc/Sources/kinc/graphics4/g4unit.c
Normal file
4
Kinc/Sources/kinc/graphics4/g4unit.c
Normal file
@ -0,0 +1,4 @@
|
||||
#include "graphics.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "vertexbuffer.c.h"
|
||||
11
Kinc/Sources/kinc/graphics4/graphics.c.h
Normal file
11
Kinc/Sources/kinc/graphics4/graphics.c.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include "graphics.h"
|
||||
|
||||
static int antialiasing_samples;
|
||||
|
||||
int kinc_g4_antialiasing_samples(void) {
|
||||
return antialiasing_samples;
|
||||
}
|
||||
|
||||
void kinc_g4_set_antialiasing_samples(int samples) {
|
||||
antialiasing_samples = samples;
|
||||
}
|
||||
432
Kinc/Sources/kinc/graphics4/graphics.h
Normal file
432
Kinc/Sources/kinc/graphics4/graphics.h
Normal file
@ -0,0 +1,432 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
#include "constantlocation.h"
|
||||
#include "pipeline.h"
|
||||
#include "textureunit.h"
|
||||
|
||||
/*! \file graphics.h
|
||||
\brief Contains the base G4-functionality.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g4_pipeline;
|
||||
struct kinc_g4_render_target;
|
||||
struct kinc_g4_texture;
|
||||
struct kinc_g4_texture_array;
|
||||
#ifdef KINC_KONG
|
||||
struct kinc_g4_constant_buffer;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_TEXTURE_ADDRESSING_REPEAT,
|
||||
KINC_G4_TEXTURE_ADDRESSING_MIRROR,
|
||||
KINC_G4_TEXTURE_ADDRESSING_CLAMP,
|
||||
KINC_G4_TEXTURE_ADDRESSING_BORDER
|
||||
} kinc_g4_texture_addressing_t;
|
||||
|
||||
typedef enum { KINC_G4_TEXTURE_DIRECTION_U, KINC_G4_TEXTURE_DIRECTION_V, KINC_G4_TEXTURE_DIRECTION_W } kinc_g4_texture_direction_t;
|
||||
|
||||
typedef enum { KINC_G4_TEXTURE_FILTER_POINT, KINC_G4_TEXTURE_FILTER_LINEAR, KINC_G4_TEXTURE_FILTER_ANISOTROPIC } kinc_g4_texture_filter_t;
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_MIPMAP_FILTER_NONE,
|
||||
KINC_G4_MIPMAP_FILTER_POINT,
|
||||
KINC_G4_MIPMAP_FILTER_LINEAR // linear texture filter + linear mip filter -> trilinear filter
|
||||
} kinc_g4_mipmap_filter_t;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether instanced rendering (kinc_g4_draw_indexed_vertices_instanced and pals) is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether instanced rendering is supported</returns>
|
||||
KINC_FUNC bool kinc_g4_supports_instanced_rendering(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether GPU-compute (the functions in kinc/graphics4/compute.h) is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether GPU-compute is supported</returns>
|
||||
KINC_FUNC bool kinc_g4_supports_compute_shaders(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether blend-constants (see kinc_g4_set_blend_constant and the blending-properties for pipelines) are supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether blend-constants are supported</returns>
|
||||
KINC_FUNC bool kinc_g4_supports_blend_constants(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether textures are supported which have widths/heights which are not powers of two.
|
||||
/// </summary>
|
||||
/// <returns>Whether non power of two texture-sizes are supported</returns>
|
||||
KINC_FUNC bool kinc_g4_supports_non_pow2_textures(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether render-targets are upside down. This happens in OpenGL and there is currently no automatic mitigation.
|
||||
/// </summary>
|
||||
/// <returns>Whether render-targets are upside down</returns>
|
||||
KINC_FUNC bool kinc_g4_render_targets_inverted_y(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns how many textures can be used at the same time in a fragment-shader.
|
||||
/// </summary>
|
||||
/// <returns>The number of textures</returns>
|
||||
KINC_FUNC int kinc_g4_max_bound_textures(void);
|
||||
|
||||
/// <summary>
|
||||
/// Kicks off lingering work - may or may not actually do anything depending on the underlying graphics-API.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_flush(void);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called before rendering to a window. Typically called at the start of each frame.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to render to</param>
|
||||
KINC_FUNC void kinc_g4_begin(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called after rendering to a window. Typically called at the end of each frame.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to render to</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g4_end(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called to make the rendered frame visible. Typically called at the very end of each frame.
|
||||
/// </summary>
|
||||
KINC_FUNC bool kinc_g4_swap_buffers(void);
|
||||
|
||||
#define KINC_G4_CLEAR_COLOR 1
|
||||
#define KINC_G4_CLEAR_DEPTH 2
|
||||
#define KINC_G4_CLEAR_STENCIL 4
|
||||
|
||||
/// <summary>
|
||||
/// Clears the color, depth and/or stencil-components of the current framebuffer or render-target.
|
||||
/// </summary>
|
||||
/// <param name="flags">Defines what components to clear</param>
|
||||
/// <param name="color">The color-value to clear to</param>
|
||||
/// <param name="depth">The depth-value to clear to</param>
|
||||
/// <param name="stencil">The stencil-value to clear to</param>
|
||||
KINC_FUNC void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the viewport which defines the portion of the framebuffer or render-target things are rendered into. By default the viewport is equivalent to the full
|
||||
/// size of the current render-target or framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="x">The x-offset of the viewport from the left of the screen in pixels</param>
|
||||
/// <param name="y">The y-offset of the viewport from the top of the screen in pixels</param>
|
||||
/// <param name="width">The width of the viewport in pixels</param>
|
||||
/// <param name="height">The height of the viewport in pixels</param>
|
||||
KINC_FUNC void kinc_g4_viewport(int x, int y, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Enables and defines the scissor-rect. When the scissor-rect is enabled, anything that's rendered outside of the scissor-rect will be ignored.
|
||||
/// </summary>
|
||||
/// <param name="x">The x-offset of the scissor-rect from the left of the screen in pixels</param>
|
||||
/// <param name="y">The y-offset of the scissor-rect from the top of the screen in pixels</param>
|
||||
/// <param name="width">The width of the scissor-rect in pixels</param>
|
||||
/// <param name="height">The height of the scissor-rect in pixels</param>
|
||||
KINC_FUNC void kinc_g4_scissor(int x, int y, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Disables the scissor-rect.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_disable_scissor(void);
|
||||
|
||||
/// <summary>
|
||||
/// Draws the entire content of the currently set index-buffer and vertex-buffer. G4 can only draw triangle-lists using vertex-indices as this is what GPUs tend
|
||||
/// to be optimized for.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_draw_indexed_vertices(void);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a part of the content of the currently set index-buffer and vertex-buffer. G4 can only draw triangle-lists using vertex-indices as this is what GPUs
|
||||
/// tend to be optimized for.
|
||||
/// </summary>
|
||||
/// <param name="start">The offset into the index-buffer</param>
|
||||
/// <param name="count">The number of indices to use</param>
|
||||
KINC_FUNC void kinc_g4_draw_indexed_vertices_from_to(int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a part of the content of the currently set index-buffer and vertex-buffer and additionally applies a general offset into the vertex-buffer. G4 can
|
||||
/// only draw triangle-lists using vertex-indices as this is what GPUs tend to be optimized for.
|
||||
/// </summary>
|
||||
/// <param name="start">The offset into the index-buffer</param>
|
||||
/// <param name="count">The number of indices to use</param>
|
||||
/// <param name="vertex_offset">The offset into the vertex-buffer which is added to each index read from the index-buffer</param>
|
||||
KINC_FUNC void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset);
|
||||
|
||||
KINC_FUNC void kinc_g4_draw_indexed_vertices_instanced(int instanceCount);
|
||||
|
||||
KINC_FUNC void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pipeline for the next draw-call. The pipeline defines most rendering-state including the shaders to be used.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to set</param>
|
||||
KINC_FUNC void kinc_g4_set_pipeline(struct kinc_g4_pipeline *pipeline);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_stencil_reference_value(int value);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the blend constant used for `KINC_G4_BLEND_CONSTANT` or `KINC_G4_INV_BLEND_CONSTANT`
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_set_blend_constant(float r, float g, float b, float a);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
KINC_FUNC void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Assigns an integer to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the value to</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_int(kinc_g4_constant_location_t location, int value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns two integers to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first component of the constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second component of the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_int2(kinc_g4_constant_location_t location, int value1, int value2);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns three integers to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first component of the constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second component of the constant/uniform</param>
|
||||
/// <param name="value3">The value to assign to the third component of the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_int3(kinc_g4_constant_location_t location, int value1, int value2, int value3);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns four integers to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first component of the constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second component of the constant/uniform</param>
|
||||
/// <param name="value3">The value to assign to the third component of the constant/uniform</param>
|
||||
/// <param name="value4">The value to assign to the fourth component of the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_int4(kinc_g4_constant_location_t location, int value1, int value2, int value3, int value4);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bunch of integers to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value">The values to assign to the constant/uniform</param>
|
||||
/// <param name="value">The number of values to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a float to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the value to</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_float(kinc_g4_constant_location_t location, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns two floats to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_float2(kinc_g4_constant_location_t location, float value1, float value2);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns three floats to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second constant/uniform</param>
|
||||
/// <param name="value3">The value to assign to the third constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_float3(kinc_g4_constant_location_t location, float value1, float value2, float value3);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns four floats to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value1">The value to assign to the first constant/uniform</param>
|
||||
/// <param name="value2">The value to assign to the second constant/uniform</param>
|
||||
/// <param name="value3">The value to assign to the third constant/uniform</param>
|
||||
/// <param name="value4">The value to assign to the fourth constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_float4(kinc_g4_constant_location_t location, float value1, float value2, float value3, float value4);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bunch of floats to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value">The values to assign to the constant/uniform</param>
|
||||
/// <param name="value">The number of values to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bool to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the value to</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_bool(kinc_g4_constant_location_t location, bool value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 3x3-matrix to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the value to</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 4x4-matrix to a constant/uniform in the currently set pipeline.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the value to</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value);
|
||||
|
||||
/// <summary>
|
||||
/// Set the texture-sampling-mode for upscaled textures.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the texture-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Set the texture-sampling-mode for upscaled 3D-textures.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the texture-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Set the texture-sampling-mode for downscaled textures.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the texture-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t unit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Set the texture-sampling-mode for downscaled 3D-textures.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the texture-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mipmap-sampling-mode which defines whether mipmaps are used at all and if so whether the two neighbouring mipmaps are linearly interpolated.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the mipmap-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t unit, kinc_g4_mipmap_filter_t filter);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mipmap-sampling-mode for a 3D-texture which defines whether mipmaps are used at all and if so whether the two neighbouring mipmaps are linearly
|
||||
/// interpolated.
|
||||
/// </summary>
|
||||
/// <param name="unit">The texture-unit to set the mipmap-sampling-mode for</param>
|
||||
/// <param name="filter">The mode to set</param>
|
||||
KINC_FUNC void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the framebuffer (aka the actual contents of the current window) to be the target of any future draw-calls.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_restore_render_target(void);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the passed render-targets to be the target of any future draw-calls.
|
||||
/// </summary>
|
||||
/// <param name="targets">An array of render-targets</param>
|
||||
/// <param name="count">The number of render-targets in the render-target-array</param>
|
||||
KINC_FUNC void kinc_g4_set_render_targets(struct kinc_g4_render_target **targets, int count);
|
||||
|
||||
KINC_FUNC void kinc_g4_set_render_target_face(struct kinc_g4_render_target *texture, int face);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for sampled access via GLSL's texture.
|
||||
/// </summary>
|
||||
/// <param name="unit">The unit to assign this texture to</param>
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
KINC_FUNC void kinc_g4_set_texture(uint32_t unit, struct kinc_g4_texture *texture);
|
||||
#else
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for sampled access via GLSL's texture.
|
||||
/// </summary>
|
||||
/// <param name="unit">The unit to assign this texture to</param>
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
KINC_FUNC void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for direct access via GLSL's texelFetch (as
|
||||
/// opposed to GLSL's texture). The name of this functions is unfortunately based
|
||||
/// on OpenGL's confusing terminology.
|
||||
/// </summary>
|
||||
/// <param name="unit">The unit to assign this texture to</param>
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
KINC_FUNC void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture);
|
||||
|
||||
KINC_FUNC bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery);
|
||||
|
||||
KINC_FUNC void kinc_g4_delete_occlusion_query(unsigned occlusionQuery);
|
||||
|
||||
KINC_FUNC void kinc_g4_start_occlusion_query(unsigned occlusionQuery);
|
||||
|
||||
KINC_FUNC void kinc_g4_end_occlusion_query(unsigned occlusionQuery);
|
||||
|
||||
KINC_FUNC bool kinc_g4_are_query_results_available(unsigned occlusionQuery);
|
||||
|
||||
KINC_FUNC void kinc_g4_get_query_results(unsigned occlusionQuery, unsigned *pixelCount);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture-array to a texture-unit.
|
||||
/// </summary>
|
||||
/// <param name="unit">The unit to assign the texture-array to</param>
|
||||
/// <param name="array">The texture-array to assign to the texture-unit</param>
|
||||
KINC_FUNC void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently used number of samples for hardware-antialiasing.
|
||||
/// </summary>
|
||||
/// <returns>The number of samples</returns>
|
||||
KINC_FUNC int kinc_g4_antialiasing_samples(void);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the number of samples used for hardware-antialiasing. This typically uses multisampling and typically only works with a few specific numbers of
|
||||
/// sample-counts - 2 and 4 are pretty safe bets. It also might do nothing at all.
|
||||
/// </summary>
|
||||
/// <param name="samples">The number of samples</param>
|
||||
KINC_FUNC void kinc_g4_set_antialiasing_samples(int samples);
|
||||
|
||||
#ifndef KINC_DOCS
|
||||
void kinc_g4_internal_init(void);
|
||||
void kinc_g4_internal_init_window(int window, int depth_buffer_bits, int stencil_buffer_bits, bool vsync);
|
||||
void kinc_g4_internal_destroy_window(int window);
|
||||
void kinc_g4_internal_destroy(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
84
Kinc/Sources/kinc/graphics4/indexbuffer.h
Normal file
84
Kinc/Sources/kinc/graphics4/indexbuffer.h
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "usage.h"
|
||||
|
||||
#include <kinc/backend/graphics4/indexbuffer.h>
|
||||
|
||||
/*! \file indexbuffer.h
|
||||
\brief Provides functions for setting up and using index-buffers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g4_index_buffer_format { KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_INDEX_BUFFER_FORMAT_16BIT } kinc_g4_index_buffer_format_t;
|
||||
|
||||
typedef struct kinc_g4_index_buffer {
|
||||
kinc_g4_index_buffer_impl_t impl;
|
||||
} kinc_g4_index_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an index-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="count">The number of indices to allocate for the buffer</param>
|
||||
/// <param name="format">The integer-format of the buffer</param>
|
||||
/// <param name="usage">A hint for how the buffer will be used</param>
|
||||
KINC_FUNC void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an index-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks an index-buffer so its contents can be modified.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the index-buffer in uint32s or uint16s depending on the format provided when initializing</returns>
|
||||
KINC_FUNC void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The index of the first index to lock</param>
|
||||
/// <param name="count">The number of indices to lock</param>
|
||||
/// <returns>The contents of the index-buffer, starting at start, in uint32s or uint16s depending on the format provided when initializing</returns>
|
||||
KINC_FUNC void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks an index-buffer after locking it so the changed buffer-contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks part of an index-buffer after locking so the changed buffer-contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
/// <param name="count">The number of indices to unlock, starting from the start-index from the previous lock-call</param>
|
||||
KINC_FUNC void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of indices in the buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to query for its number of indices</param>
|
||||
/// <returns>The number of indices</returns>
|
||||
KINC_FUNC int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Sets an index-buffer to be used for the next draw-command.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to use</param>
|
||||
KINC_FUNC void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
53
Kinc/Sources/kinc/graphics4/pipeline.c.h
Normal file
53
Kinc/Sources/kinc/graphics4/pipeline.c.h
Normal file
@ -0,0 +1,53 @@
|
||||
#include "pipeline.h"
|
||||
|
||||
void kinc_g4_internal_pipeline_set_defaults(kinc_g4_pipeline_t *state) {
|
||||
for (int i = 0; i < 16; ++i)
|
||||
state->input_layout[i] = NULL;
|
||||
state->vertex_shader = NULL;
|
||||
state->fragment_shader = NULL;
|
||||
state->geometry_shader = NULL;
|
||||
state->tessellation_control_shader = NULL;
|
||||
state->tessellation_evaluation_shader = NULL;
|
||||
|
||||
state->cull_mode = KINC_G4_CULL_NOTHING;
|
||||
|
||||
state->depth_write = false;
|
||||
state->depth_mode = KINC_G4_COMPARE_ALWAYS;
|
||||
|
||||
state->stencil_front_mode = KINC_G4_COMPARE_ALWAYS;
|
||||
state->stencil_front_both_pass = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_front_depth_fail = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_front_fail = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_back_mode = KINC_G4_COMPARE_ALWAYS;
|
||||
state->stencil_back_both_pass = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_back_depth_fail = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_back_fail = KINC_G4_STENCIL_KEEP;
|
||||
state->stencil_reference_value = 0;
|
||||
state->stencil_read_mask = 0xff;
|
||||
state->stencil_write_mask = 0xff;
|
||||
|
||||
state->blend_source = KINC_G4_BLEND_ONE;
|
||||
state->blend_destination = KINC_G4_BLEND_ZERO;
|
||||
state->blend_operation = KINC_G4_BLENDOP_ADD;
|
||||
state->alpha_blend_source = KINC_G4_BLEND_ONE;
|
||||
state->alpha_blend_destination = KINC_G4_BLEND_ZERO;
|
||||
state->alpha_blend_operation = KINC_G4_BLENDOP_ADD;
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
state->color_write_mask_red[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
state->color_write_mask_green[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
state->color_write_mask_blue[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
state->color_write_mask_alpha[i] = true;
|
||||
|
||||
state->color_attachment_count = 1;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
state->color_attachment[i] = KINC_G4_RENDER_TARGET_FORMAT_32BIT;
|
||||
|
||||
state->depth_attachment_bits = 0;
|
||||
state->stencil_attachment_bits = 0;
|
||||
|
||||
state->conservative_rasterization = false;
|
||||
}
|
||||
161
Kinc/Sources/kinc/graphics4/pipeline.h
Normal file
161
Kinc/Sources/kinc/graphics4/pipeline.h
Normal file
@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/graphics4/constantlocation.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
|
||||
/*! \file pipeline.h
|
||||
\brief Provides functions for creating and using pipelines which configure the GPU for rendering.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g4_vertex_structure;
|
||||
struct kinc_g4_shader;
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_BLEND_ONE,
|
||||
KINC_G4_BLEND_ZERO,
|
||||
KINC_G4_BLEND_SOURCE_ALPHA,
|
||||
KINC_G4_BLEND_DEST_ALPHA,
|
||||
KINC_G4_BLEND_INV_SOURCE_ALPHA,
|
||||
KINC_G4_BLEND_INV_DEST_ALPHA,
|
||||
KINC_G4_BLEND_SOURCE_COLOR,
|
||||
KINC_G4_BLEND_DEST_COLOR,
|
||||
KINC_G4_BLEND_INV_SOURCE_COLOR,
|
||||
KINC_G4_BLEND_INV_DEST_COLOR,
|
||||
KINC_G4_BLEND_CONSTANT,
|
||||
KINC_G4_BLEND_INV_CONSTANT
|
||||
} kinc_g4_blending_factor_t;
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_BLENDOP_ADD,
|
||||
KINC_G4_BLENDOP_SUBTRACT,
|
||||
KINC_G4_BLENDOP_REVERSE_SUBTRACT,
|
||||
KINC_G4_BLENDOP_MIN,
|
||||
KINC_G4_BLENDOP_MAX
|
||||
} kinc_g4_blending_operation_t;
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_COMPARE_ALWAYS,
|
||||
KINC_G4_COMPARE_NEVER,
|
||||
KINC_G4_COMPARE_EQUAL,
|
||||
KINC_G4_COMPARE_NOT_EQUAL,
|
||||
KINC_G4_COMPARE_LESS,
|
||||
KINC_G4_COMPARE_LESS_EQUAL,
|
||||
KINC_G4_COMPARE_GREATER,
|
||||
KINC_G4_COMPARE_GREATER_EQUAL
|
||||
} kinc_g4_compare_mode_t;
|
||||
|
||||
typedef enum { KINC_G4_CULL_CLOCKWISE, KINC_G4_CULL_COUNTER_CLOCKWISE, KINC_G4_CULL_NOTHING } kinc_g4_cull_mode_t;
|
||||
|
||||
typedef enum {
|
||||
KINC_G4_STENCIL_KEEP,
|
||||
KINC_G4_STENCIL_ZERO,
|
||||
KINC_G4_STENCIL_REPLACE,
|
||||
KINC_G4_STENCIL_INCREMENT,
|
||||
KINC_G4_STENCIL_INCREMENT_WRAP,
|
||||
KINC_G4_STENCIL_DECREMENT,
|
||||
KINC_G4_STENCIL_DECREMENT_WRAP,
|
||||
KINC_G4_STENCIL_INVERT
|
||||
} kinc_g4_stencil_action_t;
|
||||
|
||||
typedef struct kinc_g4_pipeline {
|
||||
struct kinc_g4_vertex_structure *input_layout[16];
|
||||
struct kinc_g4_shader *vertex_shader;
|
||||
struct kinc_g4_shader *fragment_shader;
|
||||
struct kinc_g4_shader *geometry_shader;
|
||||
struct kinc_g4_shader *tessellation_control_shader;
|
||||
struct kinc_g4_shader *tessellation_evaluation_shader;
|
||||
|
||||
kinc_g4_cull_mode_t cull_mode;
|
||||
|
||||
bool depth_write;
|
||||
kinc_g4_compare_mode_t depth_mode;
|
||||
|
||||
kinc_g4_compare_mode_t stencil_front_mode;
|
||||
kinc_g4_stencil_action_t stencil_front_both_pass;
|
||||
kinc_g4_stencil_action_t stencil_front_depth_fail;
|
||||
kinc_g4_stencil_action_t stencil_front_fail;
|
||||
|
||||
kinc_g4_compare_mode_t stencil_back_mode;
|
||||
kinc_g4_stencil_action_t stencil_back_both_pass;
|
||||
kinc_g4_stencil_action_t stencil_back_depth_fail;
|
||||
kinc_g4_stencil_action_t stencil_back_fail;
|
||||
|
||||
int stencil_reference_value;
|
||||
int stencil_read_mask;
|
||||
int stencil_write_mask;
|
||||
|
||||
// One, Zero deactivates blending
|
||||
kinc_g4_blending_factor_t blend_source;
|
||||
kinc_g4_blending_factor_t blend_destination;
|
||||
kinc_g4_blending_operation_t blend_operation;
|
||||
kinc_g4_blending_factor_t alpha_blend_source;
|
||||
kinc_g4_blending_factor_t alpha_blend_destination;
|
||||
kinc_g4_blending_operation_t alpha_blend_operation;
|
||||
|
||||
bool color_write_mask_red[8]; // Per render target
|
||||
bool color_write_mask_green[8];
|
||||
bool color_write_mask_blue[8];
|
||||
bool color_write_mask_alpha[8];
|
||||
|
||||
int color_attachment_count;
|
||||
kinc_g4_render_target_format_t color_attachment[8];
|
||||
|
||||
int depth_attachment_bits;
|
||||
int stencil_attachment_bits;
|
||||
|
||||
bool conservative_rasterization;
|
||||
|
||||
kinc_g4_pipeline_impl_t impl;
|
||||
} kinc_g4_pipeline_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a pipeline.
|
||||
/// </summary>
|
||||
/// <param name="state">The pipeline to initialize</param>
|
||||
KINC_FUNC void kinc_g4_pipeline_init(kinc_g4_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a pipeline.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to destroy</param>
|
||||
KINC_FUNC void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a pipeline. After a pipeline has been compiled it is finalized. It cannot be compiled again and further changes to the pipeline are ignored.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to compile</param>
|
||||
KINC_FUNC void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipeline);
|
||||
|
||||
#ifndef KINC_KONG
|
||||
/// <summary>
|
||||
/// Searches for a constant/uniform and returns a constant-location which can be used to change the constant/uniform.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the constant/uniform to find</param>
|
||||
/// <returns>The constant-location of the constant/uniform</returns>
|
||||
KINC_FUNC kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *pipeline, const char *name);
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a texture-declaration and returns a texture-unit which can be used to assign a texture.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the texture-declaration to search for</param>
|
||||
/// <returns>The texture-unit of the texture-declaration</returns>
|
||||
KINC_FUNC kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *pipeline, const char *name);
|
||||
#endif
|
||||
|
||||
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline);
|
||||
void kinc_g4_internal_pipeline_set_defaults(kinc_g4_pipeline_t *pipeline);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
11
Kinc/Sources/kinc/graphics4/rendertarget.c.h
Normal file
11
Kinc/Sources/kinc/graphics4/rendertarget.c.h
Normal file
@ -0,0 +1,11 @@
|
||||
#include "rendertarget.h"
|
||||
|
||||
void kinc_g4_render_target_init(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits) {
|
||||
kinc_g4_render_target_init_with_multisampling(renderTarget, width, height, format, depthBufferBits, stencilBufferBits, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits) {
|
||||
kinc_g4_render_target_init_cube_with_multisampling(renderTarget, cubeMapSize, format, depthBufferBits, stencilBufferBits, 1);
|
||||
}
|
||||
142
Kinc/Sources/kinc/graphics4/rendertarget.h
Normal file
142
Kinc/Sources/kinc/graphics4/rendertarget.h
Normal file
@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics4/rendertarget.h>
|
||||
|
||||
#include "textureunit.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file rendertarget.h
|
||||
\brief Provides functions for handling render-targets.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g4_render_target_format {
|
||||
KINC_G4_RENDER_TARGET_FORMAT_32BIT,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED,
|
||||
KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT
|
||||
} kinc_g4_render_target_format_t;
|
||||
|
||||
typedef struct kinc_g4_render_target {
|
||||
int width;
|
||||
int height;
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
bool isCubeMap;
|
||||
bool isDepthAttachment;
|
||||
|
||||
kinc_g4_render_target_impl_t impl;
|
||||
} kinc_g4_render_target_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a regular render-target.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
KINC_FUNC void kinc_g4_render_target_init(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a multi-sampled render-target if possible - otherwise it falls back to a regular render-target.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <param name="samples_per_pixel"></param>
|
||||
KINC_FUNC void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height,
|
||||
kinc_g4_render_target_format_t format, int depthBufferBits, int stencilBufferBits,
|
||||
int samples_per_pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a render-target-cube-map.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget"></param>
|
||||
/// <param name="cubeMapSize"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
KINC_FUNC void kinc_g4_render_target_init_cube(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a multi-sampled render-target-cube-map. Can fall back to a non-multi-sampled cube-map.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget"></param>
|
||||
/// <param name="cubeMapSize"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <param name="samples_per_pixel"></param>
|
||||
KINC_FUNC void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Deallocates and destroys a render-target.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to destroy</param>
|
||||
KINC_FUNC void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
/// <summary>
|
||||
/// Uses the color-component of a render-target as a texture.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to use</param>
|
||||
/// <param name="unit">The texture-unit to assign the render-target to</param>
|
||||
KINC_FUNC void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit);
|
||||
#else
|
||||
/// <summary>
|
||||
/// Uses the color-component of a render-target as a texture.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to use</param>
|
||||
/// <param name="unit">The texture-unit to assign the render-target to</param>
|
||||
KINC_FUNC void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Uses the depth-component of a render-target as a texture.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to use</param>
|
||||
/// <param name="unit">The texture-unit to assign the render-target to</param>
|
||||
KINC_FUNC void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the depth and stencil-components of one render-target into another one.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to copy the data into</param>
|
||||
/// <param name="source">The render-target from which to copy the data</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source);
|
||||
|
||||
/// <summary>
|
||||
/// Copies out the color-data from a render-target. Beware, this is very slow.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to copy the color-data from</param>
|
||||
/// <param name="data">A pointer to where the data will be copied to</param>
|
||||
KINC_FUNC void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Generates the mipmap-chain for a render-target.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to create the mipmaps for</param>
|
||||
/// <param name="levels">The number of mipmap-levels to generate</param>
|
||||
KINC_FUNC void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
58
Kinc/Sources/kinc/graphics4/shader.h
Normal file
58
Kinc/Sources/kinc/graphics4/shader.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics4/shader.h>
|
||||
|
||||
/*! \file shader.h
|
||||
\brief Provides functions for creating and destroying shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g4_shader_type {
|
||||
KINC_G4_SHADER_TYPE_FRAGMENT,
|
||||
KINC_G4_SHADER_TYPE_VERTEX,
|
||||
KINC_G4_SHADER_TYPE_COMPUTE,
|
||||
KINC_G4_SHADER_TYPE_GEOMETRY,
|
||||
KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL,
|
||||
KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION,
|
||||
|
||||
KINC_G4_SHADER_TYPE_COUNT
|
||||
} kinc_g4_shader_type_t;
|
||||
|
||||
typedef struct kinc_g4_shader {
|
||||
kinc_g4_shader_impl_t impl;
|
||||
} kinc_g4_shader_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a shader based on system-specific shader-data. The system-specific shader-data is usually created per system by the krafix-shader-compiler which
|
||||
/// is automatically called by kincmake.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to initialize</param>
|
||||
/// <param name="data">The system-specific shader-data</param>
|
||||
/// <param name="length">The length of the system-specific shader-data in bytes</param>
|
||||
/// <param name="type">The type of the shader</param>
|
||||
KINC_FUNC void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *data, size_t length, kinc_g4_shader_type_t type);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a shader from GLSL-source-code. This only works on some platforms and only if KRAFIX_LIBRARY define has been set and the krafix-shader-compiler
|
||||
/// was compiled in library-mode and linked into the application.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to initialize</param>
|
||||
/// <param name="source">The GLSL-shader-source-code</param>
|
||||
/// <param name="type">The type of the shader</param>
|
||||
/// <returns>The number of errors the compiler encountered - hopefully it's zero.</returns>
|
||||
KINC_FUNC int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to destroy</param>
|
||||
KINC_FUNC void kinc_g4_shader_destroy(kinc_g4_shader_t *shader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
106
Kinc/Sources/kinc/graphics4/texture.h
Normal file
106
Kinc/Sources/kinc/graphics4/texture.h
Normal file
@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics4/texture.h>
|
||||
#include <kinc/image.h>
|
||||
|
||||
/*! \file texture.h
|
||||
\brief Provides functions for handling textures.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef kinc_image_t kinc_g4_image_t;
|
||||
|
||||
typedef struct kinc_g4_texture {
|
||||
int tex_width;
|
||||
int tex_height;
|
||||
int tex_depth;
|
||||
kinc_image_format_t format;
|
||||
kinc_g4_texture_impl_t impl;
|
||||
} kinc_g4_texture_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture without copying any data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="width">The width of the texture to create</param>
|
||||
/// <param name="height">The height of the texture to create</param>
|
||||
/// <param name="format">The format of the texture to create</param>
|
||||
KINC_FUNC void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a 3d-texture without copying any data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="width">The width of the texture to create</param>
|
||||
/// <param name="height">The height of the texture to create</param>
|
||||
/// <param name="depth">The depth of the texture to create</param>
|
||||
/// <param name="format">The format of the texture to create</param>
|
||||
KINC_FUNC void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture and copies image-data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="image">The image which's data is copied into the texture</param>
|
||||
KINC_FUNC void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture and copies image-data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="image">The image which's data is copied into the texture</param>
|
||||
KINC_FUNC void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image);
|
||||
|
||||
/// <summary>
|
||||
/// Deallocates and destroys a texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to destroy</param>
|
||||
KINC_FUNC void kinc_g4_texture_destroy(kinc_g4_texture_t *texture);
|
||||
|
||||
KINC_FUNC unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture);
|
||||
|
||||
KINC_FUNC void kinc_g4_texture_unlock(kinc_g4_texture_t *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Clears parts of a texture to a color.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color);
|
||||
|
||||
/// <summary>
|
||||
/// Generates the mipmap-chain for a texture.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to create the mipmaps for</param>
|
||||
/// <param name="levels">The number of mipmap-levels to generate</param>
|
||||
KINC_FUNC void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mipmap for one level of a texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to set a mipmap-level for</param>
|
||||
/// <param name="mipmap">The image-data for the mipmap-level to set</param>
|
||||
/// <param name="level">The mipmap-level to set</param>
|
||||
KINC_FUNC void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the stride of the first mipmap-layer of the texture in bytes.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to figure out the stride for</param>
|
||||
/// <returns>The stride of the first mipmap-layer in bytes</returns>
|
||||
KINC_FUNC int kinc_g4_texture_stride(kinc_g4_texture_t *texture);
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
KINC_FUNC void kinc_g4_texture_init_from_id(kinc_g4_texture_t *texture, unsigned texid);
|
||||
#endif
|
||||
|
||||
#if defined(KORE_IOS) || defined(KORE_MACOS)
|
||||
KINC_FUNC void kinc_g4_texture_upload(kinc_g4_texture_t *texture, uint8_t *data, int stride);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
37
Kinc/Sources/kinc/graphics4/texturearray.h
Normal file
37
Kinc/Sources/kinc/graphics4/texturearray.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
#include <kinc/backend/graphics4/texturearray.h>
|
||||
|
||||
/*! \file texturearray.h
|
||||
\brief Provides functions for creating and destroying texture-arrays.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g4_texture_array {
|
||||
kinc_g4_texture_array_impl_t impl;
|
||||
} kinc_g4_texture_array_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture-array based on an array of images.
|
||||
/// </summary>
|
||||
/// <param name="array">The texture-array to initialize</param>
|
||||
/// <param name="images">The images to assign to the texture-array</param>
|
||||
/// <param name="count">The number of images</param>
|
||||
KINC_FUNC void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *images, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Deallocates and destroys a texture-array
|
||||
/// </summary>
|
||||
/// <param name="array">The texture-array to destroy</param>
|
||||
KINC_FUNC void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
21
Kinc/Sources/kinc/graphics4/textureunit.h
Normal file
21
Kinc/Sources/kinc/graphics4/textureunit.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
/*! \file textureunit.h
|
||||
\brief Provides a texture-unit-struct which is used for setting textures in a shader.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g4_texture_unit {
|
||||
int stages[KINC_G4_SHADER_TYPE_COUNT];
|
||||
} kinc_g4_texture_unit_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
15
Kinc/Sources/kinc/graphics4/usage.h
Normal file
15
Kinc/Sources/kinc/graphics4/usage.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
/*! \file usage.h
|
||||
\brief Provides the usage enum.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g4_usage { KINC_G4_USAGE_STATIC, KINC_G4_USAGE_DYNAMIC, KINC_G4_USAGE_READABLE } kinc_g4_usage_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
20
Kinc/Sources/kinc/graphics4/vertexbuffer.c.h
Normal file
20
Kinc/Sources/kinc/graphics4/vertexbuffer.c.h
Normal file
@ -0,0 +1,20 @@
|
||||
#include "vertexbuffer.h"
|
||||
|
||||
static void init_vertex_element(kinc_g4_vertex_element_t *element, const char *name, kinc_g4_vertex_data_t data) {
|
||||
element->name = name;
|
||||
element->data = data;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_structure_init(kinc_g4_vertex_structure_t *structure) {
|
||||
structure->size = 0;
|
||||
structure->instanced = false;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_structure_add(kinc_g4_vertex_structure_t *structure, const char *name, kinc_g4_vertex_data_t data) {
|
||||
init_vertex_element(&structure->elements[structure->size++], name, data);
|
||||
}
|
||||
|
||||
void kinc_g4_set_vertex_buffer(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g4_vertex_buffer_t *buffers[1] = {buffer};
|
||||
kinc_g4_set_vertex_buffers(buffers, 1);
|
||||
}
|
||||
101
Kinc/Sources/kinc/graphics4/vertexbuffer.h
Normal file
101
Kinc/Sources/kinc/graphics4/vertexbuffer.h
Normal file
@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "usage.h"
|
||||
#include "vertexstructure.h"
|
||||
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file vertexbuffer.h
|
||||
\brief Provides functions for setting up and using vertex-buffers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g4_vertex_buffer {
|
||||
kinc_g4_vertex_buffer_impl_t impl;
|
||||
} kinc_g4_vertex_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocate and initialize a vertex-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="count">The number of vertices in the buffer</param>
|
||||
/// <param name="structure">The structure of the buffer</param>
|
||||
/// <param name="usage">A hint for how the buffer will be used</param>
|
||||
/// <param name="instance_data_step_rate">The step-rate for instanced-rendering - use 0 if instanced-rendering will not be used with this buffer</param>
|
||||
KINC_FUNC void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a vertex-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks all of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the buffer</returns>
|
||||
KINC_FUNC float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The index of the first vertex to lock</param>
|
||||
/// <param name="count">The number of vertices to lock</param>
|
||||
/// <returns>The contents of the buffer, starting at start</returns>
|
||||
KINC_FUNC float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlock all of a vertex-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks part of a vertex-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
/// <param name="count">The number of vertices to unlock, starting from the start-vertex from the previous lock-call</param>
|
||||
KINC_FUNC void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of vertices in a buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the number of vertices for</param>
|
||||
/// <returns>The number of vertices</returns>
|
||||
KINC_FUNC int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the stride aka the size of one vertex of the buffer in bytes.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the stride for</param>
|
||||
/// <returns>The stride of the buffer in bytes</returns>
|
||||
KINC_FUNC int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset);
|
||||
|
||||
/// <summary>
|
||||
/// Sets vertex-buffers for the next draw-call.
|
||||
/// </summary>
|
||||
/// <param name="buffers">The buffers to set</param>
|
||||
/// <param name="count">The number of buffers to set</param>
|
||||
KINC_FUNC void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a vertex-buffer for the next draw-call.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to set</param>
|
||||
KINC_FUNC void kinc_g4_set_vertex_buffer(kinc_g4_vertex_buffer_t *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
157
Kinc/Sources/kinc/graphics4/vertexstructure.h
Normal file
157
Kinc/Sources/kinc/graphics4/vertexstructure.h
Normal file
@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file vertexstructure.h
|
||||
\brief Provides functions for setting up the structure of vertices in a vertex-buffer.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g4_vertex_data {
|
||||
KINC_G4_VERTEX_DATA_NONE = 0,
|
||||
KINC_G4_VERTEX_DATA_F32_1X = 1,
|
||||
KINC_G4_VERTEX_DATA_F32_2X = 2,
|
||||
KINC_G4_VERTEX_DATA_F32_3X = 3,
|
||||
KINC_G4_VERTEX_DATA_F32_4X = 4,
|
||||
KINC_G4_VERTEX_DATA_F32_4X4 = 5,
|
||||
KINC_G4_VERTEX_DATA_I8_1X = 6,
|
||||
KINC_G4_VERTEX_DATA_U8_1X = 7,
|
||||
KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED = 8,
|
||||
KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED = 9,
|
||||
KINC_G4_VERTEX_DATA_I8_2X = 10,
|
||||
KINC_G4_VERTEX_DATA_U8_2X = 11,
|
||||
KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED = 12,
|
||||
KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED = 13,
|
||||
KINC_G4_VERTEX_DATA_I8_4X = 14,
|
||||
KINC_G4_VERTEX_DATA_U8_4X = 15,
|
||||
KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED = 16,
|
||||
KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED = 17,
|
||||
KINC_G4_VERTEX_DATA_I16_1X = 18,
|
||||
KINC_G4_VERTEX_DATA_U16_1X = 19,
|
||||
KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED = 20,
|
||||
KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED = 21,
|
||||
KINC_G4_VERTEX_DATA_I16_2X = 22,
|
||||
KINC_G4_VERTEX_DATA_U16_2X = 23,
|
||||
KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED = 24,
|
||||
KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED = 25,
|
||||
KINC_G4_VERTEX_DATA_I16_4X = 26,
|
||||
KINC_G4_VERTEX_DATA_U16_4X = 27,
|
||||
KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED = 28,
|
||||
KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED = 29,
|
||||
KINC_G4_VERTEX_DATA_I32_1X = 30,
|
||||
KINC_G4_VERTEX_DATA_U32_1X = 31,
|
||||
KINC_G4_VERTEX_DATA_I32_2X = 32,
|
||||
KINC_G4_VERTEX_DATA_U32_2X = 33,
|
||||
KINC_G4_VERTEX_DATA_I32_3X = 34,
|
||||
KINC_G4_VERTEX_DATA_U32_3X = 35,
|
||||
KINC_G4_VERTEX_DATA_I32_4X = 36,
|
||||
KINC_G4_VERTEX_DATA_U32_4X = 37,
|
||||
|
||||
// deprecated
|
||||
KINC_G4_VERTEX_DATA_FLOAT1 = KINC_G4_VERTEX_DATA_F32_1X,
|
||||
KINC_G4_VERTEX_DATA_FLOAT2 = KINC_G4_VERTEX_DATA_F32_2X,
|
||||
KINC_G4_VERTEX_DATA_FLOAT3 = KINC_G4_VERTEX_DATA_F32_3X,
|
||||
KINC_G4_VERTEX_DATA_FLOAT4 = KINC_G4_VERTEX_DATA_F32_4X,
|
||||
KINC_G4_VERTEX_DATA_FLOAT4X4 = KINC_G4_VERTEX_DATA_F32_4X4,
|
||||
KINC_G4_VERTEX_DATA_SHORT2_NORM = KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED,
|
||||
KINC_G4_VERTEX_DATA_SHORT4_NORM = KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED,
|
||||
KINC_G4_VERTEX_DATA_COLOR = KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED
|
||||
} kinc_g4_vertex_data_t;
|
||||
|
||||
static inline int kinc_g4_vertex_data_size(kinc_g4_vertex_data_t data) {
|
||||
switch (data) {
|
||||
default:
|
||||
case KINC_G4_VERTEX_DATA_NONE:
|
||||
return 0;
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
return 1 * 4;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
return 2 * 4;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
return 3 * 4;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
return 4 * 4;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4:
|
||||
return 4 * 4 * 4;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
return 1 * 1;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
return 2 * 1;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
return 4 * 1;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
return 1 * 2;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
return 2 * 2;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
return 4 * 2;
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
return 1 * 4;
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
return 2 * 4;
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
return 3 * 4;
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
return 4 * 4;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct kinc_g4_vertex_element {
|
||||
const char *name;
|
||||
kinc_g4_vertex_data_t data;
|
||||
} kinc_g4_vertex_element_t;
|
||||
|
||||
#define KINC_G4_MAX_VERTEX_ELEMENTS 16
|
||||
|
||||
typedef struct kinc_g4_vertex_structure {
|
||||
kinc_g4_vertex_element_t elements[KINC_G4_MAX_VERTEX_ELEMENTS];
|
||||
int size;
|
||||
bool instanced;
|
||||
} kinc_g4_vertex_structure_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a vertex-structure.
|
||||
/// </summary>
|
||||
/// <param name="structure">The structure to initialize</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g4_vertex_structure_init(kinc_g4_vertex_structure_t *structure);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element to a vertex-structure.
|
||||
/// </summary>
|
||||
/// <param name="structure">The structure to add an element to</param>
|
||||
/// <param name="name">The name to use for the new element</param>
|
||||
/// <param name="data">The type of data to assign for the new element</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g4_vertex_structure_add(kinc_g4_vertex_structure_t *structure, const char *name, kinc_g4_vertex_data_t data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
1
Kinc/Sources/kinc/graphics5/commandlist.c.h
Normal file
1
Kinc/Sources/kinc/graphics5/commandlist.c.h
Normal file
@ -0,0 +1 @@
|
||||
#include "commandlist.h"
|
||||
323
Kinc/Sources/kinc/graphics5/commandlist.h
Normal file
323
Kinc/Sources/kinc/graphics5/commandlist.h
Normal file
@ -0,0 +1,323 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "rendertarget.h"
|
||||
#include "sampler.h"
|
||||
#include "texture.h"
|
||||
#include "textureunit.h"
|
||||
|
||||
#include <kinc/backend/graphics5/commandlist.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*! \file commandlist.h
|
||||
\brief Contains functions for building command-lists to send commands to the GPU.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KINC_G5_CLEAR_COLOR 1
|
||||
#define KINC_G5_CLEAR_DEPTH 2
|
||||
#define KINC_G5_CLEAR_STENCIL 4
|
||||
|
||||
struct kinc_g5_constant_buffer;
|
||||
struct kinc_g5_index_buffer;
|
||||
struct kinc_g5_pipeline;
|
||||
struct kinc_g5_render_target;
|
||||
struct kinc_g5_texture;
|
||||
struct kinc_g5_vertex_buffer;
|
||||
struct kinc_g5_render_target;
|
||||
|
||||
/*typedef enum kinc_g5_render_target_format {
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_16BIT_DEPTH,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED
|
||||
} kinc_g5_render_target_format_t;*/
|
||||
// typedef kinc_g4_render_target_format_t kinc_g5_render_target_format_t;
|
||||
|
||||
typedef struct kinc_g5_command_list {
|
||||
CommandList5Impl impl;
|
||||
} kinc_g5_command_list_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a command-list.
|
||||
/// </summary>
|
||||
/// <param name="list">The command-list to initialize</param>
|
||||
KINC_FUNC void kinc_g5_command_list_init(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a command-list.
|
||||
/// </summary>
|
||||
/// <param name="list">The command-list to destroy</param>
|
||||
KINC_FUNC void kinc_g5_command_list_destroy(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Starts recording commands in a command-list.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_begin(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Ends recording commands for the list. Has to be called after kinc_g5_command_list_begin and before kinc_g5_command_list_execute.
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_command_list_end(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Records a command to clear the color, depth and/or stencil-components of a render-target.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="render_target">The render-target to clear</param>
|
||||
/// <param name="flags">Defines what components to clear</param>
|
||||
/// <param name="color">The color-value to clear to</param>
|
||||
/// <param name="depth">The depth-value to clear to</param>
|
||||
/// <param name="stencil">The stencil-value to clear to</param>
|
||||
KINC_FUNC void kinc_g5_command_list_clear(kinc_g5_command_list_t *list, struct kinc_g5_render_target *render_target, unsigned flags, unsigned color,
|
||||
float depth, int stencil);
|
||||
|
||||
/// <summary>
|
||||
/// Records a command that prepares a render-target to be used as the current framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="renderTarget">The render-target to use as the current framebuffer</param>
|
||||
KINC_FUNC void kinc_g5_command_list_render_target_to_framebuffer_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Records a command that prepares a render-target for regular render-target-usage after being used as the current framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="renderTarget">The render-target to use in regular render-target-mode</param>
|
||||
KINC_FUNC void kinc_g5_command_list_framebuffer_to_render_target_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that prepares a render-target to be rendered to.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="renderTarget">The render-target to render to</param>
|
||||
KINC_FUNC void kinc_g5_command_list_texture_to_render_target_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that prepares a render-target to be used for sampling/reading like a texture.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="renderTarget">The render-target to be used like a texture</param>
|
||||
KINC_FUNC void kinc_g5_command_list_render_target_to_texture_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that draws the entire content of the currently set index-buffer and vertex-buffer. G4 can only draw triangle-lists using vertex-indices as
|
||||
/// this is what GPUs tend to be optimized for.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
KINC_FUNC void kinc_g5_command_list_draw_indexed_vertices(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that draws a part of the content of the currently set index-buffer and vertex-buffer. G4 can only draw triangle-lists using vertex-indices
|
||||
/// as this is what GPUs tend to be optimized for.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="start">The offset into the index-buffer</param>
|
||||
/// <param name="count">The number of indices to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_draw_indexed_vertices_from_to(kinc_g5_command_list_t *list, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that draws a part of the content of the currently set index-buffer and vertex-buffer and additionally applies a general offset into the
|
||||
/// vertex-buffer. G4 can only draw triangle-lists using vertex-indices as this is what GPUs tend to be optimized for.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="start">The offset into the index-buffer</param>
|
||||
/// <param name="count">The number of indices to use</param>
|
||||
/// <param name="vertex_offset">The offset into the vertex-buffer which is added to each index read from the index-buffer</param>
|
||||
KINC_FUNC void kinc_g5_command_list_draw_indexed_vertices_from_to_from(kinc_g5_command_list_t *list, int start, int count, int vertex_offset);
|
||||
|
||||
KINC_FUNC void kinc_g5_command_list_draw_indexed_vertices_instanced(kinc_g5_command_list_t *list, int instanceCount);
|
||||
KINC_FUNC void kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(kinc_g5_command_list_t *list, int instanceCount, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that sets the viewport which defines the portion of the framebuffer or render-target things are rendered into. By default the viewport is
|
||||
/// equivalent to the full size of the current render-target or framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="x">The x-offset of the viewport from the left of the screen in pixels</param>
|
||||
/// <param name="y">The y-offset of the viewport from the top of the screen in pixels</param>
|
||||
/// <param name="width">The width of the viewport in pixels</param>
|
||||
/// <param name="height">The height of the viewport in pixels</param>
|
||||
KINC_FUNC void kinc_g5_command_list_viewport(kinc_g5_command_list_t *list, int x, int y, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that enables and defines the scissor-rect. When the scissor-rect is enabled, anything that's rendered outside of the scissor-rect will be
|
||||
/// ignored.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="x">The x-offset of the scissor-rect from the left of the screen in pixels</param>
|
||||
/// <param name="y">The y-offset of the scissor-rect from the top of the screen in pixels</param>
|
||||
/// <param name="width">The width of the scissor-rect in pixels</param>
|
||||
/// <param name="height">The height of the scissor-rect in pixels</param>
|
||||
KINC_FUNC void kinc_g5_command_list_scissor(kinc_g5_command_list_t *list, int x, int y, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to disable the scissor-rect.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
KINC_FUNC void kinc_g5_command_list_disable_scissor(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to set the pipeline for the next draw-call. The pipeline defines most rendering-state including the shaders to be used.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="pipeline">The pipeline to set</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_pipeline(kinc_g5_command_list_t *list, struct kinc_g5_pipeline *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the blend constant used for `KINC_G5_BLEND_CONSTANT` or `KINC_G5_INV_BLEND_CONSTANT`
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g5_command_list_set_blend_constant(kinc_g5_command_list_t *list, float r, float g, float b, float a);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command which sets vertex-buffers for the next draw-call.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffers">The buffers to set</param>
|
||||
/// <param name="offsets">The offset to use for every buffer in number of vertices</param>
|
||||
/// <param name="count">The number of buffers to set</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_vertex_buffers(kinc_g5_command_list_t *list, struct kinc_g5_vertex_buffer **buffers, int *offsets, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to set an index-buffer to be used for the next draw-command.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The buffer to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_index_buffer(kinc_g5_command_list_t *list, struct kinc_g5_index_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that sets the render-targets to draw into in following draw-calls.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="targets">The render-targets to use for following-draw calls</param>
|
||||
/// <param name="count">The number of render-targets to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_render_targets(kinc_g5_command_list_t *list, struct kinc_g5_render_target **targets, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to upload an index-buffer that's in main-memory to gpu-memory. Does nothing on unified-memory-systems.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The buffer to upload</param>
|
||||
KINC_FUNC void kinc_g5_command_list_upload_index_buffer(kinc_g5_command_list_t *list, struct kinc_g5_index_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to upload a vertex-buffer that's in main-memory to gpu-memory. Does nothing on unified-memory-systems.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The buffer to upload</param>
|
||||
KINC_FUNC void kinc_g5_command_list_upload_vertex_buffer(kinc_g5_command_list_t *list, struct kinc_g5_vertex_buffer *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command to upload a texture that's in main-memory to gpu-memory. Does nothing on unified-memory-systems.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The texture to upload</param>
|
||||
KINC_FUNC void kinc_g5_command_list_upload_texture(kinc_g5_command_list_t *list, struct kinc_g5_texture *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that sets a constant-buffer for the vertex-shader-stage.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The buffer to set</param>
|
||||
/// <param name="offset">The offset into the buffer in bytes to use as the start</param>
|
||||
/// <param name="size">The size of the buffer to use in bytes starting at the offset</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_vertex_constant_buffer(kinc_g5_command_list_t *list, struct kinc_g5_constant_buffer *buffer, int offset, size_t size);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that sets a constant-buffer for the fragment-shader-stage.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="buffer">The buffer to set</param>
|
||||
/// <param name="offset">The offset into the buffer in bytes to use as the start</param>
|
||||
/// <param name="size">The size of the buffer to use in bytes starting at the offset</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_fragment_constant_buffer(kinc_g5_command_list_t *list, struct kinc_g5_constant_buffer *buffer, int offset, size_t size);
|
||||
|
||||
/// <summary>
|
||||
/// Kicks off execution of the commands which have been recorded in the command-list. kinc_g5_command_list_end has to be called beforehand.
|
||||
/// </summary>
|
||||
/// <param name="list">The command-list to execute</param>
|
||||
KINC_FUNC void kinc_g5_command_list_execute(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Waits for execution of the command_list to finish. Make sure the command-list is executing before you wait for it.
|
||||
/// Also take note that waiting for a command-list to finish executing completely is a very expensive operation.
|
||||
/// </summary>
|
||||
/// <param name="list">The command-list to execute</param>
|
||||
KINC_FUNC void kinc_g5_command_list_wait_for_execution_to_finish(kinc_g5_command_list_t *list);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a command that copies the contents of a render-target into a cpu-side buffer. Beware: This is enormously slow.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="render_target">The render-target to copy the data from</param>
|
||||
/// <param name="data">The buffer to copy the data into</param>
|
||||
KINC_FUNC void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, struct kinc_g5_render_target *render_target, uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Records a command that fires off a compute-run on x * y * z elements.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="x">The x-size for the compute-run</param>
|
||||
/// <param name="y">The y-size for the compute-run</param>
|
||||
/// <param name="z">The z-size for the compute-run</param>
|
||||
KINC_FUNC void kinc_g5_command_list_compute(kinc_g5_command_list_t *list, int x, int y, int z);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for sampled access via GLSL's texture.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="unit">The unit to assign this texture to</param>
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_texture(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a texture to a texture-unit for direct access via GLSL's texelFetch (as
|
||||
/// opposed to GLSL's texture). The name of this functions is unfortunately based
|
||||
/// on OpenGL's confusing terminology.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="unit">The unit to assign this texture to</param>
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_image_texture(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Uses the color-component of a render-target as a texture.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="unit">The texture-unit to assign the render-target to</param>
|
||||
/// <param name="target">The render-target to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_texture_from_render_target(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_render_target_t *target);
|
||||
|
||||
/// <summary>
|
||||
/// Uses the depth-component of a render-target as a texture.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to write the command to</param>
|
||||
/// <param name="unit">The texture-unit to assign the render-target to</param>
|
||||
/// <param name="target">The render-target to use</param>
|
||||
KINC_FUNC void kinc_g5_command_list_set_texture_from_render_target_depth(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit,
|
||||
kinc_g5_render_target_t *target);
|
||||
|
||||
KINC_FUNC void kinc_g5_command_list_set_render_target_face(kinc_g5_command_list_t *list, kinc_g5_render_target_t *texture, int face);
|
||||
|
||||
KINC_FUNC void kinc_g5_command_list_set_sampler(kinc_g5_command_list_t *list, kinc_g5_texture_unit_t unit, kinc_g5_sampler_t *sampler);
|
||||
|
||||
// Occlusion Query
|
||||
KINC_FUNC bool kinc_g5_command_list_init_occlusion_query(kinc_g5_command_list_t *list, unsigned *occlusionQuery);
|
||||
KINC_FUNC void kinc_g5_command_list_delete_occlusion_query(kinc_g5_command_list_t *list, unsigned occlusionQuery);
|
||||
KINC_FUNC void kinc_g5_command_list_render_occlusion_query(kinc_g5_command_list_t *list, unsigned occlusionQuery, int triangles);
|
||||
KINC_FUNC bool kinc_g5_command_list_are_query_results_available(kinc_g5_command_list_t *list, unsigned occlusionQuery);
|
||||
KINC_FUNC void kinc_g5_command_list_get_query_result(kinc_g5_command_list_t *list, unsigned occlusionQuery, unsigned *pixelCount);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
58
Kinc/Sources/kinc/graphics5/compute.h
Normal file
58
Kinc/Sources/kinc/graphics5/compute.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <Kore/ComputeImpl.h>
|
||||
|
||||
#include <kinc/graphics5/constantlocation.h>
|
||||
#include <kinc/graphics5/textureunit.h>
|
||||
|
||||
/*! \file compute.h
|
||||
\brief Provides support for running compute-shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_compute_shader_impl {
|
||||
int a;
|
||||
} kinc_g5_compute_shader_<EFBFBD>mpl_t;
|
||||
|
||||
typedef struct kinc_g5_compute_shader {
|
||||
kinc_g5_compute_shader_<EFBFBD>mpl_t impl;
|
||||
} kinc_g5_compute_shader_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a compute-shader from system-specific shader-data.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader-object to initialize</param>
|
||||
/// <param name="source">A pointer to system-specific shader-data</param>
|
||||
/// <param name="length">Length of the shader-data in bytes</param>
|
||||
KINC_FUNC void kinc_g5_compute_shader_init(kinc_g5_compute_shader_t *shader, void *source, int length);
|
||||
|
||||
/// <summary>
|
||||
/// Desotry a shader-object
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader-object to destroy</param>
|
||||
KINC_FUNC void kinc_g5_compute_shader_destroy(kinc_g5_compute_shader_t *shader);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the location of a constant/uniform inside of a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to look into</param>
|
||||
/// <param name="name">The constant/uniform-name to look for</param>
|
||||
/// <returns>The found constant-location</returns>
|
||||
KINC_FUNC kinc_g5_constant_location_t kinc_g5_compute_shader_get_constant_location(kinc_g5_compute_shader_t *shader, const char *name);
|
||||
|
||||
/// <summary>
|
||||
/// Finds a texture-unit inside of a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to look into</param>
|
||||
/// <param name="name">The texture-name to look for</param>
|
||||
/// <returns>The found texture-unit</returns>
|
||||
KINC_FUNC kinc_g5_texture_unit_t kinc_compute_g5_shader_get_texture_unit(kinc_g5_compute_shader_t *shader, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
112
Kinc/Sources/kinc/graphics5/constantbuffer.c.h
Normal file
112
Kinc/Sources/kinc/graphics5/constantbuffer.c.h
Normal file
@ -0,0 +1,112 @@
|
||||
#include "constantbuffer.h"
|
||||
|
||||
static void setInt(uint8_t *constants, int offset, int value) {
|
||||
int *ints = (int *)(&constants[offset]);
|
||||
ints[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat(uint8_t *constants, int offset, float value) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
floats[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat2(uint8_t *constants, int offset, float value1, float value2) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
}
|
||||
|
||||
static void setFloat3(uint8_t *constants, int offset, float value1, float value2, float value3) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
}
|
||||
|
||||
static void setFloat4(uint8_t *constants, int offset, float value1, float value2, float value3, float value4) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value4;
|
||||
}
|
||||
|
||||
static void setFloats(uint8_t *constants, int offset, float *values, int count) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
floats[i] = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void setBool(uint8_t *constants, int offset, bool value) {
|
||||
int *ints = (int *)(&constants[offset]);
|
||||
ints[0] = value ? 1 : 0;
|
||||
}
|
||||
|
||||
static void setMatrix4(uint8_t *constants, int offset, kinc_matrix4x4_t *value) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix4x4_get(value, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setMatrix3(uint8_t *constants, int offset, kinc_matrix3x3_t *value) {
|
||||
float *floats = (float *)(&constants[offset]);
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix3x3_get(value, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_int(kinc_g5_constant_buffer_t *buffer, int offset, int value) {
|
||||
setInt(buffer->data, offset, value);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_float(kinc_g5_constant_buffer_t *buffer, int offset, float value) {
|
||||
setFloat(buffer->data, offset, value);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_float2(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2) {
|
||||
setFloat2(buffer->data, offset, value1, value2);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_float3(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2, float value3) {
|
||||
setFloat3(buffer->data, offset, value1, value2, value3);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_float4(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2, float value3, float value4) {
|
||||
setFloat4(buffer->data, offset, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_floats(kinc_g5_constant_buffer_t *buffer, int offset, float *values, int count) {
|
||||
setFloats(buffer->data, offset, values, count);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_bool(kinc_g5_constant_buffer_t *buffer, int offset, bool value) {
|
||||
setBool(buffer->data, offset, value);
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_matrix4(kinc_g5_constant_buffer_t *buffer, int offset, kinc_matrix4x4_t *value) {
|
||||
if (kinc_g5_transposeMat4) {
|
||||
kinc_matrix4x4_t m = *value;
|
||||
kinc_matrix4x4_transpose(&m);
|
||||
setMatrix4(buffer->data, offset, &m);
|
||||
}
|
||||
else {
|
||||
setMatrix4(buffer->data, offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g5_constant_buffer_set_matrix3(kinc_g5_constant_buffer_t *buffer, int offset, kinc_matrix3x3_t *value) {
|
||||
if (kinc_g5_transposeMat3) {
|
||||
kinc_matrix3x3_t m = *value;
|
||||
kinc_matrix3x3_transpose(&m);
|
||||
setMatrix3(buffer->data, offset, &m);
|
||||
}
|
||||
else {
|
||||
setMatrix3(buffer->data, offset, value);
|
||||
}
|
||||
}
|
||||
140
Kinc/Sources/kinc/graphics5/constantbuffer.h
Normal file
140
Kinc/Sources/kinc/graphics5/constantbuffer.h
Normal file
@ -0,0 +1,140 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/constantbuffer.h>
|
||||
|
||||
#include <kinc/math/matrix.h>
|
||||
#include <kinc/math/vector.h>
|
||||
|
||||
/*! \file constantbuffer.h
|
||||
\brief Provides support for managing buffers of constant-data for shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_constant_buffer {
|
||||
uint8_t *data;
|
||||
ConstantBuffer5Impl impl;
|
||||
} kinc_g5_constant_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="size">The size of the constant-data in the buffer in bytes</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_init(kinc_g5_constant_buffer_t *buffer, int size);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_destroy(kinc_g5_constant_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks all of a constant-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the buffer</returns>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_lock_all(kinc_g5_constant_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a constant-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The offset of where to start the lock in bytes</param>
|
||||
/// <param name="count">The number of bytes to lock</param>
|
||||
/// <returns>The contents of the buffer, starting at start</returns>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_lock(kinc_g5_constant_buffer_t *buffer, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a constant-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_unlock(kinc_g5_constant_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out the size of the constant-data in the buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the size for</param>
|
||||
/// <returns>Returns the size of the constant-data in the buffer in bytes</returns>
|
||||
KINC_FUNC int kinc_g5_constant_buffer_size(kinc_g5_constant_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bool at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value">The value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_bool(kinc_g5_constant_buffer_t *buffer, int offset, bool value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns an integer at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value">The value to assign to the constant/uniform</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_int(kinc_g5_constant_buffer_t *buffer, int offset, int value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a float at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value">The value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_float(kinc_g5_constant_buffer_t *buffer, int offset, float value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns two floats at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value1">The first value to write into the buffer</param>
|
||||
/// <param name="value2">The second value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_float2(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns three floats at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value1">The first value to write into the buffer</param>
|
||||
/// <param name="value2">The second value to write into the buffer</param>
|
||||
/// <param name="value3">The third value to write into the buffer/param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_float3(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2, float value3);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns four floats at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value1">The first value to write into the buffer</param>
|
||||
/// <param name="value2">The second value to write into the buffer</param>
|
||||
/// <param name="value3">The third value to write into the buffer/param>
|
||||
/// <param name="value4">The fourth value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_float4(kinc_g5_constant_buffer_t *buffer, int offset, float value1, float value2, float value3, float value4);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a bunch of floats at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="location">The location of the constant/uniform to assign the values to</param>
|
||||
/// <param name="value">The values to write into the buffer</param>
|
||||
/// <param name="value">The number of values to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_floats(kinc_g5_constant_buffer_t *buffer, int offset, float *values, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 3x3-matrix at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value">The value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_matrix3(kinc_g5_constant_buffer_t *buffer, int offset, kinc_matrix3x3_t *value);
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a 4x4-matrix at an offset in a constant-buffer.
|
||||
/// </summary>
|
||||
/// <param name="offset">The offset at which to write the data</param>
|
||||
/// <param name="value">The value to write into the buffer</param>
|
||||
KINC_FUNC void kinc_g5_constant_buffer_set_matrix4(kinc_g5_constant_buffer_t *buffer, int offset, kinc_matrix4x4_t *value);
|
||||
|
||||
KINC_FUNC extern bool kinc_g5_transposeMat3;
|
||||
KINC_FUNC extern bool kinc_g5_transposeMat4;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
21
Kinc/Sources/kinc/graphics5/constantlocation.h
Normal file
21
Kinc/Sources/kinc/graphics5/constantlocation.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/pipeline.h>
|
||||
|
||||
/*! \file constantlocation.h
|
||||
\brief Provides the constant_location-struct which is used for setting constants/uniforms in a shader.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_constant_location {
|
||||
ConstantLocation5Impl impl;
|
||||
} kinc_g5_constant_location_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
7
Kinc/Sources/kinc/graphics5/g5unit.c
Normal file
7
Kinc/Sources/kinc/graphics5/g5unit.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "commandlist.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "graphics.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "sampler.c.h"
|
||||
#include "texture.c.h"
|
||||
22
Kinc/Sources/kinc/graphics5/graphics.c.h
Normal file
22
Kinc/Sources/kinc/graphics5/graphics.c.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef OPENGL_1_X
|
||||
|
||||
#include "graphics.h"
|
||||
|
||||
static int samples = 1;
|
||||
|
||||
int kinc_g5_antialiasing_samples(void) {
|
||||
return samples;
|
||||
}
|
||||
|
||||
void kinc_g5_set_antialiasing_samples(int samples_) {
|
||||
samples = samples_;
|
||||
}
|
||||
|
||||
bool kinc_g5_fullscreen = false;
|
||||
|
||||
// void Graphics5::setVertexBuffer(VertexBuffer& vertexBuffer) {
|
||||
// VertexBuffer* vertexBuffers[1] = {&vertexBuffer};
|
||||
// setVertexBuffers(vertexBuffers, 1);
|
||||
//}
|
||||
|
||||
#endif
|
||||
113
Kinc/Sources/kinc/graphics5/graphics.h
Normal file
113
Kinc/Sources/kinc/graphics5/graphics.h
Normal file
@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/image.h>
|
||||
|
||||
#include "rendertarget.h"
|
||||
#include "shader.h"
|
||||
#include "vertexstructure.h"
|
||||
|
||||
#include <kinc/backend/graphics5/graphics.h>
|
||||
|
||||
#include <kinc/math/matrix.h>
|
||||
#include <kinc/math/vector.h>
|
||||
|
||||
/*! \file graphics.h
|
||||
\brief Contains the base G5-functionality.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
KINC_FUNC extern bool kinc_g5_fullscreen;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether raytracing (see kinc/graphics5/raytrace.h) is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether raytracing is supported</returns>
|
||||
KINC_FUNC bool kinc_g5_supports_raytracing(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether instanced rendering (kinc_g5_command_list_draw_indexed_vertices_instanced and pals) is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether instanced rendering is supported</returns>
|
||||
KINC_FUNC bool kinc_g5_supports_instanced_rendering(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether GPU-compute (the functions in kinc/graphics5/compute.h) is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether GPU-compute is supported</returns>
|
||||
KINC_FUNC bool kinc_g5_supports_compute_shaders(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether blend-constants (see kinc_g4_set_blend_constant and the blending-properties for pipelines) are supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether blend-constants are supported</returns>
|
||||
KINC_FUNC bool kinc_g5_supports_blend_constants(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether textures are supported which have widths/heights which are not powers of two.
|
||||
/// </summary>
|
||||
/// <returns>Whether non power of two texture-sizes are supported</returns>
|
||||
KINC_FUNC bool kinc_g5_supports_non_pow2_textures(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether render-targets are upside down. This happens in OpenGL and there is currently no automatic mitigation.
|
||||
/// </summary>
|
||||
/// <returns>Whether render-targets are upside down</returns>
|
||||
KINC_FUNC bool kinc_g5_render_targets_inverted_y(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns how many textures can be used at the same time in a fragment-shader.
|
||||
/// </summary>
|
||||
/// <returns>The number of textures</returns>
|
||||
KINC_FUNC int kinc_g5_max_bound_textures(void);
|
||||
|
||||
/// <summary>
|
||||
/// I think this does nothing.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g5_flush(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently used number of samples for hardware-antialiasing.
|
||||
/// </summary>
|
||||
/// <returns>The number of samples</returns>
|
||||
KINC_FUNC int kinc_g5_antialiasing_samples(void);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the number of samples used for hardware-antialiasing. This typically uses multisampling and typically only works with a few specific numbers of
|
||||
/// sample-counts - 2 and 4 are pretty safe bets. It also might do nothing at all.
|
||||
/// </summary>
|
||||
/// <param name="samples">The number of samples</param>
|
||||
KINC_FUNC void kinc_g5_set_antialiasing_samples(int samples);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called before rendering to a window. Typically called at the start of each frame.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to render to</param>
|
||||
KINC_FUNC void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called after rendering to a window. Typically called at the end of each frame.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to render to</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_end(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be called to make the rendered frame visible. Typically called at the very end of each frame.
|
||||
/// </summary>
|
||||
KINC_FUNC bool kinc_g5_swap_buffers(void);
|
||||
|
||||
#ifndef KINC_DOCS
|
||||
void kinc_g5_internal_init(void);
|
||||
void kinc_g5_internal_init_window(int window, int depth_buffer_bits, int stencil_buffer_bits, bool vsync);
|
||||
void kinc_g5_internal_destroy_window(int window);
|
||||
void kinc_g5_internal_destroy(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
73
Kinc/Sources/kinc/graphics5/indexbuffer.h
Normal file
73
Kinc/Sources/kinc/graphics5/indexbuffer.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/indexbuffer.h>
|
||||
|
||||
/*! \file indexbuffer.h
|
||||
\brief Provides functions for setting up and using index-buffers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g5_index_buffer_format { KINC_G5_INDEX_BUFFER_FORMAT_32BIT, KINC_G5_INDEX_BUFFER_FORMAT_16BIT } kinc_g5_index_buffer_format_t;
|
||||
|
||||
typedef struct kinc_g5_index_buffer {
|
||||
IndexBuffer5Impl impl;
|
||||
} kinc_g5_index_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an index-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="count">The number of indices to allocate for the buffer</param>
|
||||
/// <param name="gpu_memory">When true, the buffer will be uploaded to gpu-memory which will make it faster to use but slower to change</param>
|
||||
KINC_FUNC void kinc_g5_index_buffer_init(kinc_g5_index_buffer_t *buffer, int count, kinc_g5_index_buffer_format_t format, bool gpu_memory);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an index-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g5_index_buffer_destroy(kinc_g5_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks an index-buffer so its contents can be modified.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the index-buffer in uint32s or uint16s depending on the format provided when initializing</returns>
|
||||
KINC_FUNC void *kinc_g5_index_buffer_lock_all(kinc_g5_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The index of the first index to lock</param>
|
||||
/// <param name="count">The number of indices to lock</param>
|
||||
/// <returns>The contents of the index-buffer, starting at start, in uint32s or uint16s depending on the format provided when initializing</returns>
|
||||
KINC_FUNC void *kinc_g5_index_buffer_lock(kinc_g5_index_buffer_t *buffer, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks an index-buffer after locking it so the changed buffer-contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g5_index_buffer_unlock_all(kinc_g5_index_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks part of an index-buffer after locking so the changed buffer-contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
/// <param name="count">The number of indices to unlock, starting from the start-index from the previous lock-call</param>
|
||||
KINC_FUNC void kinc_g5_index_buffer_unlock(kinc_g5_index_buffer_t *buffer, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of indices in the buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to query for its number of indices</param>
|
||||
/// <returns>The number of indices</returns>
|
||||
KINC_FUNC int kinc_g5_index_buffer_count(kinc_g5_index_buffer_t *buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
51
Kinc/Sources/kinc/graphics5/pipeline.c.h
Normal file
51
Kinc/Sources/kinc/graphics5/pipeline.c.h
Normal file
@ -0,0 +1,51 @@
|
||||
#include "pipeline.h"
|
||||
|
||||
void kinc_g5_internal_pipeline_init(kinc_g5_pipeline_t *pipe) {
|
||||
for (int i = 0; i < 16; ++i)
|
||||
pipe->inputLayout[i] = NULL;
|
||||
pipe->vertexShader = NULL;
|
||||
pipe->fragmentShader = NULL;
|
||||
pipe->geometryShader = NULL;
|
||||
pipe->tessellationControlShader = NULL;
|
||||
pipe->tessellationEvaluationShader = NULL;
|
||||
|
||||
pipe->cullMode = KINC_G5_CULL_MODE_NEVER;
|
||||
|
||||
pipe->depthWrite = false;
|
||||
pipe->depthMode = KINC_G5_COMPARE_MODE_ALWAYS;
|
||||
|
||||
pipe->stencilMode = KINC_G5_COMPARE_MODE_ALWAYS;
|
||||
pipe->stencilBothPass = KINC_G5_STENCIL_ACTION_KEEP;
|
||||
pipe->stencilDepthFail = KINC_G5_STENCIL_ACTION_KEEP;
|
||||
pipe->stencilFail = KINC_G5_STENCIL_ACTION_KEEP;
|
||||
pipe->stencilReferenceValue = 0;
|
||||
pipe->stencilReadMask = 0xff;
|
||||
pipe->stencilWriteMask = 0xff;
|
||||
|
||||
pipe->blend_source = KINC_G5_BLEND_ONE;
|
||||
pipe->blend_destination = KINC_G5_BLEND_ZERO;
|
||||
pipe->blend_operation = KINC_G5_BLENDOP_ADD;
|
||||
pipe->alpha_blend_source = KINC_G5_BLEND_ONE;
|
||||
pipe->alpha_blend_destination = KINC_G5_BLEND_ZERO;
|
||||
pipe->alpha_blend_operation = KINC_G5_BLENDOP_ADD;
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
pipe->colorWriteMaskRed[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
pipe->colorWriteMaskGreen[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
pipe->colorWriteMaskBlue[i] = true;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
pipe->colorWriteMaskAlpha[i] = true;
|
||||
|
||||
pipe->colorAttachmentCount = 1;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
pipe->colorAttachment[i] = KINC_G5_RENDER_TARGET_FORMAT_32BIT;
|
||||
|
||||
pipe->depthAttachmentBits = 0;
|
||||
pipe->stencilAttachmentBits = 0;
|
||||
}
|
||||
|
||||
void kinc_g5_internal_compute_pipeline_init(kinc_g5_compute_pipeline_t *pipe) {
|
||||
pipe->compute_shader = NULL;
|
||||
}
|
||||
199
Kinc/Sources/kinc/graphics5/pipeline.h
Normal file
199
Kinc/Sources/kinc/graphics5/pipeline.h
Normal file
@ -0,0 +1,199 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/pipeline.h>
|
||||
|
||||
#include <kinc/graphics5/vertexstructure.h>
|
||||
|
||||
#include "constantlocation.h"
|
||||
#include "graphics.h"
|
||||
|
||||
/*! \file pipeline.h
|
||||
\brief Provides functions for creating and using pipelines which configure the GPU for rendering.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g5_shader;
|
||||
|
||||
// identical to kinc_g4_blending_factor_t
|
||||
typedef enum {
|
||||
KINC_G5_BLEND_ONE,
|
||||
KINC_G5_BLEND_ZERO,
|
||||
KINC_G5_BLEND_SOURCE_ALPHA,
|
||||
KINC_G5_BLEND_DEST_ALPHA,
|
||||
KINC_G5_BLEND_INV_SOURCE_ALPHA,
|
||||
KINC_G5_BLEND_INV_DEST_ALPHA,
|
||||
KINC_G5_BLEND_SOURCE_COLOR,
|
||||
KINC_G5_BLEND_DEST_COLOR,
|
||||
KINC_G5_BLEND_INV_SOURCE_COLOR,
|
||||
KINC_G5_BLEND_INV_DEST_COLOR,
|
||||
KINC_G5_BLEND_CONSTANT,
|
||||
KINC_G5_BLEND_INV_CONSTANT
|
||||
} kinc_g5_blending_factor_t;
|
||||
|
||||
// identical to kinc_g4_blending_operation_t
|
||||
typedef enum {
|
||||
KINC_G5_BLENDOP_ADD,
|
||||
KINC_G5_BLENDOP_SUBTRACT,
|
||||
KINC_G5_BLENDOP_REVERSE_SUBTRACT,
|
||||
KINC_G5_BLENDOP_MIN,
|
||||
KINC_G5_BLENDOP_MAX
|
||||
} kinc_g5_blending_operation_t;
|
||||
|
||||
typedef enum kinc_g5_cull_mode { KINC_G5_CULL_MODE_CLOCKWISE, KINC_G5_CULL_MODE_COUNTERCLOCKWISE, KINC_G5_CULL_MODE_NEVER } kinc_g5_cull_mode_t;
|
||||
|
||||
typedef enum kinc_g5_compare_mode {
|
||||
KINC_G5_COMPARE_MODE_ALWAYS,
|
||||
KINC_G5_COMPARE_MODE_NEVER,
|
||||
KINC_G5_COMPARE_MODE_EQUAL,
|
||||
KINC_G5_COMPARE_MODE_NOT_EQUAL,
|
||||
KINC_G5_COMPARE_MODE_LESS,
|
||||
KINC_G5_COMPARE_MODE_LESS_EQUAL,
|
||||
KINC_G5_COMPARE_MODE_GREATER,
|
||||
KINC_G5_COMPARE_MODE_GREATER_EQUAL
|
||||
} kinc_g5_compare_mode_t;
|
||||
|
||||
typedef enum kinc_g5_stencil_action {
|
||||
KINC_G5_STENCIL_ACTION_KEEP,
|
||||
KINC_G5_STENCIL_ACTION_ZERO,
|
||||
KINC_G5_STENCIL_ACTION_REPLACE,
|
||||
KINC_G5_STENCIL_ACTION_INCREMENT,
|
||||
KINC_G5_STENCIL_ACTION_INCREMENT_WRAP,
|
||||
KINC_G5_STENCIL_ACTION_DECREMENT,
|
||||
KINC_G5_STENCIL_ACTION_DECREMENT_WRAP,
|
||||
KINC_G5_STENCIL_ACTION_INVERT
|
||||
} kinc_g5_stencil_action_t;
|
||||
|
||||
typedef struct kinc_g5_pipeline {
|
||||
kinc_g5_vertex_structure_t *inputLayout[16];
|
||||
struct kinc_g5_shader *vertexShader;
|
||||
struct kinc_g5_shader *fragmentShader;
|
||||
struct kinc_g5_shader *geometryShader;
|
||||
struct kinc_g5_shader *tessellationControlShader;
|
||||
struct kinc_g5_shader *tessellationEvaluationShader;
|
||||
|
||||
kinc_g5_cull_mode_t cullMode;
|
||||
|
||||
bool depthWrite;
|
||||
kinc_g5_compare_mode_t depthMode;
|
||||
|
||||
kinc_g5_compare_mode_t stencilMode;
|
||||
kinc_g5_stencil_action_t stencilBothPass;
|
||||
kinc_g5_stencil_action_t stencilDepthFail;
|
||||
kinc_g5_stencil_action_t stencilFail;
|
||||
int stencilReferenceValue;
|
||||
int stencilReadMask;
|
||||
int stencilWriteMask;
|
||||
|
||||
// One, Zero deactivates blending
|
||||
kinc_g5_blending_factor_t blend_source;
|
||||
kinc_g5_blending_factor_t blend_destination;
|
||||
kinc_g5_blending_operation_t blend_operation;
|
||||
kinc_g5_blending_factor_t alpha_blend_source;
|
||||
kinc_g5_blending_factor_t alpha_blend_destination;
|
||||
kinc_g5_blending_operation_t alpha_blend_operation;
|
||||
|
||||
bool colorWriteMaskRed[8]; // Per render target
|
||||
bool colorWriteMaskGreen[8];
|
||||
bool colorWriteMaskBlue[8];
|
||||
bool colorWriteMaskAlpha[8];
|
||||
|
||||
int colorAttachmentCount;
|
||||
kinc_g5_render_target_format_t colorAttachment[8];
|
||||
|
||||
int depthAttachmentBits;
|
||||
int stencilAttachmentBits;
|
||||
|
||||
bool conservativeRasterization;
|
||||
|
||||
PipelineState5Impl impl;
|
||||
} kinc_g5_pipeline_t;
|
||||
|
||||
typedef struct kinc_g5_compute_pipeline {
|
||||
struct kinc_g5_shader *compute_shader;
|
||||
|
||||
ComputePipelineState5Impl impl;
|
||||
} kinc_g5_compute_pipeline_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a pipeline.
|
||||
/// </summary>
|
||||
/// <param name="state">The pipeline to initialize</param>
|
||||
KINC_FUNC void kinc_g5_pipeline_init(kinc_g5_pipeline_t *pipeline);
|
||||
|
||||
void kinc_g5_internal_pipeline_init(kinc_g5_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a pipeline.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to destroy</param>
|
||||
KINC_FUNC void kinc_g5_pipeline_destroy(kinc_g5_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a pipeline. After a pipeline has been compiled it is finalized. It cannot be compiled again and further changes to the pipeline are ignored.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to compile</param>
|
||||
KINC_FUNC void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline);
|
||||
|
||||
#ifndef KINC_KONG
|
||||
/// <summary>
|
||||
/// Searches for a constant/uniform and returns a constant-location which can be used to change the constant/uniform.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the constant/uniform to find</param>
|
||||
/// <returns>The constant-location of the constant/uniform</returns>
|
||||
KINC_FUNC kinc_g5_constant_location_t kinc_g5_pipeline_get_constant_location(kinc_g5_pipeline_t *pipeline, const char *name);
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a texture-declaration and returns a texture-unit which can be used to assign a texture.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the texture-declaration to search for</param>
|
||||
/// <returns>The texture-unit of the texture-declaration</returns>
|
||||
KINC_FUNC kinc_g5_texture_unit_t kinc_g5_pipeline_get_texture_unit(kinc_g5_pipeline_t *pipeline, const char *name);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a compute-pipeline.
|
||||
/// </summary>
|
||||
/// <param name="state">The pipeline to initialize</param>
|
||||
KINC_FUNC void kinc_g5_compute_pipeline_init(kinc_g5_compute_pipeline_t *pipeline);
|
||||
|
||||
void kinc_g5_internal_compute_pipeline_init(kinc_g5_compute_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a compute-pipeline.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to destroy</param>
|
||||
KINC_FUNC void kinc_g5_compute_pipeline_destroy(kinc_g5_compute_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Compiles a compute-pipeline. After a pipeline has been compiled it is finalized. It cannot be compiled again and further changes to the pipeline are
|
||||
/// ignored.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to compile</param>
|
||||
KINC_FUNC void kinc_g5_compute_pipeline_compile(kinc_g5_compute_pipeline_t *pipeline);
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a constant/uniform and returns a constant-location which can be used to change the constant/uniform.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the constant/uniform to find</param>
|
||||
/// <returns>The constant-location of the constant/uniform</returns>
|
||||
KINC_FUNC kinc_g5_constant_location_t kinc_g5_compute_pipeline_get_constant_location(kinc_g5_compute_pipeline_t *pipeline, const char *name);
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a texture-declaration and returns a texture-unit which can be used to assign a texture.
|
||||
/// </summary>
|
||||
/// <param name="pipeline">The pipeline to search in</param>
|
||||
/// <param name="name">The name of the texture-declaration to search for</param>
|
||||
/// <returns>The texture-unit of the texture-declaration</returns>
|
||||
KINC_FUNC kinc_g5_texture_unit_t kinc_g5_compute_pipeline_get_texture_unit(kinc_g5_compute_pipeline_t *pipeline, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
49
Kinc/Sources/kinc/graphics5/raytrace.h
Normal file
49
Kinc/Sources/kinc/graphics5/raytrace.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
/*! \file raytrace.h
|
||||
\brief Preliminary API, requires some actual D3D12/Vulkan code to fill in
|
||||
the acceleration-structure and pipeline-details. Also requires manually
|
||||
compiled shaders. Use with caution.
|
||||
*/
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/raytrace.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct kinc_g5_command_list;
|
||||
struct kinc_g5_constant_buffer;
|
||||
struct kinc_g5_index_buffer;
|
||||
struct kinc_g5_render_target;
|
||||
struct kinc_g5_texture;
|
||||
struct kinc_g5_vertex_buffer;
|
||||
|
||||
typedef struct kinc_raytrace_pipeline {
|
||||
struct kinc_g5_constant_buffer *_constant_buffer;
|
||||
kinc_raytrace_pipeline_impl_t impl;
|
||||
} kinc_raytrace_pipeline_t;
|
||||
|
||||
KINC_FUNC void kinc_raytrace_pipeline_init(kinc_raytrace_pipeline_t *pipeline, struct kinc_g5_command_list *command_list, void *ray_shader, int ray_shader_size,
|
||||
struct kinc_g5_constant_buffer *constant_buffer);
|
||||
KINC_FUNC void kinc_raytrace_pipeline_destroy(kinc_raytrace_pipeline_t *pipeline);
|
||||
|
||||
typedef struct kinc_raytrace_acceleration_structure {
|
||||
kinc_raytrace_acceleration_structure_impl_t impl;
|
||||
} kinc_raytrace_acceleration_structure_t;
|
||||
|
||||
KINC_FUNC void kinc_raytrace_acceleration_structure_init(kinc_raytrace_acceleration_structure_t *accel, struct kinc_g5_command_list *command_list,
|
||||
struct kinc_g5_vertex_buffer *vb, struct kinc_g5_index_buffer *ib);
|
||||
KINC_FUNC void kinc_raytrace_acceleration_structure_destroy(kinc_raytrace_acceleration_structure_t *accel);
|
||||
|
||||
KINC_FUNC void kinc_raytrace_set_acceleration_structure(kinc_raytrace_acceleration_structure_t *accel);
|
||||
KINC_FUNC void kinc_raytrace_set_pipeline(kinc_raytrace_pipeline_t *pipeline);
|
||||
KINC_FUNC void kinc_raytrace_set_target(struct kinc_g5_texture *output);
|
||||
KINC_FUNC void kinc_raytrace_dispatch_rays(struct kinc_g5_command_list *command_list);
|
||||
KINC_FUNC void kinc_raytrace_copy(struct kinc_g5_command_list *command_list, struct kinc_g5_render_target *target, struct kinc_g5_texture *source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
16
Kinc/Sources/kinc/graphics5/rendertarget.c.h
Normal file
16
Kinc/Sources/kinc/graphics5/rendertarget.c.h
Normal file
@ -0,0 +1,16 @@
|
||||
#include "rendertarget.h"
|
||||
|
||||
void kinc_g5_render_target_init(kinc_g5_render_target_t *render_target, int width, int height, kinc_g5_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits) {
|
||||
kinc_g5_render_target_init_with_multisampling(render_target, width, height, format, depthBufferBits, stencilBufferBits, 1);
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_init_framebuffer(kinc_g5_render_target_t *render_target, int width, int height, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits) {
|
||||
kinc_g5_render_target_init_framebuffer_with_multisampling(render_target, width, height, format, depthBufferBits, stencilBufferBits, 1);
|
||||
}
|
||||
|
||||
void kinc_g5_render_target_init_cube(kinc_g5_render_target_t *render_target, int cubeMapSize, kinc_g5_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits) {
|
||||
kinc_g5_render_target_init_cube_with_multisampling(render_target, cubeMapSize, format, depthBufferBits, stencilBufferBits, 1);
|
||||
}
|
||||
134
Kinc/Sources/kinc/graphics5/rendertarget.h
Normal file
134
Kinc/Sources/kinc/graphics5/rendertarget.h
Normal file
@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "textureunit.h"
|
||||
|
||||
#include <kinc/backend/graphics5/rendertarget.h>
|
||||
|
||||
/*! \file rendertarget.h
|
||||
\brief Provides functions for handling render-targets.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g5_render_target_format {
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_16BIT_DEPTH,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED,
|
||||
KINC_G5_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT
|
||||
} kinc_g5_render_target_format_t;
|
||||
|
||||
typedef struct kinc_g5_render_target {
|
||||
int width;
|
||||
int height;
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
int framebuffer_index;
|
||||
bool isCubeMap;
|
||||
bool isDepthAttachment;
|
||||
RenderTarget5Impl impl;
|
||||
} kinc_g5_render_target_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a regular render-target.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init(kinc_g5_render_target_t *target, int width, int height, kinc_g5_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a regular render-target. Can fall back to a regular render-target.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <param name="samples_per_pixel"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init_with_multisampling(kinc_g5_render_target_t *target, int width, int height, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init_framebuffer(kinc_g5_render_target_t *target, int width, int height, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a multisampled framebuffer. Can fall back to a regular framebuffer.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <param name="samples_per_pixel"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init_framebuffer_with_multisampling(kinc_g5_render_target_t *target, int width, int height,
|
||||
kinc_g5_render_target_format_t format, int depthBufferBits, int stencilBufferBits,
|
||||
int samples_per_pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a render-target-cube-map.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="cubeMapSize"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init_cube(kinc_g5_render_target_t *target, int cubeMapSize, kinc_g5_render_target_format_t format, int depthBufferBits,
|
||||
int stencilBufferBits);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a multisampled render-target-cube-map. Can fall back to a regular cube-map.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="cubeMapSize"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="depthBufferBits"></param>
|
||||
/// <param name="stencilBufferBits"></param>
|
||||
/// <param name="samples_per_pixel"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_init_cube_with_multisampling(kinc_g5_render_target_t *target, int cubeMapSize, kinc_g5_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Deallocates and destroys a render-target.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to destroy</param>
|
||||
KINC_FUNC void kinc_g5_render_target_destroy(kinc_g5_render_target_t *target);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the depth and stencil-components of one render-target into another one.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to copy the data into</param>
|
||||
/// <param name="source">The render-target from which to copy the data</param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_g5_render_target_set_depth_stencil_from(kinc_g5_render_target_t *target, kinc_g5_render_target_t *source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
19
Kinc/Sources/kinc/graphics5/sampler.c.h
Normal file
19
Kinc/Sources/kinc/graphics5/sampler.c.h
Normal file
@ -0,0 +1,19 @@
|
||||
#include "sampler.h"
|
||||
|
||||
void kinc_g5_sampler_options_set_defaults(kinc_g5_sampler_options_t *options) {
|
||||
options->u_addressing = KINC_G5_TEXTURE_ADDRESSING_CLAMP;
|
||||
options->v_addressing = KINC_G5_TEXTURE_ADDRESSING_CLAMP;
|
||||
options->w_addressing = KINC_G5_TEXTURE_ADDRESSING_CLAMP;
|
||||
|
||||
options->magnification_filter = KINC_G5_TEXTURE_FILTER_POINT;
|
||||
options->minification_filter = KINC_G5_TEXTURE_FILTER_POINT;
|
||||
options->mipmap_filter = KINC_G5_MIPMAP_FILTER_POINT;
|
||||
|
||||
options->lod_min_clamp = 0.0f;
|
||||
options->lod_max_clamp = 32.0f;
|
||||
|
||||
options->is_comparison = false;
|
||||
options->compare_mode = KINC_G5_COMPARE_MODE_ALWAYS;
|
||||
|
||||
options->max_anisotropy = 1;
|
||||
}
|
||||
78
Kinc/Sources/kinc/graphics5/sampler.h
Normal file
78
Kinc/Sources/kinc/graphics5/sampler.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics5/sampler.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
|
||||
/*! \file sampler.h
|
||||
\brief Provides functions for sampler objects.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g5_texture_addressing {
|
||||
KINC_G5_TEXTURE_ADDRESSING_REPEAT,
|
||||
KINC_G5_TEXTURE_ADDRESSING_MIRROR,
|
||||
KINC_G5_TEXTURE_ADDRESSING_CLAMP,
|
||||
KINC_G5_TEXTURE_ADDRESSING_BORDER
|
||||
} kinc_g5_texture_addressing_t;
|
||||
|
||||
typedef enum kinc_g5_texture_filter {
|
||||
KINC_G5_TEXTURE_FILTER_POINT,
|
||||
KINC_G5_TEXTURE_FILTER_LINEAR,
|
||||
KINC_G5_TEXTURE_FILTER_ANISOTROPIC
|
||||
} kinc_g5_texture_filter_t;
|
||||
|
||||
typedef enum kinc_g5_mipmap_filter {
|
||||
KINC_G5_MIPMAP_FILTER_NONE,
|
||||
KINC_G5_MIPMAP_FILTER_POINT,
|
||||
KINC_G5_MIPMAP_FILTER_LINEAR // linear texture filter + linear mip filter -> trilinear filter
|
||||
} kinc_g5_mipmap_filter_t;
|
||||
|
||||
typedef struct kinc_g5_sampler_options {
|
||||
kinc_g5_texture_addressing_t u_addressing;
|
||||
kinc_g5_texture_addressing_t v_addressing;
|
||||
kinc_g5_texture_addressing_t w_addressing;
|
||||
|
||||
kinc_g5_texture_filter_t minification_filter;
|
||||
kinc_g5_texture_filter_t magnification_filter;
|
||||
kinc_g5_mipmap_filter_t mipmap_filter;
|
||||
|
||||
float lod_min_clamp;
|
||||
float lod_max_clamp;
|
||||
|
||||
uint16_t max_anisotropy;
|
||||
|
||||
bool is_comparison;
|
||||
kinc_g5_compare_mode_t compare_mode;
|
||||
} kinc_g5_sampler_options_t;
|
||||
|
||||
typedef struct kinc_g5_sampler {
|
||||
kinc_g5_sampler_impl_t impl;
|
||||
} kinc_g5_sampler_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the passed options-object with the default-options.
|
||||
/// </summary>
|
||||
/// <param name="options">The options-object for which the default-options will be set</param>
|
||||
KINC_FUNC void kinc_g5_sampler_options_set_defaults(kinc_g5_sampler_options_t *options);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a sampler-object.
|
||||
///
|
||||
/// On platforms such as older OpenGL not all sampler attributes may be available.
|
||||
/// </summary>
|
||||
/// <param name="sampler">Pointer to the sampler object to initialize</param>
|
||||
/// <param name="descriptor">Options for the sampler</param>
|
||||
KINC_FUNC void kinc_g5_sampler_init(kinc_g5_sampler_t *sampler, const kinc_g5_sampler_options_t *options);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a sampler-object.
|
||||
/// </summary>
|
||||
/// <param name="sampler">The sampler-object to destroy</param>
|
||||
KINC_FUNC void kinc_g5_sampler_destroy(kinc_g5_sampler_t *sampler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
50
Kinc/Sources/kinc/graphics5/shader.h
Normal file
50
Kinc/Sources/kinc/graphics5/shader.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/shader.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*! \file shader.h
|
||||
\brief Provides functions for creating and destroying shaders.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_g5_shader_type {
|
||||
KINC_G5_SHADER_TYPE_FRAGMENT,
|
||||
KINC_G5_SHADER_TYPE_VERTEX,
|
||||
KINC_G5_SHADER_TYPE_COMPUTE,
|
||||
KINC_G5_SHADER_TYPE_GEOMETRY,
|
||||
KINC_G5_SHADER_TYPE_TESSELLATION_CONTROL,
|
||||
KINC_G5_SHADER_TYPE_TESSELLATION_EVALUATION,
|
||||
|
||||
KINC_G5_SHADER_TYPE_COUNT
|
||||
} kinc_g5_shader_type_t;
|
||||
|
||||
typedef struct kinc_g5_shader {
|
||||
Shader5Impl impl;
|
||||
} kinc_g5_shader_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a shader based on system-specific shader-data. The system-specific shader-data is usually created per system by the krafix-shader-compiler which
|
||||
/// is automatically called by kincmake.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to initialize</param>
|
||||
/// <param name="data">The system-specific shader-data</param>
|
||||
/// <param name="length">The length of the system-specific shader-data in bytes</param>
|
||||
/// <param name="type">The type of the shader</param>
|
||||
KINC_FUNC void kinc_g5_shader_init(kinc_g5_shader_t *shader, const void *source, size_t length, kinc_g5_shader_type_t type);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a shader.
|
||||
/// </summary>
|
||||
/// <param name="shader">The shader to destroy</param>
|
||||
KINC_FUNC void kinc_g5_shader_destroy(kinc_g5_shader_t *shader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
32
Kinc/Sources/kinc/graphics5/texture.c.h
Normal file
32
Kinc/Sources/kinc/graphics5/texture.c.h
Normal file
@ -0,0 +1,32 @@
|
||||
#include "texture.h"
|
||||
|
||||
/*
|
||||
Graphics5::Texture::Texture(Kore::Reader& reader, const char* format, bool readable) : Image(reader, format, readable) {
|
||||
_init(format, readable);
|
||||
}
|
||||
|
||||
Graphics5::Texture::Texture(const char* filename, bool readable) {
|
||||
FileReader reader(filename);
|
||||
Image::init(reader, filename, readable);
|
||||
_init(filename, readable);
|
||||
}
|
||||
|
||||
Graphics5::Texture::Texture(void* data, int size, const char* format, bool readable) {
|
||||
BufferReader reader(data, size);
|
||||
Image::init(reader, format, readable);
|
||||
_init(format, readable);
|
||||
}
|
||||
|
||||
Graphics5::Texture::Texture(void* data, int width, int height, int format, bool readable) : Image(data, width, height, Image::Format(format), readable) {
|
||||
_init("", readable);
|
||||
}
|
||||
*/
|
||||
|
||||
bool kinc_g5_texture_unit_equals(kinc_g5_texture_unit_t *unit1, kinc_g5_texture_unit_t *unit2) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit1->stages[i] != unit2->stages[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
98
Kinc/Sources/kinc/graphics5/texture.h
Normal file
98
Kinc/Sources/kinc/graphics5/texture.h
Normal file
@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/image.h>
|
||||
|
||||
#include "textureunit.h"
|
||||
|
||||
#include <kinc/backend/graphics5/texture.h>
|
||||
|
||||
/*! \file texture.h
|
||||
\brief Provides functions for handling textures.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_texture {
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
kinc_image_format_t format;
|
||||
Texture5Impl impl;
|
||||
} kinc_g5_texture_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture without copying any data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="width">The width of the texture to create</param>
|
||||
/// <param name="height">The height of the texture to create</param>
|
||||
/// <param name="format">The format of the texture to create</param>
|
||||
KINC_FUNC void kinc_g5_texture_init(kinc_g5_texture_t *texture, int width, int height, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a 3d-texture without copying any data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="width">The width of the texture to create</param>
|
||||
/// <param name="height">The height of the texture to create</param>
|
||||
/// <param name="depth">The depth of the texture to create</param>
|
||||
/// <param name="format">The format of the texture to create</param>
|
||||
KINC_FUNC void kinc_g5_texture_init3d(kinc_g5_texture_t *texture, int width, int height, int depth, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Allocates and initializes a texture and copies image-data into it.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to initialize</param>
|
||||
/// <param name="image">The image which's data is copied into the texture</param>
|
||||
KINC_FUNC void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *image);
|
||||
|
||||
// void kinc_g5_texture_init_from_encoded_data(kinc_g5_texture_t *texture, void *data, int size, const char *format, bool readable);
|
||||
// void kinc_g5_texture_init_from_data(kinc_g5_texture_t *texture, void *data, int width, int height, int format, bool readable);
|
||||
|
||||
KINC_FUNC void kinc_g5_texture_init_non_sampled_access(kinc_g5_texture_t *texture, int width, int height, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Deallocates and destroys a texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to destroy</param>
|
||||
KINC_FUNC void kinc_g5_texture_destroy(kinc_g5_texture_t *texture);
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
KINC_FUNC void kinc_g5_texture_init_from_id(kinc_g5_texture_t *texture, unsigned texid);
|
||||
#endif
|
||||
|
||||
KINC_FUNC uint8_t *kinc_g5_texture_lock(kinc_g5_texture_t *texture);
|
||||
|
||||
KINC_FUNC void kinc_g5_texture_unlock(kinc_g5_texture_t *texture);
|
||||
|
||||
/// <summary>
|
||||
/// Clears parts of a texture to a color.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_g5_texture_clear(kinc_g5_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color);
|
||||
|
||||
#if defined(KORE_IOS) || defined(KORE_MACOS)
|
||||
KINC_FUNC void kinc_g5_texture_upload(kinc_g5_texture_t *texture, uint8_t *data);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Generates the mipmap-chain for a texture.
|
||||
/// </summary>
|
||||
/// <param name="renderTarget">The render-target to create the mipmaps for</param>
|
||||
/// <param name="levels">The number of mipmap-levels to generate</param>
|
||||
KINC_FUNC void kinc_g5_texture_generate_mipmaps(kinc_g5_texture_t *texture, int levels);
|
||||
|
||||
KINC_FUNC void kinc_g5_texture_set_mipmap(kinc_g5_texture_t *texture, kinc_image_t *mipmap, int level);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the stride of the first mipmap-layer of the texture in bytes.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture to figure out the stride for</param>
|
||||
/// <returns>The stride of the first mipmap-layer in bytes</returns>
|
||||
KINC_FUNC int kinc_g5_texture_stride(kinc_g5_texture_t *texture);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
24
Kinc/Sources/kinc/graphics5/textureunit.h
Normal file
24
Kinc/Sources/kinc/graphics5/textureunit.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/backend/graphics5/texture.h>
|
||||
#include <kinc/graphics5/shader.h>
|
||||
|
||||
/*! \file textureunit.h
|
||||
\brief Provides a texture-unit-struct which is used for setting textures in a shader.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_texture_unit {
|
||||
int stages[KINC_G5_SHADER_TYPE_COUNT];
|
||||
} kinc_g5_texture_unit_t;
|
||||
|
||||
bool kinc_g5_texture_unit_equals(kinc_g5_texture_unit_t *unit1, kinc_g5_texture_unit_t *unit2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
85
Kinc/Sources/kinc/graphics5/vertexbuffer.h
Normal file
85
Kinc/Sources/kinc/graphics5/vertexbuffer.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include "vertexstructure.h"
|
||||
|
||||
#include <kinc/backend/graphics5/vertexbuffer.h>
|
||||
|
||||
/*! \file vertexbuffer.h
|
||||
\brief Provides functions for setting up and using vertex-buffers.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_g5_vertex_buffer {
|
||||
VertexBuffer5Impl impl;
|
||||
} kinc_g5_vertex_buffer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Allocate and initialize a vertex-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to initialize</param>
|
||||
/// <param name="count">The number of vertices in the buffer</param>
|
||||
/// <param name="structure">The structure of the buffer</param>
|
||||
/// <param name="gpu_memory">If true, the vertex-buffer will reside in gpu-memory which will make it slower to update but faster to use</param>
|
||||
/// <param name="instance_data_step_rate">The step-rate for instanced-rendering - use 0 if instanced-rendering will not be used with this buffer</param>
|
||||
KINC_FUNC void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int count, kinc_g5_vertex_structure_t *structure, bool gpu_memory,
|
||||
int instance_data_step_rate);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a vertex-buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to destroy</param>
|
||||
KINC_FUNC void kinc_g5_vertex_buffer_destroy(kinc_g5_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks all of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <returns>The contents of the buffer</returns>
|
||||
KINC_FUNC float *kinc_g5_vertex_buffer_lock_all(kinc_g5_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Locks part of a vertex-buffer to modify its contents.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to lock</param>
|
||||
/// <param name="start">The index of the first vertex to lock</param>
|
||||
/// <param name="count">The number of vertices to lock</param>
|
||||
/// <returns>The contents of the buffer, starting at start</returns>
|
||||
KINC_FUNC float *kinc_g5_vertex_buffer_lock(kinc_g5_vertex_buffer_t *buffer, int start, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Unlock all of a vertex-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
KINC_FUNC void kinc_g5_vertex_buffer_unlock_all(kinc_g5_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks part of a vertex-buffer so the changed contents can be used.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to unlock</param>
|
||||
/// <param name="count">The number of vertices to unlock, starting from the start-vertex from the previous lock-call</param>
|
||||
KINC_FUNC void kinc_g5_vertex_buffer_unlock(kinc_g5_vertex_buffer_t *buffer, int count);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of vertices in a buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the number of vertices for</param>
|
||||
/// <returns>The number of vertices</returns>
|
||||
KINC_FUNC int kinc_g5_vertex_buffer_count(kinc_g5_vertex_buffer_t *buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the stride aka the size of one vertex of the buffer in bytes.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to figure out the stride for</param>
|
||||
/// <returns>The stride of the buffer in bytes</returns>
|
||||
KINC_FUNC int kinc_g5_vertex_buffer_stride(kinc_g5_vertex_buffer_t *buffer);
|
||||
|
||||
int kinc_g5_internal_vertex_buffer_set(kinc_g5_vertex_buffer_t *buffer, int offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
45
Kinc/Sources/kinc/graphics5/vertexstructure.h
Normal file
45
Kinc/Sources/kinc/graphics5/vertexstructure.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
|
||||
/*! \file vertexstructure.h
|
||||
\brief Provides types for setting up the structure of vertices in a vertex-buffer.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef kinc_g4_vertex_data_t kinc_g5_vertex_data_t;
|
||||
|
||||
// typedef kinc_g4_vertex_attribute_t kinc_g5_vertex_attribute_t;
|
||||
|
||||
typedef kinc_g4_vertex_element_t kinc_g5_vertex_element_t;
|
||||
|
||||
typedef kinc_g4_vertex_structure_t kinc_g5_vertex_structure_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a vertex-structure.
|
||||
/// </summary>
|
||||
/// <param name="structure">The structure to initialize</param>
|
||||
/// <returns></returns>
|
||||
static inline void kinc_g5_vertex_structure_init(kinc_g5_vertex_structure_t *structure) {
|
||||
kinc_g4_vertex_structure_init(structure);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an element to a vertex-structure.
|
||||
/// </summary>
|
||||
/// <param name="structure">The structure to add an element to</param>
|
||||
/// <param name="name">The name to use for the new element</param>
|
||||
/// <param name="data">The type of data to assign for the new element</param>
|
||||
/// <returns></returns>
|
||||
static inline void kinc_g5_vertex_structure_add(kinc_g5_vertex_structure_t *structure, const char *name, kinc_g5_vertex_data_t data) {
|
||||
kinc_g4_vertex_structure_add(structure, name, data);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
754
Kinc/Sources/kinc/image.h
Normal file
754
Kinc/Sources/kinc/image.h
Normal file
@ -0,0 +1,754 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*! \file image.h
|
||||
\brief Functionality for creating and loading images. Image loading supports PNG, JPEG and the custom K format. K files can contain image data that uses
|
||||
texture-compression (see kinc_image_compression).
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_image_compression {
|
||||
KINC_IMAGE_COMPRESSION_NONE,
|
||||
KINC_IMAGE_COMPRESSION_DXT5,
|
||||
KINC_IMAGE_COMPRESSION_ASTC,
|
||||
KINC_IMAGE_COMPRESSION_PVRTC
|
||||
} kinc_image_compression_t;
|
||||
|
||||
typedef enum kinc_image_format {
|
||||
KINC_IMAGE_FORMAT_RGBA32,
|
||||
KINC_IMAGE_FORMAT_GREY8,
|
||||
KINC_IMAGE_FORMAT_RGB24,
|
||||
KINC_IMAGE_FORMAT_RGBA128,
|
||||
KINC_IMAGE_FORMAT_RGBA64,
|
||||
KINC_IMAGE_FORMAT_A32,
|
||||
KINC_IMAGE_FORMAT_BGRA32,
|
||||
KINC_IMAGE_FORMAT_A16
|
||||
} kinc_image_format_t;
|
||||
|
||||
typedef struct kinc_image {
|
||||
int width, height, depth;
|
||||
kinc_image_format_t format;
|
||||
unsigned internal_format;
|
||||
kinc_image_compression_t compression;
|
||||
void *data;
|
||||
int data_size;
|
||||
} kinc_image_t;
|
||||
|
||||
typedef struct kinc_image_read_callbacks {
|
||||
int (*read)(void *user_data, void *data, size_t size);
|
||||
void (*seek)(void *user_data, int pos);
|
||||
int (*pos)(void *user_data);
|
||||
size_t (*size)(void *user_data);
|
||||
} kinc_image_read_callbacks_t;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a 2D kinc_image in the provided memory.
|
||||
/// </summary>
|
||||
/// <returns>The size that's occupied by the image in memory in bytes</returns>
|
||||
KINC_FUNC size_t kinc_image_init(kinc_image_t *image, void *memory, int width, int height, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a 3D kinc_image in the provided memory.
|
||||
/// </summary>
|
||||
/// <returns>The size that's occupied by the image in memory in bytes</returns>
|
||||
KINC_FUNC size_t kinc_image_init3d(kinc_image_t *image, void *memory, int width, int height, int depth, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Peeks into an image file and figures out the size it will occupy in memory.
|
||||
/// </summary>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_size_from_file(const char *filename);
|
||||
|
||||
/// <summary>
|
||||
/// Peeks into an image that is loaded via callback functions and figures out the size it will occupy in memory.
|
||||
/// </summary>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_size_from_callbacks(kinc_image_read_callbacks_t callbacks, void *user_data, const char *format);
|
||||
|
||||
/// <summary>
|
||||
/// Peeks into an image file that resides in memory and figures out the size it will occupy in memory once it is uncompressed.
|
||||
/// </summary>
|
||||
/// <param name="data">The encoded data</param>
|
||||
/// <param name="data_size">The size of the encoded data</param>
|
||||
/// <param name="format_hint">Something like "png" can help, it also works to just put in the filename</param>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_size_from_encoded_bytes(void *data, size_t data_size, const char *format_hint);
|
||||
|
||||
/// <summary>
|
||||
/// Loads an image from a file.
|
||||
/// </summary>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_init_from_file(kinc_image_t *image, void *memory, const char *filename);
|
||||
|
||||
/// <summary>
|
||||
/// Loads an image file using callbacks.
|
||||
/// </summary>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_init_from_callbacks(kinc_image_t *image, void *memory, kinc_image_read_callbacks_t callbacks, void *user_data, const char *format);
|
||||
|
||||
/// <summary>
|
||||
/// Loads an image file from a memory.
|
||||
/// </summary>
|
||||
/// <returns>The memory size in bytes that will be used when loading the image</returns>
|
||||
KINC_FUNC size_t kinc_image_init_from_encoded_bytes(kinc_image_t *image, void *memory, void *data, size_t data_size, const char *format);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a 2D image from memory.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_image_init_from_bytes(kinc_image_t *image, void *data, int width, int height, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a 3D image from memory.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_image_init_from_bytes3d(kinc_image_t *image, void *data, int width, int height, int depth, kinc_image_format_t format);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys an image. This does not free the user-provided memory.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_image_destroy(kinc_image_t *image);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color value of a 32 bit pixel. If this doesn't fit the format of the image please use kinc_image_at_raw instead.
|
||||
/// </summary>
|
||||
/// <returns>One 32 bit color value</returns>
|
||||
KINC_FUNC uint32_t kinc_image_at(kinc_image_t *image, int x, int y);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the color-data of one pixel.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the color-data of the pixel pointed to by x and y</returns>
|
||||
KINC_FUNC void *kinc_image_at_raw(kinc_image_t *image, int x, int y);
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to the image data.
|
||||
/// </summary>
|
||||
/// <returns>A pointer to the image data</returns>
|
||||
KINC_FUNC uint8_t *kinc_image_get_pixels(kinc_image_t *image);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size in bytes of a single pixel for a given image format.
|
||||
/// </summary>
|
||||
/// <returns>The size of one pixel in bytes</returns>
|
||||
KINC_FUNC int kinc_image_format_sizeof(kinc_image_format_t format);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#ifdef KORE_LZ4X
|
||||
#include <kinc/libs/lz4x.h>
|
||||
#else
|
||||
#include <kinc/io/lz4/lz4.h>
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#endif
|
||||
#include <kinc/log.h>
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
#include <kinc/math/core.h>
|
||||
#define KINC_IMPLEMENTATION
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define BUFFER_SIZE 4096 * 4096 * 4
|
||||
static uint8_t buffer[BUFFER_SIZE];
|
||||
static size_t buffer_offset = 0;
|
||||
static uint8_t *last_allocated_pointer = 0;
|
||||
|
||||
static void *buffer_malloc(size_t size) {
|
||||
uint8_t *current = &buffer[buffer_offset];
|
||||
buffer_offset += size + sizeof(size_t);
|
||||
if (buffer_offset > BUFFER_SIZE) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Not enough memory on image.c Buffer.");
|
||||
return NULL;
|
||||
}
|
||||
*(size_t *)current = size;
|
||||
last_allocated_pointer = current + sizeof(size_t);
|
||||
return current + sizeof(size_t);
|
||||
}
|
||||
|
||||
static void *buffer_realloc(void *p, size_t size) {
|
||||
if (p == NULL) {
|
||||
return buffer_malloc(size);
|
||||
}
|
||||
uint8_t *old_pointer = (uint8_t *)p;
|
||||
size_t old_size = *(size_t *)(old_pointer - sizeof(size_t));
|
||||
if (size <= old_size) {
|
||||
return old_pointer;
|
||||
}
|
||||
else {
|
||||
if (last_allocated_pointer == old_pointer) {
|
||||
size_t last_size = &buffer[buffer_offset] - old_pointer;
|
||||
size_t size_diff = size - last_size;
|
||||
buffer_offset += size_diff + sizeof(size_t);
|
||||
return old_pointer;
|
||||
}
|
||||
uint8_t *new_pointer = (uint8_t *)buffer_malloc(size);
|
||||
if (new_pointer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(new_pointer, old_pointer, old_size < size ? old_size : size);
|
||||
return new_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
static void buffer_free(void *p) {}
|
||||
|
||||
#define STBI_MALLOC(sz) buffer_malloc(sz)
|
||||
#define STBI_REALLOC(p, newsz) buffer_realloc(p, newsz)
|
||||
#define STBI_FREE(p) buffer_free(p)
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_STATIC
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
#include <kinc/libs/stb_image.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
kinc_image_read_callbacks_t callbacks;
|
||||
void *user_data;
|
||||
} read_data;
|
||||
|
||||
// fill 'data' with 'size' bytes. return number of bytes actually read
|
||||
static int stb_read(void *user, char *data, int size) {
|
||||
read_data *reader = (read_data *)user;
|
||||
return reader->callbacks.read(reader->user_data, data, size);
|
||||
}
|
||||
|
||||
// skip the next 'n' bytes, or 'unget' the last -n bytes if negative
|
||||
static void stb_skip(void *user, int n) {
|
||||
read_data *reader = (read_data *)user;
|
||||
reader->callbacks.seek(reader->user_data, reader->callbacks.pos(reader->user_data) + n);
|
||||
}
|
||||
|
||||
// returns nonzero if we are at end of file/data
|
||||
static int stb_eof(void *user) {
|
||||
read_data *reader = (read_data *)user;
|
||||
return reader->callbacks.pos(reader->user_data) == reader->callbacks.size(reader->user_data);
|
||||
}
|
||||
|
||||
static _Bool endsWith(const char *str, const char *suffix) {
|
||||
if (str == NULL || suffix == NULL)
|
||||
return 0;
|
||||
size_t lenstr = strlen(str);
|
||||
size_t lensuffix = strlen(suffix);
|
||||
if (lensuffix > lenstr)
|
||||
return 0;
|
||||
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
|
||||
}
|
||||
|
||||
static size_t loadImageSize(kinc_image_read_callbacks_t callbacks, void *user_data, const char *filename) {
|
||||
if (endsWith(filename, "k")) {
|
||||
uint8_t data[4];
|
||||
callbacks.read(user_data, data, 4);
|
||||
int width = kinc_read_s32le(data);
|
||||
callbacks.read(user_data, data, 4);
|
||||
int height = kinc_read_s32le(data);
|
||||
|
||||
char fourcc[5];
|
||||
callbacks.read(user_data, fourcc, 4);
|
||||
fourcc[4] = 0;
|
||||
|
||||
if (strcmp(fourcc, "LZ4 ") == 0) {
|
||||
return width * height * 4;
|
||||
}
|
||||
else if (strcmp(fourcc, "LZ4F") == 0) {
|
||||
return width * height * 16;
|
||||
}
|
||||
else if (strcmp(fourcc, "ASTC") == 0) {
|
||||
return width * height * 4; // just an upper bound
|
||||
}
|
||||
else if (strcmp(fourcc, "DXT5") == 0) {
|
||||
return width * height; // just an upper bound
|
||||
}
|
||||
else {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Unknown fourcc in .k file.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (endsWith(filename, "pvr")) {
|
||||
uint8_t data[4];
|
||||
callbacks.read(user_data, data, 4); // version
|
||||
callbacks.read(user_data, data, 4); // flags
|
||||
callbacks.read(user_data, data, 4); // pixelFormat1
|
||||
callbacks.read(user_data, data, 4); // colourSpace
|
||||
callbacks.read(user_data, data, 4); // channelType
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t hh = kinc_read_u32le(data);
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t ww = kinc_read_u32le(data);
|
||||
|
||||
return ww * hh / 2;
|
||||
}
|
||||
else if (endsWith(filename, "hdr")) {
|
||||
stbi_io_callbacks stbi_callbacks;
|
||||
stbi_callbacks.eof = stb_eof;
|
||||
stbi_callbacks.read = stb_read;
|
||||
stbi_callbacks.skip = stb_skip;
|
||||
|
||||
read_data reader;
|
||||
reader.callbacks = callbacks;
|
||||
reader.user_data = user_data;
|
||||
|
||||
int x, y, comp;
|
||||
stbi_info_from_callbacks(&stbi_callbacks, &reader, &x, &y, &comp);
|
||||
buffer_offset = 0;
|
||||
return x * y * 16;
|
||||
}
|
||||
else {
|
||||
stbi_io_callbacks stbi_callbacks;
|
||||
stbi_callbacks.eof = stb_eof;
|
||||
stbi_callbacks.read = stb_read;
|
||||
stbi_callbacks.skip = stb_skip;
|
||||
|
||||
read_data reader;
|
||||
reader.callbacks = callbacks;
|
||||
reader.user_data = user_data;
|
||||
|
||||
int x, y, comp;
|
||||
stbi_info_from_callbacks(&stbi_callbacks, &reader, &x, &y, &comp);
|
||||
buffer_offset = 0;
|
||||
return x * y * 4;
|
||||
}
|
||||
}
|
||||
|
||||
static bool loadImage(kinc_image_read_callbacks_t callbacks, void *user_data, const char *filename, uint8_t *output, int *outputSize, int *width, int *height,
|
||||
kinc_image_compression_t *compression, kinc_image_format_t *format, unsigned *internalFormat) {
|
||||
*format = KINC_IMAGE_FORMAT_RGBA32;
|
||||
if (endsWith(filename, "k")) {
|
||||
uint8_t data[4];
|
||||
callbacks.read(user_data, data, 4);
|
||||
*width = kinc_read_s32le(data);
|
||||
callbacks.read(user_data, data, 4);
|
||||
*height = kinc_read_s32le(data);
|
||||
|
||||
char fourcc[5];
|
||||
callbacks.read(user_data, fourcc, 4);
|
||||
fourcc[4] = 0;
|
||||
|
||||
int compressedSize = (int)callbacks.size(user_data) - 12;
|
||||
|
||||
if (strcmp(fourcc, "LZ4 ") == 0) {
|
||||
*compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
*internalFormat = 0;
|
||||
*outputSize = *width * *height * 4;
|
||||
callbacks.read(user_data, buffer, compressedSize);
|
||||
LZ4_decompress_safe((char *)buffer, (char *)output, compressedSize, *outputSize);
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(fourcc, "LZ4F") == 0) {
|
||||
*compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
*internalFormat = 0;
|
||||
*outputSize = *width * *height * 16;
|
||||
callbacks.read(user_data, buffer, compressedSize);
|
||||
LZ4_decompress_safe((char *)buffer, (char *)output, compressedSize, *outputSize);
|
||||
*format = KINC_IMAGE_FORMAT_RGBA128;
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(fourcc, "ASTC") == 0) {
|
||||
*compression = KINC_IMAGE_COMPRESSION_ASTC;
|
||||
*outputSize = *width * *height * 4;
|
||||
callbacks.read(user_data, buffer, compressedSize);
|
||||
*outputSize = LZ4_decompress_safe((char *)buffer, (char *)output, compressedSize, *outputSize);
|
||||
|
||||
uint8_t blockdim_x = 6;
|
||||
uint8_t blockdim_y = 6;
|
||||
*internalFormat = (blockdim_x << 8) + blockdim_y;
|
||||
|
||||
return true;
|
||||
|
||||
/*int index = 0;
|
||||
index += 4; // magic
|
||||
u8 blockdim_x = astcdata[index++];
|
||||
u8 blockdim_y = astcdata[index++];
|
||||
++index; // blockdim_z
|
||||
internalFormat = (blockdim_x << 8) + blockdim_y;
|
||||
u8 xsize[4];
|
||||
xsize[0] = astcdata[index++];
|
||||
xsize[1] = astcdata[index++];
|
||||
xsize[2] = astcdata[index++];
|
||||
xsize[3] = 0;
|
||||
this->width = *(unsigned*)&xsize[0];
|
||||
u8 ysize[4];
|
||||
ysize[0] = astcdata[index++];
|
||||
ysize[1] = astcdata[index++];
|
||||
ysize[2] = astcdata[index++];
|
||||
ysize[3] = 0;
|
||||
this->height = *(unsigned*)&ysize[0];
|
||||
u8 zsize[3];
|
||||
zsize[0] = astcdata[index++];
|
||||
zsize[1] = astcdata[index++];
|
||||
zsize[2] = astcdata[index++];
|
||||
u8* all = (u8*)astcdata[index];
|
||||
dataSize -= 16;
|
||||
this->data = new u8[dataSize];
|
||||
for (int i = 0; i < dataSize; ++i) {
|
||||
data[i] = all[16 + i];
|
||||
}
|
||||
free(astcdata);*/
|
||||
}
|
||||
else if (strcmp(fourcc, "DXT5") == 0) {
|
||||
*compression = KINC_IMAGE_COMPRESSION_DXT5;
|
||||
*outputSize = *width * *height;
|
||||
callbacks.read(user_data, buffer, compressedSize);
|
||||
*outputSize = LZ4_decompress_safe((char *)buffer, (char *)output, compressedSize, *outputSize);
|
||||
*internalFormat = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Unknown fourcc in .k file.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (endsWith(filename, "pvr")) {
|
||||
uint8_t data[4];
|
||||
callbacks.read(user_data, data, 4); // version
|
||||
callbacks.read(user_data, data, 4); // flags
|
||||
callbacks.read(user_data, data, 4); // pixelFormat1
|
||||
callbacks.read(user_data, data, 4); // colourSpace
|
||||
callbacks.read(user_data, data, 4); // channelType
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t hh = kinc_read_u32le(data);
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t ww = kinc_read_u32le(data);
|
||||
callbacks.read(user_data, data, 4); // depth
|
||||
callbacks.read(user_data, data, 4); // numSurfaces
|
||||
callbacks.read(user_data, data, 4); // numFaces
|
||||
callbacks.read(user_data, data, 4); // mipMapCount
|
||||
callbacks.read(user_data, data, 4);
|
||||
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t meta1fourcc = kinc_read_u32le(data);
|
||||
callbacks.read(user_data, data, 4); // meta1key
|
||||
callbacks.read(user_data, data, 4); // meta1size
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t meta1data = kinc_read_u32le(data);
|
||||
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t meta2fourcc = kinc_read_u32le(data);
|
||||
callbacks.read(user_data, data, 4); // meta2key
|
||||
callbacks.read(user_data, data, 4); // meta2size
|
||||
callbacks.read(user_data, data, 4);
|
||||
uint32_t meta2data = kinc_read_u32le(data);
|
||||
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
if (meta1fourcc == 0)
|
||||
w = meta1data;
|
||||
if (meta1fourcc == 1)
|
||||
h = meta1data;
|
||||
if (meta2fourcc == 0)
|
||||
w = meta2data;
|
||||
if (meta2fourcc == 1)
|
||||
h = meta2data;
|
||||
|
||||
*width = w;
|
||||
*height = h;
|
||||
*compression = KINC_IMAGE_COMPRESSION_PVRTC;
|
||||
*internalFormat = 0;
|
||||
|
||||
*outputSize = ww * hh / 2;
|
||||
callbacks.read(user_data, output, *outputSize);
|
||||
return true;
|
||||
}
|
||||
else if (endsWith(filename, "hdr")) {
|
||||
*compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
*internalFormat = 0;
|
||||
|
||||
stbi_io_callbacks stbi_callbacks;
|
||||
stbi_callbacks.eof = stb_eof;
|
||||
stbi_callbacks.read = stb_read;
|
||||
stbi_callbacks.skip = stb_skip;
|
||||
|
||||
read_data reader;
|
||||
reader.callbacks = callbacks;
|
||||
reader.user_data = user_data;
|
||||
|
||||
int comp;
|
||||
float *uncompressed = stbi_loadf_from_callbacks(&stbi_callbacks, &reader, width, height, &comp, 4);
|
||||
if (uncompressed == NULL) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, stbi_failure_reason());
|
||||
return false;
|
||||
}
|
||||
*outputSize = *width * *height * 16;
|
||||
memcpy(output, uncompressed, *outputSize);
|
||||
*format = KINC_IMAGE_FORMAT_RGBA128;
|
||||
buffer_offset = 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
*compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
*internalFormat = 0;
|
||||
|
||||
stbi_io_callbacks stbi_callbacks;
|
||||
stbi_callbacks.eof = stb_eof;
|
||||
stbi_callbacks.read = stb_read;
|
||||
stbi_callbacks.skip = stb_skip;
|
||||
|
||||
read_data reader;
|
||||
reader.callbacks = callbacks;
|
||||
reader.user_data = user_data;
|
||||
|
||||
int comp;
|
||||
uint8_t *uncompressed = stbi_load_from_callbacks(&stbi_callbacks, &reader, width, height, &comp, 4);
|
||||
if (uncompressed == NULL) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, stbi_failure_reason());
|
||||
return false;
|
||||
}
|
||||
for (int y = 0; y < *height; ++y) {
|
||||
for (int x = 0; x < *width; ++x) {
|
||||
float r = uncompressed[y * *width * 4 + x * 4 + 0] / 255.0f;
|
||||
float g = uncompressed[y * *width * 4 + x * 4 + 1] / 255.0f;
|
||||
float b = uncompressed[y * *width * 4 + x * 4 + 2] / 255.0f;
|
||||
float a = uncompressed[y * *width * 4 + x * 4 + 3] / 255.0f;
|
||||
r *= a;
|
||||
g *= a;
|
||||
b *= a;
|
||||
output[y * *width * 4 + x * 4 + 0] = (uint8_t)kinc_round(r * 255.0f);
|
||||
output[y * *width * 4 + x * 4 + 1] = (uint8_t)kinc_round(g * 255.0f);
|
||||
output[y * *width * 4 + x * 4 + 2] = (uint8_t)kinc_round(b * 255.0f);
|
||||
output[y * *width * 4 + x * 4 + 3] = (uint8_t)kinc_round(a * 255.0f);
|
||||
}
|
||||
}
|
||||
*outputSize = *width * *height * 4;
|
||||
buffer_offset = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_image_format_sizeof(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return 16;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return 8;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return 2;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return 1;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return 3;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// static bool formatIsFloatingPoint(kinc_image_format_t format) {
|
||||
// return format == KINC_IMAGE_FORMAT_RGBA128 || format == KINC_IMAGE_FORMAT_RGBA64 || format == KINC_IMAGE_FORMAT_A32 || format == KINC_IMAGE_FORMAT_A16;
|
||||
//}
|
||||
|
||||
size_t kinc_image_init(kinc_image_t *image, void *memory, int width, int height, kinc_image_format_t format) {
|
||||
return kinc_image_init3d(image, memory, width, height, 1, format);
|
||||
}
|
||||
|
||||
size_t kinc_image_init3d(kinc_image_t *image, void *memory, int width, int height, int depth, kinc_image_format_t format) {
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->depth = depth;
|
||||
image->format = format;
|
||||
image->compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
image->data = memory;
|
||||
return width * height * depth * kinc_image_format_sizeof(format);
|
||||
}
|
||||
|
||||
void kinc_image_init_from_bytes(kinc_image_t *image, void *data, int width, int height, kinc_image_format_t format) {
|
||||
kinc_image_init_from_bytes3d(image, data, width, height, 1, format);
|
||||
}
|
||||
|
||||
void kinc_image_init_from_bytes3d(kinc_image_t *image, void *data, int width, int height, int depth, kinc_image_format_t format) {
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->depth = depth;
|
||||
image->format = format;
|
||||
image->compression = KINC_IMAGE_COMPRESSION_NONE;
|
||||
image->data = data;
|
||||
}
|
||||
|
||||
static int read_callback(void *user_data, void *data, size_t size) {
|
||||
return kinc_file_reader_read((kinc_file_reader_t *)user_data, data, size);
|
||||
}
|
||||
|
||||
static size_t size_callback(void *user_data) {
|
||||
return kinc_file_reader_size((kinc_file_reader_t *)user_data);
|
||||
}
|
||||
|
||||
static int pos_callback(void *user_data) {
|
||||
return kinc_file_reader_pos((kinc_file_reader_t *)user_data);
|
||||
}
|
||||
|
||||
static void seek_callback(void *user_data, int pos) {
|
||||
kinc_file_reader_seek((kinc_file_reader_t *)user_data, pos);
|
||||
}
|
||||
|
||||
struct kinc_internal_image_memory {
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
static int memory_read_callback(void *user_data, void *data, size_t size) {
|
||||
struct kinc_internal_image_memory *memory = (struct kinc_internal_image_memory *)user_data;
|
||||
size_t read_size = memory->size - memory->offset < size ? memory->size - memory->offset : size;
|
||||
memcpy(data, &memory->data[memory->offset], read_size);
|
||||
memory->offset += read_size;
|
||||
return (int)read_size;
|
||||
}
|
||||
|
||||
static size_t memory_size_callback(void *user_data) {
|
||||
struct kinc_internal_image_memory *memory = (struct kinc_internal_image_memory *)user_data;
|
||||
return memory->size;
|
||||
}
|
||||
|
||||
static int memory_pos_callback(void *user_data) {
|
||||
struct kinc_internal_image_memory *memory = (struct kinc_internal_image_memory *)user_data;
|
||||
return (int)memory->offset;
|
||||
}
|
||||
|
||||
static void memory_seek_callback(void *user_data, int pos) {
|
||||
struct kinc_internal_image_memory *memory = (struct kinc_internal_image_memory *)user_data;
|
||||
memory->offset = (size_t)pos;
|
||||
}
|
||||
|
||||
size_t kinc_image_size_from_callbacks(kinc_image_read_callbacks_t callbacks, void *user_data, const char *filename) {
|
||||
return loadImageSize(callbacks, user_data, filename);
|
||||
}
|
||||
|
||||
size_t kinc_image_size_from_file(const char *filename) {
|
||||
kinc_file_reader_t reader;
|
||||
if (kinc_file_reader_open(&reader, filename, KINC_FILE_TYPE_ASSET)) {
|
||||
kinc_image_read_callbacks_t callbacks;
|
||||
callbacks.read = read_callback;
|
||||
callbacks.size = size_callback;
|
||||
callbacks.pos = pos_callback;
|
||||
callbacks.seek = seek_callback;
|
||||
|
||||
size_t dataSize = loadImageSize(callbacks, &reader, filename);
|
||||
kinc_file_reader_close(&reader);
|
||||
return dataSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t kinc_image_size_from_encoded_bytes(void *data, size_t data_size, const char *format) {
|
||||
kinc_image_read_callbacks_t callbacks;
|
||||
callbacks.read = memory_read_callback;
|
||||
callbacks.size = memory_size_callback;
|
||||
callbacks.pos = memory_pos_callback;
|
||||
callbacks.seek = memory_seek_callback;
|
||||
|
||||
struct kinc_internal_image_memory image_memory;
|
||||
image_memory.data = (uint8_t *)data;
|
||||
image_memory.size = data_size;
|
||||
image_memory.offset = 0;
|
||||
|
||||
return loadImageSize(callbacks, &image_memory, format);
|
||||
}
|
||||
|
||||
size_t kinc_image_init_from_callbacks(kinc_image_t *image, void *memory, kinc_image_read_callbacks_t callbacks, void *user_data, const char *filename) {
|
||||
int dataSize;
|
||||
loadImage(callbacks, user_data, filename, memory, &dataSize, &image->width, &image->height, &image->compression, &image->format, &image->internal_format);
|
||||
image->data = memory;
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
size_t kinc_image_init_from_file(kinc_image_t *image, void *memory, const char *filename) {
|
||||
kinc_file_reader_t reader;
|
||||
if (kinc_file_reader_open(&reader, filename, KINC_FILE_TYPE_ASSET)) {
|
||||
kinc_image_read_callbacks_t callbacks;
|
||||
callbacks.read = read_callback;
|
||||
callbacks.size = size_callback;
|
||||
callbacks.pos = pos_callback;
|
||||
callbacks.seek = seek_callback;
|
||||
|
||||
int dataSize;
|
||||
loadImage(callbacks, &reader, filename, memory, &dataSize, &image->width, &image->height, &image->compression, &image->format, &image->internal_format);
|
||||
kinc_file_reader_close(&reader);
|
||||
image->data = memory;
|
||||
image->data_size = dataSize;
|
||||
image->depth = 1;
|
||||
return dataSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t kinc_image_init_from_encoded_bytes(kinc_image_t *image, void *memory, void *data, size_t data_size, const char *format) {
|
||||
kinc_image_read_callbacks_t callbacks;
|
||||
callbacks.read = memory_read_callback;
|
||||
callbacks.size = memory_size_callback;
|
||||
callbacks.pos = memory_pos_callback;
|
||||
callbacks.seek = memory_seek_callback;
|
||||
|
||||
struct kinc_internal_image_memory image_memory;
|
||||
image_memory.data = (uint8_t *)data;
|
||||
image_memory.size = data_size;
|
||||
image_memory.offset = 0;
|
||||
|
||||
int dataSize;
|
||||
loadImage(callbacks, &image_memory, format, memory, &dataSize, &image->width, &image->height, &image->compression, &image->format, &image->internal_format);
|
||||
image->data = memory;
|
||||
image->data_size = dataSize;
|
||||
image->depth = 1;
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
void kinc_image_destroy(kinc_image_t *image) {
|
||||
// user has to free the data
|
||||
image->data = NULL;
|
||||
}
|
||||
|
||||
uint32_t kinc_image_at(kinc_image_t *image, int x, int y) {
|
||||
if (image->data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return *(uint32_t *)&((uint8_t *)image->data)[image->width * kinc_image_format_sizeof(image->format) * y + x * kinc_image_format_sizeof(image->format)];
|
||||
}
|
||||
}
|
||||
|
||||
void *kinc_image_at_raw(kinc_image_t *image, int x, int y) {
|
||||
if (image->data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
return &((uint8_t *)image->data)[image->width * kinc_image_format_sizeof(image->format) * y + x * kinc_image_format_sizeof(image->format)];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *kinc_image_get_pixels(kinc_image_t *image) {
|
||||
return (uint8_t *)image->data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
45
Kinc/Sources/kinc/input/acceleration.h
Normal file
45
Kinc/Sources/kinc/input/acceleration.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file acceleration.h
|
||||
\brief Provides data provided by acceleration-sensors.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets the acceleration-callback which is called with measured acceleration-data in three dimensions.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_acceleration_set_callback(void (*value)(float /*x*/, float /*y*/, float /*z*/));
|
||||
|
||||
void kinc_internal_on_acceleration(float x, float y, float z);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
void (*acceleration_callback)(float /*x*/, float /*y*/, float /*z*/) = NULL;
|
||||
|
||||
void kinc_acceleration_set_callback(void (*value)(float /*x*/, float /*y*/, float /*z*/)) {
|
||||
acceleration_callback = value;
|
||||
}
|
||||
|
||||
void kinc_internal_on_acceleration(float x, float y, float z) {
|
||||
if (acceleration_callback != NULL) {
|
||||
acceleration_callback(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
92
Kinc/Sources/kinc/input/gamepad.h
Normal file
92
Kinc/Sources/kinc/input/gamepad.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file gamepad.h
|
||||
\brief Provides gamepad-support.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets the gamepad-axis-callback which is called with data about changing gamepad-sticks.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_gamepad_set_axis_callback(void (*value)(int /*gamepad*/, int /*axis*/, float /*value*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the gamepad-button-callback which is called with data about changing gamepad-buttons.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_gamepad_set_button_callback(void (*value)(int /*gamepad*/, int /*button*/, float /*value*/));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a vendor-name for a gamepad.
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The index of the gamepad for which to receive the vendor-name</param>
|
||||
/// <returns>The vendor-name</returns>
|
||||
KINC_FUNC const char *kinc_gamepad_vendor(int gamepad);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a name for a gamepad.
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The index of the gamepad for which to receive the name</param>
|
||||
/// <returns>The gamepad's name</returns>
|
||||
KINC_FUNC const char *kinc_gamepad_product_name(int gamepad);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a gamepad is connected.
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The index of the gamepad which's connection will be checked</param>
|
||||
/// <returns>Whether a gamepad is connected for the gamepad-index</returns>
|
||||
KINC_FUNC bool kinc_gamepad_connected(int gamepad);
|
||||
|
||||
/// <summary>
|
||||
/// Rumbles a gamepad. Careful here because it might just fall off your table.
|
||||
/// </summary>
|
||||
/// <param name="gamepad">The index of the gamepad to rumble</param>
|
||||
/// <param name="left">Rumble-strength for the left motor between 0 and 1</param>
|
||||
/// <param name="right">Rumble-strength for the right motor between 0 and 1</param>
|
||||
KINC_FUNC void kinc_gamepad_rumble(int gamepad, float left, float right);
|
||||
|
||||
void kinc_internal_gamepad_trigger_axis(int gamepad, int axis, float value);
|
||||
void kinc_internal_gamepad_trigger_button(int gamepad, int button, float value);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*gamepad_axis_callback)(int /*gamepad*/, int /*axis*/, float /*value*/) = NULL;
|
||||
static void (*gamepad_button_callback)(int /*gamepad*/, int /*button*/, float /*value*/) = NULL;
|
||||
|
||||
void kinc_gamepad_set_axis_callback(void (*value)(int /*gamepad*/, int /*axis*/, float /*value*/)) {
|
||||
gamepad_axis_callback = value;
|
||||
}
|
||||
|
||||
void kinc_gamepad_set_button_callback(void (*value)(int /*gamepad*/, int /*button*/, float /*value*/)) {
|
||||
gamepad_button_callback = value;
|
||||
}
|
||||
|
||||
void kinc_internal_gamepad_trigger_axis(int gamepad, int axis, float value) {
|
||||
if (gamepad_axis_callback != NULL) {
|
||||
gamepad_axis_callback(gamepad, axis, value);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_gamepad_trigger_button(int gamepad, int button, float value) {
|
||||
if (gamepad_button_callback != NULL) {
|
||||
gamepad_button_callback(gamepad, button, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
9
Kinc/Sources/kinc/input/inputunit.c
Normal file
9
Kinc/Sources/kinc/input/inputunit.c
Normal file
@ -0,0 +1,9 @@
|
||||
#define KINC_IMPLEMENTATION_INPUT
|
||||
|
||||
#include "acceleration.h"
|
||||
#include "gamepad.h"
|
||||
#include "keyboard.h"
|
||||
#include "mouse.h"
|
||||
#include "pen.h"
|
||||
#include "rotation.h"
|
||||
#include "surface.h"
|
||||
293
Kinc/Sources/kinc/input/keyboard.h
Normal file
293
Kinc/Sources/kinc/input/keyboard.h
Normal file
@ -0,0 +1,293 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file keyboard.h
|
||||
\brief Provides keyboard-support.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KINC_KEY_UNKNOWN 0
|
||||
#define KINC_KEY_BACK 1 // Android
|
||||
#define KINC_KEY_CANCEL 3
|
||||
#define KINC_KEY_HELP 6
|
||||
#define KINC_KEY_BACKSPACE 8
|
||||
#define KINC_KEY_TAB 9
|
||||
#define KINC_KEY_CLEAR 12
|
||||
#define KINC_KEY_RETURN 13
|
||||
#define KINC_KEY_SHIFT 16
|
||||
#define KINC_KEY_CONTROL 17
|
||||
#define KINC_KEY_ALT 18
|
||||
#define KINC_KEY_PAUSE 19
|
||||
#define KINC_KEY_CAPS_LOCK 20
|
||||
#define KINC_KEY_KANA 21
|
||||
#define KINC_KEY_HANGUL 21
|
||||
#define KINC_KEY_EISU 22
|
||||
#define KINC_KEY_JUNJA 23
|
||||
#define KINC_KEY_FINAL 24
|
||||
#define KINC_KEY_HANJA 25
|
||||
#define KINC_KEY_KANJI 25
|
||||
#define KINC_KEY_ESCAPE 27
|
||||
#define KINC_KEY_CONVERT 28
|
||||
#define KINC_KEY_NON_CONVERT 29
|
||||
#define KINC_KEY_ACCEPT 30
|
||||
#define KINC_KEY_MODE_CHANGE 31
|
||||
#define KINC_KEY_SPACE 32
|
||||
#define KINC_KEY_PAGE_UP 33
|
||||
#define KINC_KEY_PAGE_DOWN 34
|
||||
#define KINC_KEY_END 35
|
||||
#define KINC_KEY_HOME 36
|
||||
#define KINC_KEY_LEFT 37
|
||||
#define KINC_KEY_UP 38
|
||||
#define KINC_KEY_RIGHT 39
|
||||
#define KINC_KEY_DOWN 40
|
||||
#define KINC_KEY_SELECT 41
|
||||
#define KINC_KEY_PRINT 42
|
||||
#define KINC_KEY_EXECUTE 43
|
||||
#define KINC_KEY_PRINT_SCREEN 44
|
||||
#define KINC_KEY_INSERT 45
|
||||
#define KINC_KEY_DELETE 46
|
||||
#define KINC_KEY_0 48
|
||||
#define KINC_KEY_1 49
|
||||
#define KINC_KEY_2 50
|
||||
#define KINC_KEY_3 51
|
||||
#define KINC_KEY_4 52
|
||||
#define KINC_KEY_5 53
|
||||
#define KINC_KEY_6 54
|
||||
#define KINC_KEY_7 55
|
||||
#define KINC_KEY_8 56
|
||||
#define KINC_KEY_9 57
|
||||
#define KINC_KEY_COLON 58
|
||||
#define KINC_KEY_SEMICOLON 59
|
||||
#define KINC_KEY_LESS_THAN 60
|
||||
#define KINC_KEY_EQUALS 61
|
||||
#define KINC_KEY_GREATER_THAN 62
|
||||
#define KINC_KEY_QUESTIONMARK 63
|
||||
#define KINC_KEY_AT 64
|
||||
#define KINC_KEY_A 65
|
||||
#define KINC_KEY_B 66
|
||||
#define KINC_KEY_C 67
|
||||
#define KINC_KEY_D 68
|
||||
#define KINC_KEY_E 69
|
||||
#define KINC_KEY_F 70
|
||||
#define KINC_KEY_G 71
|
||||
#define KINC_KEY_H 72
|
||||
#define KINC_KEY_I 73
|
||||
#define KINC_KEY_J 74
|
||||
#define KINC_KEY_K 75
|
||||
#define KINC_KEY_L 76
|
||||
#define KINC_KEY_M 77
|
||||
#define KINC_KEY_N 78
|
||||
#define KINC_KEY_O 79
|
||||
#define KINC_KEY_P 80
|
||||
#define KINC_KEY_Q 81
|
||||
#define KINC_KEY_R 82
|
||||
#define KINC_KEY_S 83
|
||||
#define KINC_KEY_T 84
|
||||
#define KINC_KEY_U 85
|
||||
#define KINC_KEY_V 86
|
||||
#define KINC_KEY_W 87
|
||||
#define KINC_KEY_X 88
|
||||
#define KINC_KEY_Y 89
|
||||
#define KINC_KEY_Z 90
|
||||
#define KINC_KEY_WIN 91
|
||||
#define KINC_KEY_CONTEXT_MENU 93
|
||||
#define KINC_KEY_SLEEP 95
|
||||
#define KINC_KEY_NUMPAD_0 96
|
||||
#define KINC_KEY_NUMPAD_1 97
|
||||
#define KINC_KEY_NUMPAD_2 98
|
||||
#define KINC_KEY_NUMPAD_3 99
|
||||
#define KINC_KEY_NUMPAD_4 100
|
||||
#define KINC_KEY_NUMPAD_5 101
|
||||
#define KINC_KEY_NUMPAD_6 102
|
||||
#define KINC_KEY_NUMPAD_7 103
|
||||
#define KINC_KEY_NUMPAD_8 104
|
||||
#define KINC_KEY_NUMPAD_9 105
|
||||
#define KINC_KEY_MULTIPLY 106
|
||||
#define KINC_KEY_ADD 107
|
||||
#define KINC_KEY_SEPARATOR 108
|
||||
#define KINC_KEY_SUBTRACT 109
|
||||
#define KINC_KEY_DECIMAL 110
|
||||
#define KINC_KEY_DIVIDE 111
|
||||
#define KINC_KEY_F1 112
|
||||
#define KINC_KEY_F2 113
|
||||
#define KINC_KEY_F3 114
|
||||
#define KINC_KEY_F4 115
|
||||
#define KINC_KEY_F5 116
|
||||
#define KINC_KEY_F6 117
|
||||
#define KINC_KEY_F7 118
|
||||
#define KINC_KEY_F8 119
|
||||
#define KINC_KEY_F9 120
|
||||
#define KINC_KEY_F10 121
|
||||
#define KINC_KEY_F11 122
|
||||
#define KINC_KEY_F12 123
|
||||
#define KINC_KEY_F13 124
|
||||
#define KINC_KEY_F14 125
|
||||
#define KINC_KEY_F15 126
|
||||
#define KINC_KEY_F16 127
|
||||
#define KINC_KEY_F17 128
|
||||
#define KINC_KEY_F18 129
|
||||
#define KINC_KEY_F19 130
|
||||
#define KINC_KEY_F20 131
|
||||
#define KINC_KEY_F21 132
|
||||
#define KINC_KEY_F22 133
|
||||
#define KINC_KEY_F23 134
|
||||
#define KINC_KEY_F24 135
|
||||
#define KINC_KEY_NUM_LOCK 144
|
||||
#define KINC_KEY_SCROLL_LOCK 145
|
||||
#define KINC_KEY_WIN_OEM_FJ_JISHO 146
|
||||
#define KINC_KEY_WIN_OEM_FJ_MASSHOU 147
|
||||
#define KINC_KEY_WIN_OEM_FJ_TOUROKU 148
|
||||
#define KINC_KEY_WIN_OEM_FJ_LOYA 149
|
||||
#define KINC_KEY_WIN_OEM_FJ_ROYA 150
|
||||
#define KINC_KEY_CIRCUMFLEX 160
|
||||
#define KINC_KEY_EXCLAMATION 161
|
||||
#define KINC_KEY_DOUBLE_QUOTE 162
|
||||
#define KINC_KEY_HASH 163
|
||||
#define KINC_KEY_DOLLAR 164
|
||||
#define KINC_KEY_PERCENT 165
|
||||
#define KINC_KEY_AMPERSAND 166
|
||||
#define KINC_KEY_UNDERSCORE 167
|
||||
#define KINC_KEY_OPEN_PAREN 168
|
||||
#define KINC_KEY_CLOSE_PAREN 169
|
||||
#define KINC_KEY_ASTERISK 170
|
||||
#define KINC_KEY_PLUS 171
|
||||
#define KINC_KEY_PIPE 172
|
||||
#define KINC_KEY_HYPHEN_MINUS 173
|
||||
#define KINC_KEY_OPEN_CURLY_BRACKET 174
|
||||
#define KINC_KEY_CLOSE_CURLY_BRACKET 175
|
||||
#define KINC_KEY_TILDE 176
|
||||
#define KINC_KEY_VOLUME_MUTE 181
|
||||
#define KINC_KEY_VOLUME_DOWN 182
|
||||
#define KINC_KEY_VOLUME_UP 183
|
||||
#define KINC_KEY_COMMA 188
|
||||
#define KINC_KEY_PERIOD 190
|
||||
#define KINC_KEY_SLASH 191
|
||||
#define KINC_KEY_BACK_QUOTE 192
|
||||
#define KINC_KEY_OPEN_BRACKET 219
|
||||
#define KINC_KEY_BACK_SLASH 220
|
||||
#define KINC_KEY_CLOSE_BRACKET 221
|
||||
#define KINC_KEY_QUOTE 222
|
||||
#define KINC_KEY_META 224
|
||||
#define KINC_KEY_ALT_GR 225
|
||||
#define KINC_KEY_WIN_ICO_HELP 227
|
||||
#define KINC_KEY_WIN_ICO_00 228
|
||||
#define KINC_KEY_WIN_ICO_CLEAR 230
|
||||
#define KINC_KEY_WIN_OEM_RESET 233
|
||||
#define KINC_KEY_WIN_OEM_JUMP 234
|
||||
#define KINC_KEY_WIN_OEM_PA1 235
|
||||
#define KINC_KEY_WIN_OEM_PA2 236
|
||||
#define KINC_KEY_WIN_OEM_PA3 237
|
||||
#define KINC_KEY_WIN_OEM_WSCTRL 238
|
||||
#define KINC_KEY_WIN_OEM_CUSEL 239
|
||||
#define KINC_KEY_WIN_OEM_ATTN 240
|
||||
#define KINC_KEY_WIN_OEM_FINISH 241
|
||||
#define KINC_KEY_WIN_OEM_COPY 242
|
||||
#define KINC_KEY_WIN_OEM_AUTO 243
|
||||
#define KINC_KEY_WIN_OEM_ENLW 244
|
||||
#define KINC_KEY_WIN_OEM_BACK_TAB 245
|
||||
#define KINC_KEY_ATTN 246
|
||||
#define KINC_KEY_CRSEL 247
|
||||
#define KINC_KEY_EXSEL 248
|
||||
#define KINC_KEY_EREOF 249
|
||||
#define KINC_KEY_PLAY 250
|
||||
#define KINC_KEY_ZOOM 251
|
||||
#define KINC_KEY_PA1 253
|
||||
#define KINC_KEY_WIN_OEM_CLEAR 254
|
||||
|
||||
/// <summary>
|
||||
/// Show the keyboard if the system is using a software-keyboard.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_keyboard_show(void);
|
||||
|
||||
/// <summary>
|
||||
/// Hide the keyboard if the system is using a software-keyboard.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_keyboard_hide(void);
|
||||
|
||||
/// <summary>
|
||||
/// Figure out whether the keyboard is currently shown if the system is using a software-keyboard.
|
||||
/// </summary>
|
||||
/// <returns>Whether the keyboard is currently shown</returns>
|
||||
KINC_FUNC bool kinc_keyboard_active(void);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the keyboard-key-down-callback which is called with a key-code when a key goes down. Do not use this for text-input, that's what the key-press-callback
|
||||
/// is here for.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_keyboard_set_key_down_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the keyboard-key-up-callback which is called with a key-code when a key goes up. Do not use this for text-input, that's what the key-press-callback is
|
||||
/// here for.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_keyboard_set_key_up_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the keyboard-key-press-callback which is called when the system decides that a character came in via the keyboard. Use this for text-input.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_keyboard_set_key_press_callback(void (*value)(unsigned /*character*/, void * /*data*/), void *data);
|
||||
|
||||
void kinc_internal_keyboard_trigger_key_down(int key_code);
|
||||
void kinc_internal_keyboard_trigger_key_up(int key_code);
|
||||
void kinc_internal_keyboard_trigger_key_press(unsigned character);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*keyboard_key_down_callback)(int /*key_code*/, void * /*data*/) = NULL;
|
||||
static void *keyboard_key_down_callback_data = NULL;
|
||||
static void (*keyboard_key_up_callback)(int /*key_code*/, void * /*data*/) = NULL;
|
||||
static void *keyboard_key_up_callback_data = NULL;
|
||||
static void (*keyboard_key_press_callback)(unsigned /*character*/, void * /*data*/) = NULL;
|
||||
static void *keyboard_key_press_callback_data = NULL;
|
||||
|
||||
void kinc_keyboard_set_key_down_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data) {
|
||||
keyboard_key_down_callback = value;
|
||||
keyboard_key_down_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_keyboard_set_key_up_callback(void (*value)(int /*key_code*/, void * /*data*/), void *data) {
|
||||
keyboard_key_up_callback = value;
|
||||
keyboard_key_up_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_keyboard_set_key_press_callback(void (*value)(unsigned /*character*/, void * /*data*/), void *data) {
|
||||
keyboard_key_press_callback = value;
|
||||
keyboard_key_press_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_internal_keyboard_trigger_key_down(int key_code) {
|
||||
if (keyboard_key_down_callback != NULL) {
|
||||
keyboard_key_down_callback(key_code, keyboard_key_down_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_keyboard_trigger_key_up(int key_code) {
|
||||
if (keyboard_key_up_callback != NULL) {
|
||||
keyboard_key_up_callback(key_code, keyboard_key_up_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_keyboard_trigger_key_press(unsigned character) {
|
||||
if (keyboard_key_press_callback != NULL) {
|
||||
keyboard_key_press_callback(character, keyboard_key_press_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
296
Kinc/Sources/kinc/input/mouse.h
Normal file
296
Kinc/Sources/kinc/input/mouse.h
Normal file
@ -0,0 +1,296 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file mouse.h
|
||||
\brief Provides mouse-support.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KINC_MOUSE_LEFT 0
|
||||
#define KINC_MOUSE_RIGHT 1
|
||||
#define KINC_MOUSE_MIDDLE 2
|
||||
// eg backward sidebutton
|
||||
#define KINC_MOUSE_EXTRA1 3
|
||||
// eg forward sidebutton
|
||||
#define KINC_MOUSE_EXTRA2 4
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-press-callback which is called when a mouse-button is pressed.
|
||||
/// The button callback argument will usually contain one of the KINC_MOUSE_* values,
|
||||
/// but can contain higher values on certain platforms when mice with a lot of buttons are used.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_press_callback(void (*value)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-release-callback which is called when a mouse-button is released.
|
||||
/// The button callback argument will usually contain one of the KINC_MOUSE_* values,
|
||||
/// but can contain higher values on certain platforms when mice with a lot of buttons are used.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_release_callback(void (*value)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-move-callback which is called when the mouse is moved.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, int /*movement_x*/, int /*movement_y*/, void * /*data*/),
|
||||
void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-scroll-callback which is called when the mouse wheel is spinning.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_scroll_callback(void (*value)(int /*window*/, int /*delta*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-enter-window-callback which is called when the mouse-cursor enters the application-window.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_enter_window_callback(void (*value)(int /*window*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse-leave-window-callback which is called when the mouse-cursor leaves the application-window.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_mouse_set_leave_window_callback(void (*value)(int /*window*/, void * /*data*/), void *data);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out whether mouse-locking is supported.
|
||||
/// </summary>
|
||||
/// <returns>Whether mouse-locking is supported</returns>
|
||||
KINC_FUNC bool kinc_mouse_can_lock(void);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out whether the mouse is currently locked.
|
||||
/// </summary>
|
||||
/// <returns>Whether the mouse is currently locked</returns>
|
||||
KINC_FUNC bool kinc_mouse_is_locked(void);
|
||||
|
||||
/// <summary>
|
||||
/// Locks the mouse to a window.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to lock the mouse to</param>
|
||||
KINC_FUNC void kinc_mouse_lock(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks the mouse.
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC void kinc_mouse_unlock(void);
|
||||
|
||||
/// <summary>
|
||||
/// Change the cursor-image to something that's semi-randomly based on the provided int.
|
||||
/// </summary>
|
||||
/// <param name="cursor">Defines what the cursor is changed to - somehow</param>
|
||||
KINC_FUNC void kinc_mouse_set_cursor(int cursor);
|
||||
|
||||
/// <summary>
|
||||
/// Shows the mouse-cursor.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_mouse_show(void);
|
||||
|
||||
/// <summary>
|
||||
/// Hides the mouse-cursor.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_mouse_hide(void);
|
||||
|
||||
/// <summary>
|
||||
/// Manually sets the mouse-cursor-position.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to place the cursor in</param>
|
||||
/// <param name="x">The x-position inside the window to place the cursor at</param>
|
||||
/// <param name="y">The y-position inside the window to place the cursor at</param>
|
||||
KINC_FUNC void kinc_mouse_set_position(int window, int x, int y);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current mouse-position relative to a window.
|
||||
/// </summary>
|
||||
/// <param name="window">The window to base the returned position on</param>
|
||||
/// <param name="x">A pointer where the cursor's x-position is put into</param>
|
||||
/// <param name="y">A pointer where the cursor's y-position is put into</param>
|
||||
KINC_FUNC void kinc_mouse_get_position(int window, int *x, int *y);
|
||||
|
||||
void kinc_internal_mouse_trigger_press(int window, int button, int x, int y);
|
||||
void kinc_internal_mouse_trigger_release(int window, int button, int x, int y);
|
||||
void kinc_internal_mouse_trigger_move(int window, int x, int y);
|
||||
void kinc_internal_mouse_trigger_scroll(int window, int delta);
|
||||
void kinc_internal_mouse_trigger_enter_window(int window);
|
||||
void kinc_internal_mouse_trigger_leave_window(int window);
|
||||
void kinc_internal_mouse_lock(int window);
|
||||
void kinc_internal_mouse_unlock(void);
|
||||
void kinc_internal_mouse_window_activated(int window);
|
||||
void kinc_internal_mouse_window_deactivated(int window);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#include <kinc/window.h>
|
||||
#define KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*mouse_press_callback)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/) = NULL;
|
||||
static void *mouse_press_callback_data = NULL;
|
||||
static void (*mouse_release_callback)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/) = NULL;
|
||||
static void *mouse_release_callback_data = NULL;
|
||||
static void (*mouse_move_callback)(int /*window*/, int /*x*/, int /*y*/, int /*movementX*/, int /*movementY*/, void * /*data*/) = NULL;
|
||||
static void *mouse_move_callback_data = NULL;
|
||||
static void (*mouse_scroll_callback)(int /*window*/, int /*delta*/, void * /*data*/) = NULL;
|
||||
static void *mouse_scroll_callback_data = NULL;
|
||||
static void (*mouse_enter_window_callback)(int /*window*/, void * /*data*/) = NULL;
|
||||
static void *mouse_enter_window_callback_data = NULL;
|
||||
static void (*mouse_leave_window_callback)(int /*window*/, void * /*data*/) = NULL;
|
||||
static void *mouse_leave_window_callback_data = NULL;
|
||||
|
||||
void kinc_mouse_set_press_callback(void (*value)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data) {
|
||||
mouse_press_callback = value;
|
||||
mouse_press_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_mouse_set_release_callback(void (*value)(int /*window*/, int /*button*/, int /*x*/, int /*y*/, void * /*data*/), void *data) {
|
||||
mouse_release_callback = value;
|
||||
mouse_release_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_mouse_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, int /*movement_x*/, int /*movement_y*/, void * /*data*/), void *data) {
|
||||
mouse_move_callback = value;
|
||||
mouse_move_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_mouse_set_scroll_callback(void (*value)(int /*window*/, int /*delta*/, void * /*data*/), void *data) {
|
||||
mouse_scroll_callback = value;
|
||||
mouse_scroll_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_mouse_set_enter_window_callback(void (*value)(int /*window*/, void * /*data*/), void *data) {
|
||||
mouse_enter_window_callback = value;
|
||||
mouse_enter_window_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_mouse_set_leave_window_callback(void (*value)(int /*window*/, void * /*data*/), void *data) {
|
||||
mouse_leave_window_callback = value;
|
||||
mouse_leave_window_callback_data = data;
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_trigger_release(int window, int button, int x, int y) {
|
||||
if (mouse_release_callback != NULL) {
|
||||
mouse_release_callback(window, button, x, y, mouse_release_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_trigger_scroll(int window, int delta) {
|
||||
if (mouse_scroll_callback != NULL) {
|
||||
mouse_scroll_callback(window, delta, mouse_scroll_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_trigger_enter_window(int window) {
|
||||
if (mouse_enter_window_callback != NULL) {
|
||||
mouse_enter_window_callback(window, mouse_enter_window_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_trigger_leave_window(int window) {
|
||||
if (mouse_leave_window_callback != NULL) {
|
||||
mouse_leave_window_callback(window, mouse_leave_window_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_window_activated(int window) {
|
||||
if (kinc_mouse_is_locked()) {
|
||||
kinc_internal_mouse_lock(window);
|
||||
}
|
||||
}
|
||||
void kinc_internal_mouse_window_deactivated(int window) {
|
||||
if (kinc_mouse_is_locked()) {
|
||||
kinc_internal_mouse_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle state per window
|
||||
static bool moved = false;
|
||||
static bool locked = false;
|
||||
static int preLockWindow = 0;
|
||||
static int preLockX = 0;
|
||||
static int preLockY = 0;
|
||||
static int centerX = 0;
|
||||
static int centerY = 0;
|
||||
static int lastX = 0;
|
||||
static int lastY = 0;
|
||||
|
||||
void kinc_internal_mouse_trigger_press(int window, int button, int x, int y) {
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
if (mouse_press_callback != NULL) {
|
||||
mouse_press_callback(window, button, x, y, mouse_press_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_mouse_trigger_move(int window, int x, int y) {
|
||||
int movementX = 0;
|
||||
int movementY = 0;
|
||||
if (kinc_mouse_is_locked()) {
|
||||
movementX = x - centerX;
|
||||
movementY = y - centerY;
|
||||
if (movementX != 0 || movementY != 0) {
|
||||
kinc_mouse_set_position(window, centerX, centerY);
|
||||
x = centerX;
|
||||
y = centerY;
|
||||
}
|
||||
}
|
||||
else if (moved) {
|
||||
movementX = x - lastX;
|
||||
movementY = y - lastY;
|
||||
}
|
||||
moved = true;
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
if (mouse_move_callback != NULL && (movementX != 0 || movementY != 0)) {
|
||||
mouse_move_callback(window, x, y, movementX, movementY, mouse_move_callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
bool kinc_mouse_is_locked(void) {
|
||||
return locked;
|
||||
}
|
||||
|
||||
void kinc_mouse_lock(int window) {
|
||||
if (!kinc_mouse_can_lock()) {
|
||||
return;
|
||||
}
|
||||
locked = true;
|
||||
kinc_internal_mouse_lock(window);
|
||||
kinc_mouse_get_position(window, &preLockX, &preLockY);
|
||||
centerX = kinc_window_width(window) / 2;
|
||||
centerY = kinc_window_height(window) / 2;
|
||||
kinc_mouse_set_position(window, centerX, centerY);
|
||||
}
|
||||
|
||||
void kinc_mouse_unlock(void) {
|
||||
if (!kinc_mouse_can_lock()) {
|
||||
return;
|
||||
}
|
||||
moved = false;
|
||||
locked = false;
|
||||
kinc_internal_mouse_unlock();
|
||||
kinc_mouse_set_position(preLockWindow, preLockX, preLockY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
137
Kinc/Sources/kinc/input/pen.h
Normal file
137
Kinc/Sources/kinc/input/pen.h
Normal file
@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file pen.h
|
||||
\brief Provides pen-support.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pen-press-callback which is called when the pen is touching the drawing-surface.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_pen_set_press_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pen-move-callback which is called when the pen is moved.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_pen_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the pen-release-callback which is called when the pen is moved away from the drawing-surface.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_pen_set_release_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the eraser-press-callback which is called when the pen is touching the drawing-surface in eraser-mode.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_eraser_set_press_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the eraser-move-callback which is called when the pen is moved while in eraser-mode.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_eraser_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the eraser-release-callback which is called when the pen is moved away from the drawing-surface when in eraser-mode.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_eraser_set_release_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/));
|
||||
|
||||
void kinc_internal_pen_trigger_move(int window, int x, int y, float pressure);
|
||||
void kinc_internal_pen_trigger_press(int window, int x, int y, float pressure);
|
||||
void kinc_internal_pen_trigger_release(int window, int x, int y, float pressure);
|
||||
|
||||
void kinc_internal_eraser_trigger_move(int window, int x, int y, float pressure);
|
||||
void kinc_internal_eraser_trigger_press(int window, int x, int y, float pressure);
|
||||
void kinc_internal_eraser_trigger_release(int window, int x, int y, float pressure);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*pen_press_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
static void (*pen_move_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
static void (*pen_release_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
|
||||
static void (*eraser_press_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
static void (*eraser_move_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
static void (*eraser_release_callback)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/) = NULL;
|
||||
|
||||
void kinc_pen_set_press_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
pen_press_callback = value;
|
||||
}
|
||||
|
||||
void kinc_pen_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
pen_move_callback = value;
|
||||
}
|
||||
|
||||
void kinc_pen_set_release_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
pen_release_callback = value;
|
||||
}
|
||||
|
||||
void kinc_eraser_set_press_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
eraser_press_callback = value;
|
||||
}
|
||||
|
||||
void kinc_eraser_set_move_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
eraser_move_callback = value;
|
||||
}
|
||||
|
||||
void kinc_eraser_set_release_callback(void (*value)(int /*window*/, int /*x*/, int /*y*/, float /*pressure*/)) {
|
||||
eraser_release_callback = value;
|
||||
}
|
||||
|
||||
void kinc_internal_pen_trigger_press(int window, int x, int y, float pressure) {
|
||||
if (pen_press_callback != NULL) {
|
||||
pen_press_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_pen_trigger_move(int window, int x, int y, float pressure) {
|
||||
if (pen_move_callback != NULL) {
|
||||
pen_move_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_pen_trigger_release(int window, int x, int y, float pressure) {
|
||||
if (pen_release_callback != NULL) {
|
||||
pen_release_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_eraser_trigger_press(int window, int x, int y, float pressure) {
|
||||
if (eraser_press_callback != NULL) {
|
||||
eraser_press_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_eraser_trigger_move(int window, int x, int y, float pressure) {
|
||||
if (eraser_move_callback != NULL) {
|
||||
eraser_move_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_eraser_trigger_release(int window, int x, int y, float pressure) {
|
||||
if (eraser_release_callback != NULL) {
|
||||
eraser_release_callback(window, x, y, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
45
Kinc/Sources/kinc/input/rotation.h
Normal file
45
Kinc/Sources/kinc/input/rotation.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file rotation.h
|
||||
\brief Provides support for rotation-sensors.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets the rotation-callback which is called when the device is rotated. Act quickly when this is called for a desktop-system.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_rotation_set_callback(void (*value)(float /*x*/, float /*y*/, float /*z*/));
|
||||
|
||||
void kinc_internal_on_rotation(float x, float y, float z);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*rotation_callback)(float /*x*/, float /*y*/, float /*z*/) = NULL;
|
||||
|
||||
void kinc_rotation_set_callback(void (*value)(float /*x*/, float /*y*/, float /*z*/)) {
|
||||
rotation_callback = value;
|
||||
}
|
||||
|
||||
void kinc_internal_on_rotation(float x, float y, float z) {
|
||||
if (rotation_callback != NULL) {
|
||||
rotation_callback(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
81
Kinc/Sources/kinc/input/surface.h
Normal file
81
Kinc/Sources/kinc/input/surface.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file surface.h
|
||||
\brief Provides touch-support.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets the surface-touch-start-callback which is called when a finger-touch is detected.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_surface_set_touch_start_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the surface-move-callback which is called when a finger is moving around.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_surface_set_move_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/));
|
||||
|
||||
/// <summary>
|
||||
/// Sets the surface-touch-end-callback which is called when a finger disappears. This is usually not a medical emergency.
|
||||
/// </summary>
|
||||
/// <param name="value">The callback</param>
|
||||
KINC_FUNC void kinc_surface_set_touch_end_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/));
|
||||
|
||||
void kinc_internal_surface_trigger_touch_start(int index, int x, int y);
|
||||
void kinc_internal_surface_trigger_move(int index, int x, int y);
|
||||
void kinc_internal_surface_trigger_touch_end(int index, int x, int y);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_INPUT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void (*surface_touch_start_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
|
||||
static void (*surface_move_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
|
||||
static void (*surface_touch_end_callback)(int /*index*/, int /*x*/, int /*y*/) = NULL;
|
||||
|
||||
void kinc_surface_set_touch_start_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
|
||||
surface_touch_start_callback = value;
|
||||
}
|
||||
|
||||
void kinc_surface_set_move_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
|
||||
surface_move_callback = value;
|
||||
}
|
||||
|
||||
void kinc_surface_set_touch_end_callback(void (*value)(int /*index*/, int /*x*/, int /*y*/)) {
|
||||
surface_touch_end_callback = value;
|
||||
}
|
||||
|
||||
void kinc_internal_surface_trigger_touch_start(int index, int x, int y) {
|
||||
if (surface_touch_start_callback != NULL) {
|
||||
surface_touch_start_callback(index, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_surface_trigger_move(int index, int x, int y) {
|
||||
if (surface_move_callback != NULL) {
|
||||
surface_move_callback(index, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_surface_trigger_touch_end(int index, int x, int y) {
|
||||
if (surface_touch_end_callback != NULL) {
|
||||
surface_touch_end_callback(index, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
563
Kinc/Sources/kinc/io/filereader.h
Normal file
563
Kinc/Sources/kinc/io/filereader.h
Normal file
@ -0,0 +1,563 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#if defined(KORE_SONY) || defined(KORE_SWITCH)
|
||||
#include <kinc/backend/FileReaderImpl.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*! \file filereader.h
|
||||
\brief Provides an API very similar to fread and friends but handles the intricacies of where files are actually hidden on each supported system.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef KORE_DEBUGDIR
|
||||
#define KORE_DEBUGDIR "Deployment"
|
||||
#endif
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
struct AAsset;
|
||||
struct __sFILE;
|
||||
typedef struct __sFILE FILE;
|
||||
#endif
|
||||
|
||||
#define KINC_FILE_TYPE_ASSET 0
|
||||
#define KINC_FILE_TYPE_SAVE 1
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
typedef struct kinc_file_reader {
|
||||
int pos;
|
||||
int size;
|
||||
FILE *file;
|
||||
struct AAsset *asset;
|
||||
int type;
|
||||
} kinc_file_reader_t;
|
||||
#else
|
||||
typedef struct kinc_file_reader {
|
||||
void *file;
|
||||
int size;
|
||||
int type;
|
||||
int mode;
|
||||
bool mounted;
|
||||
#if defined(KORE_SONY) || defined(KORE_SWITCH)
|
||||
kinc_file_reader_impl_t impl;
|
||||
#endif
|
||||
} kinc_file_reader_t;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Opens a file for reading.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader to initialize for reading</param>
|
||||
/// <param name="filepath">A filepath to identify a file</param>
|
||||
/// <param name="type">Looks for a regular file (KINC_FILE_TYPE_ASSET) or a save-file (KINC_FILE_TYPE_SAVE)</param>
|
||||
/// <returns>Whether the file could be opened</returns>
|
||||
KINC_FUNC bool kinc_file_reader_open(kinc_file_reader_t *reader, const char *filepath, int type);
|
||||
|
||||
/// <summary>
|
||||
/// Closes a file.
|
||||
/// </summary>
|
||||
/// <param name="reader">The file to close</param>
|
||||
KINC_FUNC void kinc_file_reader_close(kinc_file_reader_t *reader);
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from a file starting from the current reading-position and increases the reading-position accordingly.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader to read from</param>
|
||||
/// <param name="data">A pointer to write the data to</param>
|
||||
/// <param name="size">The amount of data to read in bytes</param>
|
||||
/// <returns>The number of bytes that were read - can be less than size if there is not enough data in the file</returns>
|
||||
KINC_FUNC int kinc_file_reader_read(kinc_file_reader_t *reader, void *data, size_t size);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out the size of a file.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader which's file-size to figure out</param>
|
||||
/// <returns>The size in bytes</returns>
|
||||
KINC_FUNC size_t kinc_file_reader_size(kinc_file_reader_t *reader);
|
||||
|
||||
/// <summary>
|
||||
/// Figures out the current reading-position in the file.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader which's reading-position to figure out</param>
|
||||
/// <returns>The current reading-position</returns>
|
||||
KINC_FUNC int kinc_file_reader_pos(kinc_file_reader_t *reader);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the reading-position manually.
|
||||
/// </summary>
|
||||
/// <param name="reader">The reader which's reading-position to set</param>
|
||||
/// <param name="pos">The reading-position to set</param>
|
||||
KINC_FUNC void kinc_file_reader_seek(kinc_file_reader_t *reader, int pos);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a little-endian float.
|
||||
/// </summary>
|
||||
KINC_FUNC float kinc_read_f32le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a big-endian float.
|
||||
/// </summary>
|
||||
KINC_FUNC float kinc_read_f32be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets eight bytes starting at the provided pointer as a little-endian uint64.
|
||||
/// </summary>
|
||||
KINC_FUNC uint64_t kinc_read_u64le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets eight bytes starting at the provided pointer as a big-endian uint64.
|
||||
/// </summary>
|
||||
KINC_FUNC uint64_t kinc_read_u64be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets eight bytes starting at the provided pointer as a little-endian int64.
|
||||
/// </summary>
|
||||
KINC_FUNC int64_t kinc_read_s64le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets eight bytes starting at the provided pointer as a big-endian int64.
|
||||
/// </summary>
|
||||
KINC_FUNC int64_t kinc_read_s64be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a little-endian uint32.
|
||||
/// </summary>
|
||||
KINC_FUNC uint32_t kinc_read_u32le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a big-endian uint32.
|
||||
/// </summary>
|
||||
KINC_FUNC uint32_t kinc_read_u32be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a little-endian int32.
|
||||
/// </summary>
|
||||
KINC_FUNC int32_t kinc_read_s32le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets four bytes starting at the provided pointer as a big-endian int32.
|
||||
/// </summary>
|
||||
KINC_FUNC int32_t kinc_read_s32be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets two bytes starting at the provided pointer as a little-endian uint16.
|
||||
/// </summary>
|
||||
KINC_FUNC uint16_t kinc_read_u16le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets two bytes starting at the provided pointer as a big-endian uint16.
|
||||
/// </summary>
|
||||
KINC_FUNC uint16_t kinc_read_u16be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets two bytes starting at the provided pointer as a little-endian int16.
|
||||
/// </summary>
|
||||
KINC_FUNC int16_t kinc_read_s16le(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets two bytes starting at the provided pointer as a big-endian int16.
|
||||
/// </summary>
|
||||
KINC_FUNC int16_t kinc_read_s16be(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets one byte starting at the provided pointer as a uint8.
|
||||
/// </summary>
|
||||
KINC_FUNC uint8_t kinc_read_u8(uint8_t *data);
|
||||
|
||||
/// <summary>
|
||||
/// Interprets one byte starting at the provided pointer as an int8.
|
||||
/// </summary>
|
||||
KINC_FUNC int8_t kinc_read_s8(uint8_t *data);
|
||||
|
||||
void kinc_internal_set_files_location(char *dir);
|
||||
char *kinc_internal_get_files_location(void);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_IO
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include "filereader.h"
|
||||
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#include <kinc/system.h>
|
||||
#define KINC_IMPLEMENTATION
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
#include <kinc/backend/Android.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef KORE_WINDOWS
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
#ifndef KORE_CONSOLE
|
||||
|
||||
#ifdef KORE_IOS
|
||||
const char *iphonegetresourcepath(void);
|
||||
#endif
|
||||
|
||||
#ifdef KORE_MACOS
|
||||
const char *macgetresourcepath(void);
|
||||
#endif
|
||||
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
#include <kinc/backend/MiniWindows.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_TIZEN
|
||||
#include <FApp.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_PI
|
||||
#define KORE_LINUX
|
||||
#endif
|
||||
|
||||
static char *fileslocation = NULL;
|
||||
#ifdef KORE_WINDOWS
|
||||
static wchar_t wfilepath[1001];
|
||||
#endif
|
||||
|
||||
void kinc_internal_set_files_location(char *dir) {
|
||||
fileslocation = dir;
|
||||
}
|
||||
|
||||
char *kinc_internal_get_files_location(void) {
|
||||
return fileslocation;
|
||||
}
|
||||
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
void kinc_internal_uwp_installed_location_path(char *path);
|
||||
#endif
|
||||
|
||||
#ifndef KORE_ANDROID
|
||||
bool kinc_file_reader_open(kinc_file_reader_t *reader, const char *filename, int type) {
|
||||
memset(reader, 0, sizeof(kinc_file_reader_t));
|
||||
char filepath[1001];
|
||||
#ifdef KORE_IOS
|
||||
strcpy(filepath, type == KINC_FILE_TYPE_SAVE ? kinc_internal_save_path() : iphonegetresourcepath());
|
||||
if (type != KINC_FILE_TYPE_SAVE) {
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, KORE_DEBUGDIR);
|
||||
strcat(filepath, "/");
|
||||
}
|
||||
|
||||
strcat(filepath, filename);
|
||||
#endif
|
||||
#ifdef KORE_MACOS
|
||||
strcpy(filepath, type == KINC_FILE_TYPE_SAVE ? kinc_internal_save_path() : macgetresourcepath());
|
||||
if (type != KINC_FILE_TYPE_SAVE) {
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, KORE_DEBUGDIR);
|
||||
strcat(filepath, "/");
|
||||
}
|
||||
strcat(filepath, filename);
|
||||
#endif
|
||||
#ifdef KORE_WINDOWS
|
||||
if (type == KINC_FILE_TYPE_SAVE) {
|
||||
strcpy(filepath, kinc_internal_save_path());
|
||||
strcat(filepath, filename);
|
||||
}
|
||||
else {
|
||||
strcpy(filepath, filename);
|
||||
}
|
||||
size_t filepathlength = strlen(filepath);
|
||||
for (size_t i = 0; i < filepathlength; ++i)
|
||||
if (filepath[i] == '/')
|
||||
filepath[i] = '\\';
|
||||
#endif
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
kinc_internal_uwp_installed_location_path(filepath);
|
||||
strcat(filepath, "\\");
|
||||
strcat(filepath, filename);
|
||||
#endif
|
||||
#ifdef KORE_LINUX
|
||||
if (type == KINC_FILE_TYPE_SAVE) {
|
||||
strcpy(filepath, kinc_internal_save_path());
|
||||
strcat(filepath, filename);
|
||||
}
|
||||
else {
|
||||
strcpy(filepath, filename);
|
||||
}
|
||||
#endif
|
||||
#ifdef KORE_WASM
|
||||
strcpy(filepath, filename);
|
||||
#endif
|
||||
#ifdef KORE_EMSCRIPTEN
|
||||
strcpy(filepath, KORE_DEBUGDIR);
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, filename);
|
||||
#endif
|
||||
#ifdef KORE_TIZEN
|
||||
for (int i = 0; i < Tizen::App::App::GetInstance()->GetAppDataPath().GetLength(); ++i) {
|
||||
wchar_t c;
|
||||
Tizen::App::App::GetInstance()->GetAppDataPath().GetCharAt(i, c);
|
||||
filepath[i] = (char)c;
|
||||
}
|
||||
filepath[Tizen::App::App::GetInstance()->GetAppDataPath().GetLength()] = 0;
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, filename);
|
||||
#endif
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
// Drive letter or network
|
||||
bool isAbsolute = (filename[1] == ':' && filename[2] == '\\') || (filename[0] == '\\' && filename[1] == '\\');
|
||||
#else
|
||||
bool isAbsolute = filename[0] == '/';
|
||||
#endif
|
||||
|
||||
if (isAbsolute) {
|
||||
strcpy(filepath, filename);
|
||||
}
|
||||
else if (fileslocation != NULL && type != KINC_FILE_TYPE_SAVE) {
|
||||
strcpy(filepath, fileslocation);
|
||||
strcat(filepath, "/");
|
||||
strcat(filepath, filename);
|
||||
}
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
MultiByteToWideChar(CP_UTF8, 0, filepath, -1, wfilepath, 1000);
|
||||
reader->file = CreateFileW(wfilepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (reader->file == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
reader->file = fopen(filepath, "rb");
|
||||
if (reader->file == NULL) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
reader->size = GetFileSize(reader->file, NULL);
|
||||
#else
|
||||
fseek((FILE *)reader->file, 0, SEEK_END);
|
||||
reader->size = (int)ftell((FILE *)reader->file);
|
||||
fseek((FILE *)reader->file, 0, SEEK_SET);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int kinc_file_reader_read(kinc_file_reader_t *reader, void *data, size_t size) {
|
||||
#ifdef KORE_ANDROID
|
||||
if (reader->file != NULL) {
|
||||
return (int)fread(data, 1, size, reader->file);
|
||||
}
|
||||
else {
|
||||
int read = AAsset_read(reader->asset, data, size);
|
||||
reader->pos += read;
|
||||
return read;
|
||||
}
|
||||
#elif defined(KORE_WINDOWS)
|
||||
DWORD readBytes = 0;
|
||||
if (ReadFile(reader->file, data, (DWORD)size, &readBytes, NULL)) {
|
||||
return (int)readBytes;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return (int)fread(data, 1, size, (FILE *)reader->file);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_file_reader_seek(kinc_file_reader_t *reader, int pos) {
|
||||
#ifdef KORE_ANDROID
|
||||
if (reader->file != NULL) {
|
||||
fseek(reader->file, pos, SEEK_SET);
|
||||
}
|
||||
else {
|
||||
AAsset_seek(reader->asset, pos, SEEK_SET);
|
||||
reader->pos = pos;
|
||||
}
|
||||
#elif defined(KORE_WINDOWS)
|
||||
SetFilePointer(reader->file, pos, NULL, FILE_BEGIN);
|
||||
#else
|
||||
fseek((FILE *)reader->file, pos, SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_file_reader_close(kinc_file_reader_t *reader) {
|
||||
#ifdef KORE_ANDROID
|
||||
if (reader->file != NULL) {
|
||||
fclose(reader->file);
|
||||
reader->file = NULL;
|
||||
}
|
||||
if (reader->asset != NULL) {
|
||||
AAsset_close(reader->asset);
|
||||
reader->asset = NULL;
|
||||
}
|
||||
#elif defined(KORE_WINDOWS)
|
||||
CloseHandle(reader->file);
|
||||
#else
|
||||
if (reader->file == NULL) {
|
||||
return;
|
||||
}
|
||||
fclose((FILE *)reader->file);
|
||||
reader->file = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_file_reader_pos(kinc_file_reader_t *reader) {
|
||||
#ifdef KORE_ANDROID
|
||||
if (reader->file != NULL)
|
||||
return (int)ftell(reader->file);
|
||||
else
|
||||
return reader->pos;
|
||||
#elif defined(KORE_WINDOWS)
|
||||
return (int)SetFilePointer(reader->file, 0, NULL, FILE_CURRENT);
|
||||
#else
|
||||
return (int)ftell((FILE *)reader->file);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t kinc_file_reader_size(kinc_file_reader_t *reader) {
|
||||
return (size_t)reader->size;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
float kinc_read_f32le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN // speed optimization
|
||||
return *(float *)data;
|
||||
#else // works on all architectures
|
||||
int i = (data[0] << 0) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
return *(float *)&i;
|
||||
#endif
|
||||
}
|
||||
|
||||
float kinc_read_f32be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN // speed optimization
|
||||
return *(float *)data;
|
||||
#else // works on all architectures
|
||||
int i = (data[3] << 0) | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
|
||||
return *(float *)&i;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t kinc_read_u64le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(uint64_t *)data;
|
||||
#else
|
||||
return ((uint64_t)data[0] << 0) | ((uint64_t)data[1] << 8) | ((uint64_t)data[2] << 16) | ((uint64_t)data[3] << 24) | ((uint64_t)data[4] << 32) |
|
||||
((uint64_t)data[5] << 40) | ((uint64_t)data[6] << 48) | ((uint64_t)data[7] << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t kinc_read_u64be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(uint64_t *)data;
|
||||
#else
|
||||
return ((uint64_t)data[7] << 0) | ((uint64_t)data[6] << 8) | ((uint64_t)data[5] << 16) | ((uint64_t)data[4] << 24) | ((uint64_t)data[3] << 32) |
|
||||
((uint64_t)data[2] << 40) | ((uint64_t)data[1] << 48) | ((uint64_t)data[0] << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t kinc_read_s64le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(int64_t *)data;
|
||||
#else
|
||||
return ((int64_t)data[0] << 0) | ((int64_t)data[1] << 8) | ((int64_t)data[2] << 16) | ((int64_t)data[3] << 24) | ((int64_t)data[4] << 32) |
|
||||
((int64_t)data[5] << 40) | ((int64_t)data[6] << 48) | ((int64_t)data[7] << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
int64_t kinc_read_s64be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(int64_t *)data;
|
||||
#else
|
||||
return ((int64_t)data[7] << 0) | ((int64_t)data[6] << 8) | ((int64_t)data[5] << 16) | ((int64_t)data[4] << 24) | ((int64_t)data[3] << 32) |
|
||||
((int64_t)data[2] << 40) | ((int64_t)data[1] << 48) | ((int64_t)data[0] << 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t kinc_read_u32le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(uint32_t *)data;
|
||||
#else
|
||||
return (data[0] << 0) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t kinc_read_u32be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(uint32_t *)data;
|
||||
#else
|
||||
return (data[3] << 0) | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t kinc_read_s32le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(int32_t *)data;
|
||||
#else
|
||||
return (data[0] << 0) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t kinc_read_s32be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(int32_t *)data;
|
||||
#else
|
||||
return (data[3] << 0) | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t kinc_read_u16le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(uint16_t *)data;
|
||||
#else
|
||||
return (data[0] << 0) | (data[1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t kinc_read_u16be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(uint16_t *)data;
|
||||
#else
|
||||
return (data[1] << 0) | (data[0] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t kinc_read_s16le(uint8_t *data) {
|
||||
#ifdef KORE_LITTLE_ENDIAN
|
||||
return *(int16_t *)data;
|
||||
#else
|
||||
return (data[0] << 0) | (data[1] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t kinc_read_s16be(uint8_t *data) {
|
||||
#ifdef KORE_BIG_ENDIAN
|
||||
return *(int16_t *)data;
|
||||
#else
|
||||
return (data[1] << 0) | (data[0] << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t kinc_read_u8(uint8_t *data) {
|
||||
return *data;
|
||||
}
|
||||
|
||||
int8_t kinc_read_s8(uint8_t *data) {
|
||||
return *(int8_t *)data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
132
Kinc/Sources/kinc/io/filewriter.h
Normal file
132
Kinc/Sources/kinc/io/filewriter.h
Normal file
@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file filewriter.h
|
||||
\brief Provides an API very similar to fwrite and friends but uses a directory that can actually used for persistent file storage. This can later be read
|
||||
using the kinc_file_reader-functions and KINC_FILE_TYPE_SAVE.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_file_writer {
|
||||
void *file;
|
||||
const char *filename;
|
||||
bool mounted;
|
||||
} kinc_file_writer_t;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a file for writing.
|
||||
/// </summary>
|
||||
/// <param name="reader">The writer to initialize for writing</param>
|
||||
/// <param name="filepath">A filepath to identify a file</param>
|
||||
/// <returns>Whether the file could be opened</returns>
|
||||
KINC_FUNC bool kinc_file_writer_open(kinc_file_writer_t *writer, const char *filepath);
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to a file starting from the current writing-position and increases the writing-position accordingly.
|
||||
/// </summary>
|
||||
/// <param name="reader">The writer to write to</param>
|
||||
/// <param name="data">A pointer to read the data from</param>
|
||||
/// <param name="size">The amount of data to write in bytes</param>
|
||||
KINC_FUNC void kinc_file_writer_write(kinc_file_writer_t *writer, void *data, int size);
|
||||
|
||||
/// <summary>
|
||||
/// Closes a file.
|
||||
/// </summary>
|
||||
/// <param name="reader">The file to close</param>
|
||||
KINC_FUNC void kinc_file_writer_close(kinc_file_writer_t *writer);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_IO
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#if !defined(KORE_CONSOLE)
|
||||
|
||||
#include "filewriter.h"
|
||||
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#include <kinc/error.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
#define KINC_IMPLEMENTATION
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(KORE_WINDOWS)
|
||||
#include <kinc/backend/MiniWindows.h>
|
||||
#endif
|
||||
|
||||
#if defined(KORE_PS4) || defined(KORE_SWITCH)
|
||||
#define MOUNT_SAVES
|
||||
bool mountSaveData(bool);
|
||||
void unmountSaveData();
|
||||
#endif
|
||||
|
||||
bool kinc_file_writer_open(kinc_file_writer_t *writer, const char *filepath) {
|
||||
writer->file = NULL;
|
||||
writer->mounted = false;
|
||||
#ifdef MOUNT_SAVES
|
||||
if (!mountSaveData(true)) {
|
||||
return false;
|
||||
}
|
||||
writer->mounted = true;
|
||||
#endif
|
||||
char path[1001];
|
||||
strcpy(path, kinc_internal_save_path());
|
||||
strcat(path, filepath);
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
wchar_t wpath[MAX_PATH];
|
||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH);
|
||||
writer->file = CreateFileW(wpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
#else
|
||||
writer->file = fopen(path, "wb");
|
||||
#endif
|
||||
if (writer->file == NULL) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not open file %s.", filepath);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void kinc_file_writer_close(kinc_file_writer_t *writer) {
|
||||
if (writer->file != NULL) {
|
||||
#ifdef KORE_WINDOWS
|
||||
CloseHandle(writer->file);
|
||||
#else
|
||||
fclose((FILE *)writer->file);
|
||||
#endif
|
||||
writer->file = NULL;
|
||||
}
|
||||
#ifdef MOUNT_SAVES
|
||||
if (writer->mounted) {
|
||||
writer->mounted = false;
|
||||
unmountSaveData();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_file_writer_write(kinc_file_writer_t *writer, void *data, int size) {
|
||||
#ifdef KORE_WINDOWS
|
||||
DWORD written = 0;
|
||||
WriteFile(writer->file, data, (DWORD)size, &written, NULL);
|
||||
#else
|
||||
fwrite(data, 1, size, (FILE *)writer->file);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
4
Kinc/Sources/kinc/io/iounit.c
Normal file
4
Kinc/Sources/kinc/io/iounit.c
Normal file
@ -0,0 +1,4 @@
|
||||
#define KINC_IMPLEMENTATION_IO
|
||||
|
||||
#include "filereader.h"
|
||||
#include "filewriter.h"
|
||||
24
Kinc/Sources/kinc/io/lz4/LICENSE
Normal file
24
Kinc/Sources/kinc/io/lz4/LICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
LZ4 Library
|
||||
Copyright (c) 2011-2016, Yann Collet
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||
1526
Kinc/Sources/kinc/io/lz4/lz4.c
Normal file
1526
Kinc/Sources/kinc/io/lz4/lz4.c
Normal file
File diff suppressed because it is too large
Load Diff
463
Kinc/Sources/kinc/io/lz4/lz4.h
Normal file
463
Kinc/Sources/kinc/io/lz4/lz4.h
Normal file
@ -0,0 +1,463 @@
|
||||
/*
|
||||
* LZ4 - Fast LZ compression algorithm
|
||||
* Header File
|
||||
* Copyright (C) 2011-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 homepage : http://www.lz4.org
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
*/
|
||||
#ifndef LZ4_H_2983827168210
|
||||
#define LZ4_H_2983827168210
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* --- Dependency --- */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**
|
||||
Introduction
|
||||
|
||||
LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core,
|
||||
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||
|
||||
The LZ4 compression library provides in-memory compression and decompression functions.
|
||||
Compression can be done in:
|
||||
- a single step (described as Simple Functions)
|
||||
- a single step, reusing a context (described in Advanced Functions)
|
||||
- unbounded multiple steps (described as Streaming compression)
|
||||
|
||||
lz4.h provides block compression functions. It gives full buffer control to user.
|
||||
Decompressing an lz4-compressed block also requires metadata (such as compressed size).
|
||||
Each application is free to encode such metadata in whichever way it wants.
|
||||
|
||||
An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md),
|
||||
take care of encoding standard metadata alongside LZ4-compressed blocks.
|
||||
If your application requires interoperability, it's recommended to use it.
|
||||
A library is provided to take care of it, see lz4frame.h.
|
||||
*/
|
||||
|
||||
/*^***************************************************************
|
||||
* Export parameters
|
||||
*****************************************************************/
|
||||
/*
|
||||
* LZ4_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
*/
|
||||
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
|
||||
# define LZ4LIB_API __declspec(dllexport)
|
||||
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
|
||||
# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define LZ4LIB_API
|
||||
#endif
|
||||
|
||||
|
||||
/*========== Version =========== */
|
||||
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ4_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */
|
||||
|
||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||
|
||||
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||
#define LZ4_QUOTE(str) #str
|
||||
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
|
||||
|
||||
LZ4LIB_API int LZ4_versionNumber (void);
|
||||
LZ4LIB_API const char* LZ4_versionString (void);
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Tuning parameter
|
||||
**************************************/
|
||||
/*!
|
||||
* LZ4_MEMORY_USAGE :
|
||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||
* Increasing memory usage improves compression ratio
|
||||
* Reduced memory usage can improve speed, due to cache effect
|
||||
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||
*/
|
||||
#define LZ4_MEMORY_USAGE 14
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
/*! LZ4_compress_default() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'source' into a more limited 'dest' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
As a consequence, 'dest' content is not valid.
|
||||
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
|
||||
sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
|
||||
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
|
||||
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
|
||||
or 0 if compression fails */
|
||||
LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
|
||||
/*! LZ4_decompress_safe() :
|
||||
compressedSize : is the precise full size of the compressed block.
|
||||
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (<0).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function is protected against buffer overflow exploits, including malicious data packets.
|
||||
It never writes outside output buffer, nor reads outside input buffer.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
|
||||
/*!
|
||||
LZ4_compressBound() :
|
||||
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
|
||||
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
|
||||
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compressBound(int inputSize);
|
||||
|
||||
/*!
|
||||
LZ4_compress_fast() :
|
||||
Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
|
||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_compress_fast_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LZ4_sizeofState() to know how much memory must be allocated,
|
||||
and allocate it on 8-bytes boundaries (using malloc() typically).
|
||||
Then, provide it as 'void* state' to compression function.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_sizeofState(void);
|
||||
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_compress_destSize() :
|
||||
Reverse the logic, by compressing as much data as possible from 'source' buffer
|
||||
into already allocated buffer 'dest' of size 'targetDestSize'.
|
||||
This function either compresses the entire 'source' content into 'dest' if it's large enough,
|
||||
or fill 'dest' buffer completely with as much data as possible from 'source'.
|
||||
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
|
||||
New value is necessarily <= old value.
|
||||
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
|
||||
or 0 if compression fails
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_decompress_fast() :
|
||||
originalSize : is the original and therefore uncompressed size
|
||||
return : the number of bytes read from the source buffer (in other words, the compressed size)
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
|
||||
note : This function fully respect memory boundaries for properly formed compressed data.
|
||||
It is a bit faster than LZ4_decompress_safe().
|
||||
However, it does not provide any protection against intentionally modified data stream (malicious input).
|
||||
Use this function in trusted environment only (data to decode comes from a trusted source).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize);
|
||||
|
||||
/*!
|
||||
LZ4_decompress_safe_partial() :
|
||||
This function decompress a compressed block of size 'compressedSize' at position 'source'
|
||||
into destination buffer 'dest' of size 'maxDecompressedSize'.
|
||||
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
|
||||
reducing decompression time.
|
||||
return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
|
||||
Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
|
||||
Always control how many bytes were decoded.
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
/*-*********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||
|
||||
/*! LZ4_createStream() and LZ4_freeStream() :
|
||||
* LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure.
|
||||
* LZ4_freeStream() releases its memory.
|
||||
*/
|
||||
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*! LZ4_resetStream() :
|
||||
* An LZ4_stream_t structure can be allocated once and re-used multiple times.
|
||||
* Use this function to init an allocated `LZ4_stream_t` structure and start a new compression.
|
||||
*/
|
||||
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*! LZ4_loadDict() :
|
||||
* Use this function to load a static dictionary into LZ4_stream.
|
||||
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
|
||||
* Loading a size of 0 is allowed.
|
||||
* Return : dictionary size, in bytes (necessarily <= 64 KB)
|
||||
*/
|
||||
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
/*! LZ4_compress_fast_continue() :
|
||||
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
|
||||
* Important : Previous data blocks are assumed to still be present and unmodified !
|
||||
* 'dst' buffer must be already allocated.
|
||||
* If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
|
||||
|
||||
/*! LZ4_saveDict() :
|
||||
* If previously compressed data block is not guaranteed to remain available at its memory location,
|
||||
* save it into a safer place (char* safeBuffer).
|
||||
* Note : you don't need to call LZ4_loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue().
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
/*-**********************************************
|
||||
* Streaming Decompression Functions
|
||||
* Bufferless synchronous API
|
||||
************************************************/
|
||||
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */
|
||||
|
||||
/* creation / destruction of streaming decompression tracking structure */
|
||||
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||
|
||||
/*! LZ4_setStreamDecode() :
|
||||
* Use this function to instruct where to find the dictionary.
|
||||
* Setting a size of 0 is allowed (same effect as reset).
|
||||
* @return : 1 if OK, 0 if error
|
||||
*/
|
||||
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
|
||||
|
||||
/*!
|
||||
LZ4_decompress_*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
|
||||
In the case of a ring buffers, decoding buffer must be either :
|
||||
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
|
||||
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
|
||||
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
- _At least_ 64 KB + 8 bytes + maxBlockSize.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including larger than decoding buffer.
|
||||
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
|
||||
and indicate where it is saved using LZ4_setStreamDecode()
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize);
|
||||
|
||||
|
||||
/*! LZ4_decompress_*_usingDict() :
|
||||
* These decoding functions work the same as
|
||||
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
|
||||
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
/*^**********************************************
|
||||
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||
***********************************************/
|
||||
/*-************************************
|
||||
* Private definitions
|
||||
**************************************
|
||||
* Do not use these definitions.
|
||||
* They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
||||
* Using these definitions will expose code to API and/or ABI break in future versions of the library.
|
||||
**************************************/
|
||||
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
||||
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
||||
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||
|
||||
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t hashTable[LZ4_HASH_SIZE_U32];
|
||||
uint32_t currentOffset;
|
||||
uint32_t initCheck;
|
||||
const uint8_t* dictionary;
|
||||
uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */
|
||||
uint32_t dictSize;
|
||||
} LZ4_stream_t_internal;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t* externalDict;
|
||||
size_t extDictSize;
|
||||
const uint8_t* prefixEnd;
|
||||
size_t prefixSize;
|
||||
} LZ4_streamDecode_t_internal;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct {
|
||||
unsigned int hashTable[LZ4_HASH_SIZE_U32];
|
||||
unsigned int currentOffset;
|
||||
unsigned int initCheck;
|
||||
const unsigned char* dictionary;
|
||||
unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */
|
||||
unsigned int dictSize;
|
||||
} LZ4_stream_t_internal;
|
||||
|
||||
typedef struct {
|
||||
const unsigned char* externalDict;
|
||||
size_t extDictSize;
|
||||
const unsigned char* prefixEnd;
|
||||
size_t prefixSize;
|
||||
} LZ4_streamDecode_t_internal;
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* LZ4_stream_t :
|
||||
* information structure to track an LZ4 stream.
|
||||
* init this structure before first use.
|
||||
* note : only use in association with static linking !
|
||||
* this definition is not API/ABI safe,
|
||||
* and may change in a future version !
|
||||
*/
|
||||
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
|
||||
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))
|
||||
union LZ4_stream_u {
|
||||
unsigned long long table[LZ4_STREAMSIZE_U64];
|
||||
LZ4_stream_t_internal internal_donotuse;
|
||||
} ; /* previously typedef'd to LZ4_stream_t */
|
||||
|
||||
|
||||
/*!
|
||||
* LZ4_streamDecode_t :
|
||||
* information structure to track an LZ4 stream during decompression.
|
||||
* init this structure using LZ4_setStreamDecode (or memset()) before first use
|
||||
* note : only use in association with static linking !
|
||||
* this definition is not API/ABI safe,
|
||||
* and may change in a future version !
|
||||
*/
|
||||
#define LZ4_STREAMDECODESIZE_U64 4
|
||||
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||
union LZ4_streamDecode_u {
|
||||
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
||||
LZ4_streamDecode_t_internal internal_donotuse;
|
||||
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||
|
||||
|
||||
/*=************************************
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
/* Deprecation warnings */
|
||||
/* Should these warnings be a problem,
|
||||
it is generally possible to disable them,
|
||||
typically with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||
Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
||||
#else
|
||||
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
||||
# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ4_GCC_VERSION >= 301)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
|
||||
# define LZ4_DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Obsolete decompression functions */
|
||||
/* These function names are completely deprecated and must no longer be used.
|
||||
They are only provided in lz4.c for compatibility with older programs.
|
||||
- LZ4_uncompress is the same as LZ4_decompress_fast
|
||||
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
|
||||
These function prototypes are now disabled; uncomment them only if you really need them.
|
||||
It is highly recommended to stop using these prototypes and migrate to maintained ones */
|
||||
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
|
||||
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
|
||||
|
||||
/* Obsolete streaming functions; use new streaming interface whenever possible */
|
||||
LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer);
|
||||
LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
|
||||
LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||
LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state);
|
||||
|
||||
/* Obsolete streaming decoding functions */
|
||||
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LZ4_H_2983827168210 */
|
||||
1413
Kinc/Sources/kinc/io/lz4/lz4frame.c
Normal file
1413
Kinc/Sources/kinc/io/lz4/lz4frame.c
Normal file
File diff suppressed because it is too large
Load Diff
340
Kinc/Sources/kinc/io/lz4/lz4frame.h
Normal file
340
Kinc/Sources/kinc/io/lz4/lz4frame.h
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
LZ4 auto-framing library
|
||||
Header File
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
/* LZ4F is a stand-alone API to create LZ4-compressed frames
|
||||
* conformant with specification v1.5.1.
|
||||
* It also offers streaming capabilities.
|
||||
* lz4.h is not required when using lz4frame.h.
|
||||
* */
|
||||
|
||||
#ifndef LZ4F_H_09782039843
|
||||
#define LZ4F_H_09782039843
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* --- Dependency --- */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/*-***************************************************************
|
||||
* Compiler specifics
|
||||
*****************************************************************/
|
||||
/*!
|
||||
* LZ4_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
*/
|
||||
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
|
||||
# define LZ4FLIB_API __declspec(dllexport)
|
||||
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
|
||||
# define LZ4FLIB_API __declspec(dllimport)
|
||||
#else
|
||||
# define LZ4FLIB_API
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define LZ4F_DEPRECATE(x) x /* __declspec(deprecated) x - only works with C++ */
|
||||
#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
|
||||
# define LZ4F_DEPRECATE(x) x __attribute__((deprecated))
|
||||
#else
|
||||
# define LZ4F_DEPRECATE(x) x /* no deprecation warning for this compiler */
|
||||
#endif
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Error management
|
||||
**************************************/
|
||||
typedef size_t LZ4F_errorCode_t;
|
||||
|
||||
LZ4FLIB_API unsigned LZ4F_isError(LZ4F_errorCode_t code);
|
||||
LZ4FLIB_API const char* LZ4F_getErrorName(LZ4F_errorCode_t code); /* return error code string; useful for debugging */
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Frame compression types
|
||||
**************************************/
|
||||
/* #define LZ4F_DISABLE_OBSOLETE_ENUMS */ /* uncomment to disable obsolete enums */
|
||||
#ifndef LZ4F_DISABLE_OBSOLETE_ENUMS
|
||||
# define LZ4F_OBSOLETE_ENUM(x) , LZ4F_DEPRECATE(x) = LZ4F_##x
|
||||
#else
|
||||
# define LZ4F_OBSOLETE_ENUM(x)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LZ4F_default=0,
|
||||
LZ4F_max64KB=4,
|
||||
LZ4F_max256KB=5,
|
||||
LZ4F_max1MB=6,
|
||||
LZ4F_max4MB=7
|
||||
LZ4F_OBSOLETE_ENUM(max64KB)
|
||||
LZ4F_OBSOLETE_ENUM(max256KB)
|
||||
LZ4F_OBSOLETE_ENUM(max1MB)
|
||||
LZ4F_OBSOLETE_ENUM(max4MB)
|
||||
} LZ4F_blockSizeID_t;
|
||||
|
||||
typedef enum {
|
||||
LZ4F_blockLinked=0,
|
||||
LZ4F_blockIndependent
|
||||
LZ4F_OBSOLETE_ENUM(blockLinked)
|
||||
LZ4F_OBSOLETE_ENUM(blockIndependent)
|
||||
} LZ4F_blockMode_t;
|
||||
|
||||
typedef enum {
|
||||
LZ4F_noContentChecksum=0,
|
||||
LZ4F_contentChecksumEnabled
|
||||
LZ4F_OBSOLETE_ENUM(noContentChecksum)
|
||||
LZ4F_OBSOLETE_ENUM(contentChecksumEnabled)
|
||||
} LZ4F_contentChecksum_t;
|
||||
|
||||
typedef enum {
|
||||
LZ4F_frame=0,
|
||||
LZ4F_skippableFrame
|
||||
LZ4F_OBSOLETE_ENUM(skippableFrame)
|
||||
} LZ4F_frameType_t;
|
||||
|
||||
#ifndef LZ4F_DISABLE_OBSOLETE_ENUMS
|
||||
typedef LZ4F_blockSizeID_t blockSizeID_t;
|
||||
typedef LZ4F_blockMode_t blockMode_t;
|
||||
typedef LZ4F_frameType_t frameType_t;
|
||||
typedef LZ4F_contentChecksum_t contentChecksum_t;
|
||||
#endif
|
||||
|
||||
/* LZ4F_frameInfo_t :
|
||||
* makes it possible to supply detailed frame parameters to the stream interface.
|
||||
* It's not required to set all fields, as long as the structure was initially memset() to zero.
|
||||
* All reserved fields must be set to zero. */
|
||||
typedef struct {
|
||||
LZ4F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
LZ4F_blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
LZ4F_contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
LZ4F_frameType_t frameType; /* LZ4F_frame, skippableFrame ; 0 == default */
|
||||
unsigned long long contentSize; /* Size of uncompressed (original) content ; 0 == unknown */
|
||||
unsigned reserved[2]; /* must be zero for forward compatibility */
|
||||
} LZ4F_frameInfo_t;
|
||||
|
||||
/* LZ4F_preferences_t :
|
||||
* makes it possible to supply detailed compression parameters to the stream interface.
|
||||
* It's not required to set all fields, as long as the structure was initially memset() to zero.
|
||||
* All reserved fields must be set to zero. */
|
||||
typedef struct {
|
||||
LZ4F_frameInfo_t frameInfo;
|
||||
int compressionLevel; /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */
|
||||
unsigned autoFlush; /* 1 == always flush (reduce usage of tmp buffer) */
|
||||
unsigned reserved[4]; /* must be zero for forward compatibility */
|
||||
} LZ4F_preferences_t;
|
||||
|
||||
|
||||
/*-*********************************
|
||||
* Simple compression function
|
||||
***********************************/
|
||||
/*!LZ4F_compressFrameBound() :
|
||||
* Returns the maximum possible size of a frame compressed with LZ4F_compressFrame() given srcSize content and preferences.
|
||||
* Note : this result is only usable with LZ4F_compressFrame(), not with multi-segments compression.
|
||||
*/
|
||||
LZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
|
||||
/*!LZ4F_compressFrame() :
|
||||
* Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.5.1
|
||||
* An important rule is that dstBuffer MUST be large enough (dstCapacity) to store the result in worst case situation.
|
||||
* This value is supplied by LZ4F_compressFrameBound().
|
||||
* If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode).
|
||||
* The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
|
||||
* @return : number of bytes written into dstBuffer.
|
||||
* or an error code if it fails (can be tested using LZ4F_isError())
|
||||
*/
|
||||
LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
|
||||
|
||||
|
||||
|
||||
/*-***********************************
|
||||
* Advanced compression functions
|
||||
*************************************/
|
||||
typedef struct LZ4F_cctx_s LZ4F_cctx; /* incomplete type */
|
||||
typedef LZ4F_cctx* LZ4F_compressionContext_t; /* for compatibility with previous API version */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableSrc; /* 1 == src content will remain present on future calls to LZ4F_compress(); skip copying src content within tmp buffer */
|
||||
unsigned reserved[3];
|
||||
} LZ4F_compressOptions_t;
|
||||
|
||||
/* Resource Management */
|
||||
|
||||
#define LZ4F_VERSION 100
|
||||
LZ4FLIB_API unsigned LZ4F_getVersion(void);
|
||||
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version);
|
||||
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx);
|
||||
/* LZ4F_createCompressionContext() :
|
||||
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
|
||||
* This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
|
||||
* The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL.
|
||||
* The function will provide a pointer to a fully allocated LZ4F_cctx object.
|
||||
* If @return != zero, there was an error during context creation.
|
||||
* Object can release its memory using LZ4F_freeCompressionContext();
|
||||
*/
|
||||
|
||||
|
||||
/* Compression */
|
||||
|
||||
#define LZ4F_HEADER_SIZE_MAX 15
|
||||
LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_preferences_t* prefsPtr);
|
||||
/* LZ4F_compressBegin() :
|
||||
* will write the frame header into dstBuffer.
|
||||
* dstCapacity must be large enough to store the header. Maximum header size is LZ4F_HEADER_SIZE_MAX bytes.
|
||||
* `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default.
|
||||
* @return : number of bytes written into dstBuffer for the header
|
||||
* or an error code (which can be tested using LZ4F_isError())
|
||||
*/
|
||||
|
||||
LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);
|
||||
/* LZ4F_compressBound() :
|
||||
* Provides dstCapacity given a srcSize to guarantee operation success in worst case situations.
|
||||
* prefsPtr is optional : you can provide NULL as argument, preferences will be set to cover worst case scenario.
|
||||
* Result is always the same for a srcSize and prefsPtr, so it can be trusted to size reusable buffers.
|
||||
* When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations.
|
||||
*/
|
||||
|
||||
LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* cOptPtr);
|
||||
/* LZ4F_compressUpdate() :
|
||||
* LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
|
||||
* An important rule is that dstCapacity MUST be large enough to ensure operation success even in worst case situations.
|
||||
* This value is provided by LZ4F_compressBound().
|
||||
* If this condition is not respected, LZ4F_compress() will fail (result is an errorCode).
|
||||
* LZ4F_compressUpdate() doesn't guarantee error recovery. When an error occurs, compression context must be freed or resized.
|
||||
* `cOptPtr` is optional : NULL can be provided, in which case all options are set to default.
|
||||
* @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).
|
||||
* or an error code if it fails (which can be tested using LZ4F_isError())
|
||||
*/
|
||||
|
||||
LZ4FLIB_API size_t LZ4F_flush(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t* cOptPtr);
|
||||
/* LZ4F_flush() :
|
||||
* When data must be generated and sent immediately, without waiting for a block to be completely filled,
|
||||
* it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx.
|
||||
* `dstCapacity` must be large enough to ensure the operation will be successful.
|
||||
* `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.
|
||||
* @return : number of bytes written into dstBuffer (it can be zero, which means there was no data stored within cctx)
|
||||
* or an error code if it fails (which can be tested using LZ4F_isError())
|
||||
*/
|
||||
|
||||
LZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_cctx* cctx, void* dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t* cOptPtr);
|
||||
/* LZ4F_compressEnd() :
|
||||
* To properly finish an LZ4 frame, invoke LZ4F_compressEnd().
|
||||
* It will flush whatever data remained within `cctx` (like LZ4_flush())
|
||||
* and properly finalize the frame, with an endMark and a checksum.
|
||||
* `cOptPtr` is optional : NULL can be provided, in which case all options will be set to default.
|
||||
* @return : number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)
|
||||
* or an error code if it fails (which can be tested using LZ4F_isError())
|
||||
* A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task.
|
||||
*/
|
||||
|
||||
|
||||
/*-*********************************
|
||||
* Decompression functions
|
||||
***********************************/
|
||||
typedef struct LZ4F_dctx_s LZ4F_dctx; /* incomplete type */
|
||||
typedef LZ4F_dctx* LZ4F_decompressionContext_t; /* compatibility with previous API versions */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableDst; /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */
|
||||
unsigned reserved[3];
|
||||
} LZ4F_decompressOptions_t;
|
||||
|
||||
|
||||
/* Resource management */
|
||||
|
||||
/*!LZ4F_createDecompressionContext() :
|
||||
* Create an LZ4F_decompressionContext_t object, which will be used to track all decompression operations.
|
||||
* The version provided MUST be LZ4F_VERSION. It is intended to track potential breaking differences between different versions.
|
||||
* The function will provide a pointer to a fully allocated and initialized LZ4F_decompressionContext_t object.
|
||||
* The result is an errorCode, which can be tested using LZ4F_isError().
|
||||
* dctx memory can be released using LZ4F_freeDecompressionContext();
|
||||
* The result of LZ4F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
|
||||
* That is, it should be == 0 if decompression has been completed fully and correctly.
|
||||
*/
|
||||
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version);
|
||||
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* const dctx);
|
||||
|
||||
|
||||
/*====== Decompression ======*/
|
||||
|
||||
/*!LZ4F_getFrameInfo() :
|
||||
* This function decodes frame header information (such as max blockSize, frame checksum, etc.).
|
||||
* Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.
|
||||
* A header size is variable and can length from 7 to 15 bytes. It's possible to provide more input bytes than that.
|
||||
* The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).
|
||||
* Decompression must resume from this point (srcBuffer + *srcSizePtr).
|
||||
* Note that LZ4F_getFrameInfo() can also be used anytime *after* decompression is started, in which case 0 input byte can be enough.
|
||||
* Frame header info is *copied into* an already allocated LZ4F_frameInfo_t structure.
|
||||
* @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,
|
||||
* or an error code which can be tested using LZ4F_isError()
|
||||
* (typically, when there is not enough src bytes to fully decode the frame header)
|
||||
*/
|
||||
LZ4FLIB_API size_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
|
||||
LZ4F_frameInfo_t* frameInfoPtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr);
|
||||
|
||||
/*!LZ4F_decompress() :
|
||||
* Call this function repetitively to regenerate data compressed within `srcBuffer`.
|
||||
* The function will attempt to decode up to *srcSizePtr bytes from srcBuffer, into dstBuffer of capacity *dstSizePtr.
|
||||
*
|
||||
* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
|
||||
*
|
||||
* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* Number of bytes read can be < number of bytes provided, meaning there is some more data to decode.
|
||||
* It typically happens when dstBuffer is not large enough to contain all decoded data.
|
||||
* Remaining data will have to be presented again in a subsequent invocation.
|
||||
*
|
||||
* `dstBuffer` content is expected to be flushed between each invocation, as its content will be overwritten.
|
||||
* `dstBuffer` can be changed at will between each consecutive function invocation.
|
||||
*
|
||||
* @return is an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call.
|
||||
* Schematically, it's the size of the current (or remaining) compressed block + header of next block.
|
||||
* Respecting the hint provides some boost to performance, since it does skip intermediate buffers.
|
||||
* This is just a hint though, it's always possible to provide any srcSize.
|
||||
* When a frame is fully decoded, @return will be 0 (no more data expected).
|
||||
* If decompression failed, @return is an error code, which can be tested using LZ4F_isError().
|
||||
*
|
||||
* After a frame is fully decoded, dctx can be used again to decompress another frame.
|
||||
*/
|
||||
LZ4FLIB_API size_t LZ4F_decompress(LZ4F_dctx* dctx,
|
||||
void* dstBuffer, size_t* dstSizePtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr,
|
||||
const LZ4F_decompressOptions_t* dOptPtr);
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LZ4F_H_09782039843 */
|
||||
82
Kinc/Sources/kinc/io/lz4/lz4frame_static.h
Normal file
82
Kinc/Sources/kinc/io/lz4/lz4frame_static.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
LZ4 auto-framing library
|
||||
Header File for static linking only
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
#ifndef LZ4FRAME_STATIC_H_0398209384
|
||||
#define LZ4FRAME_STATIC_H_0398209384
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* lz4frame_static.h should be used solely in the context of static linking.
|
||||
* It contains definitions which are not stable and may change in the future.
|
||||
* Never use it in the context of DLL linking.
|
||||
* */
|
||||
|
||||
|
||||
/* --- Dependency --- */
|
||||
#include "lz4frame.h"
|
||||
|
||||
|
||||
/* --- Error List --- */
|
||||
#define LZ4F_LIST_ERRORS(ITEM) \
|
||||
ITEM(OK_NoError) ITEM(ERROR_GENERIC) \
|
||||
ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \
|
||||
ITEM(ERROR_compressionLevel_invalid) \
|
||||
ITEM(ERROR_headerVersion_wrong) ITEM(ERROR_blockChecksum_unsupported) ITEM(ERROR_reservedFlag_set) \
|
||||
ITEM(ERROR_allocation_failed) \
|
||||
ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \
|
||||
ITEM(ERROR_frameHeader_incomplete) ITEM(ERROR_frameType_unknown) ITEM(ERROR_frameSize_wrong) \
|
||||
ITEM(ERROR_srcPtr_wrong) \
|
||||
ITEM(ERROR_decompressionFailed) \
|
||||
ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \
|
||||
ITEM(ERROR_maxCode)
|
||||
|
||||
#define LZ4F_DISABLE_OLD_ENUMS /* comment to enable deprecated enums */
|
||||
#ifndef LZ4F_DISABLE_OLD_ENUMS
|
||||
# define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM, ENUM = LZ4F_##ENUM,
|
||||
#else
|
||||
# define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM,
|
||||
#endif
|
||||
typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM) } LZ4F_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
|
||||
|
||||
LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LZ4FRAME_STATIC_H_0398209384 */
|
||||
720
Kinc/Sources/kinc/io/lz4/lz4hc.c
Normal file
720
Kinc/Sources/kinc/io/lz4/lz4hc.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
LZ4 HC - High Compression Mode of LZ4
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Tuning Parameter
|
||||
***************************************/
|
||||
|
||||
/*!
|
||||
* HEAPMODE :
|
||||
* Select how default compression function will allocate workplace memory,
|
||||
* in stack (0:fastest), or in heap (1:requires malloc()).
|
||||
* Since workplace is rather large, heap mode is recommended.
|
||||
*/
|
||||
#ifndef LZ4HC_HEAPMODE
|
||||
# define LZ4HC_HEAPMODE 1
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Dependency
|
||||
***************************************/
|
||||
#include "lz4hc.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Local Compiler Options
|
||||
***************************************/
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#if defined (__clang__)
|
||||
# pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Common LZ4 definition
|
||||
***************************************/
|
||||
#define LZ4_COMMONDEFS_ONLY
|
||||
#include "lz4.c"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Local Constants
|
||||
***************************************/
|
||||
#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
|
||||
|
||||
|
||||
/**************************************
|
||||
* Local Macros
|
||||
**************************************/
|
||||
#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
|
||||
#define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */
|
||||
#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */
|
||||
|
||||
static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* HC Compression
|
||||
**************************************/
|
||||
static void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start)
|
||||
{
|
||||
MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
|
||||
MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
|
||||
hc4->nextToUpdate = 64 KB;
|
||||
hc4->base = start - 64 KB;
|
||||
hc4->end = start;
|
||||
hc4->dictBase = start - 64 KB;
|
||||
hc4->dictLimit = 64 KB;
|
||||
hc4->lowLimit = 64 KB;
|
||||
}
|
||||
|
||||
|
||||
/* Update chains up to ip (excluded) */
|
||||
FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
|
||||
{
|
||||
U16* const chainTable = hc4->chainTable;
|
||||
U32* const hashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
U32 const target = (U32)(ip - base);
|
||||
U32 idx = hc4->nextToUpdate;
|
||||
|
||||
while (idx < target) {
|
||||
U32 const h = LZ4HC_hashPtr(base+idx);
|
||||
size_t delta = idx - hashTable[h];
|
||||
if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
|
||||
DELTANEXTU16(idx) = (U16)delta;
|
||||
hashTable[h] = idx;
|
||||
idx++;
|
||||
}
|
||||
|
||||
hc4->nextToUpdate = target;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos,
|
||||
const int maxNbAttempts)
|
||||
{
|
||||
U16* const chainTable = hc4->chainTable;
|
||||
U32* const HashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
const BYTE* const dictBase = hc4->dictBase;
|
||||
const U32 dictLimit = hc4->dictLimit;
|
||||
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
|
||||
U32 matchIndex;
|
||||
int nbAttempts=maxNbAttempts;
|
||||
size_t ml=0;
|
||||
|
||||
/* HC4 match finder */
|
||||
LZ4HC_Insert(hc4, ip);
|
||||
matchIndex = HashTable[LZ4HC_hashPtr(ip)];
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit) {
|
||||
const BYTE* const match = base + matchIndex;
|
||||
if (*(match+ml) == *(ip+ml)
|
||||
&& (LZ4_read32(match) == LZ4_read32(ip)))
|
||||
{
|
||||
size_t const mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if (mlt > ml) { ml = mlt; *matchpos = match; }
|
||||
}
|
||||
} else {
|
||||
const BYTE* const match = dictBase + matchIndex;
|
||||
if (LZ4_read32(match) == LZ4_read32(ip)) {
|
||||
size_t mlt;
|
||||
const BYTE* vLimit = ip + (dictLimit - matchIndex);
|
||||
if (vLimit > iLimit) vLimit = iLimit;
|
||||
mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
|
||||
if ((ip+mlt == vLimit) && (vLimit < iLimit))
|
||||
mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
|
||||
if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
matchIndex -= DELTANEXTU16(matchIndex);
|
||||
}
|
||||
|
||||
return (int)ml;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
|
||||
LZ4HC_CCtx_internal* hc4,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
int longest,
|
||||
const BYTE** matchpos,
|
||||
const BYTE** startpos,
|
||||
const int maxNbAttempts)
|
||||
{
|
||||
U16* const chainTable = hc4->chainTable;
|
||||
U32* const HashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
const U32 dictLimit = hc4->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
|
||||
const BYTE* const dictBase = hc4->dictBase;
|
||||
U32 matchIndex;
|
||||
int nbAttempts = maxNbAttempts;
|
||||
int delta = (int)(ip-iLowLimit);
|
||||
|
||||
|
||||
/* First Match */
|
||||
LZ4HC_Insert(hc4, ip);
|
||||
matchIndex = HashTable[LZ4HC_hashPtr(ip)];
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit) {
|
||||
const BYTE* matchPtr = base + matchIndex;
|
||||
if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) {
|
||||
if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
|
||||
int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
|
||||
int back = 0;
|
||||
|
||||
while ((ip+back > iLowLimit)
|
||||
&& (matchPtr+back > lowPrefixPtr)
|
||||
&& (ip[back-1] == matchPtr[back-1]))
|
||||
back--;
|
||||
|
||||
mlt -= back;
|
||||
|
||||
if (mlt > longest) {
|
||||
longest = (int)mlt;
|
||||
*matchpos = matchPtr+back;
|
||||
*startpos = ip+back;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const BYTE* const matchPtr = dictBase + matchIndex;
|
||||
if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
|
||||
size_t mlt;
|
||||
int back=0;
|
||||
const BYTE* vLimit = ip + (dictLimit - matchIndex);
|
||||
if (vLimit > iHighLimit) vLimit = iHighLimit;
|
||||
mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
|
||||
if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
|
||||
mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
|
||||
mlt -= back;
|
||||
if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
|
||||
}
|
||||
}
|
||||
matchIndex -= DELTANEXTU16(matchIndex);
|
||||
}
|
||||
|
||||
return longest;
|
||||
}
|
||||
|
||||
|
||||
typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
|
||||
|
||||
#define LZ4HC_DEBUG 0
|
||||
#if LZ4HC_DEBUG
|
||||
static unsigned debug = 0;
|
||||
#endif
|
||||
|
||||
FORCE_INLINE int LZ4HC_encodeSequence (
|
||||
const BYTE** ip,
|
||||
BYTE** op,
|
||||
const BYTE** anchor,
|
||||
int matchLength,
|
||||
const BYTE* const match,
|
||||
limitedOutput_directive limitedOutputBuffer,
|
||||
BYTE* oend)
|
||||
{
|
||||
int length;
|
||||
BYTE* token;
|
||||
|
||||
#if LZ4HC_DEBUG
|
||||
if (debug) printf("literal : %u -- match : %u -- offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
|
||||
#endif
|
||||
|
||||
/* Encode Literal length */
|
||||
length = (int)(*ip - *anchor);
|
||||
token = (*op)++;
|
||||
if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */
|
||||
if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; }
|
||||
else *token = (BYTE)(length<<ML_BITS);
|
||||
|
||||
/* Copy Literals */
|
||||
LZ4_wildCopy(*op, *anchor, (*op) + length);
|
||||
*op += length;
|
||||
|
||||
/* Encode Offset */
|
||||
LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
|
||||
|
||||
/* Encode MatchLength */
|
||||
length = (int)(matchLength-MINMATCH);
|
||||
if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */
|
||||
if (length>=(int)ML_MASK) {
|
||||
*token += ML_MASK;
|
||||
length -= ML_MASK;
|
||||
for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; }
|
||||
if (length > 254) { length-=255; *(*op)++ = 255; }
|
||||
*(*op)++ = (BYTE)length;
|
||||
} else {
|
||||
*token += (BYTE)(length);
|
||||
}
|
||||
|
||||
/* Prepare next loop */
|
||||
*ip += matchLength;
|
||||
*anchor = *ip;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "lz4opt.h"
|
||||
|
||||
static int LZ4HC_compress_hashChain (
|
||||
LZ4HC_CCtx_internal* const ctx,
|
||||
const char* const source,
|
||||
char* const dest,
|
||||
int const inputSize,
|
||||
int const maxOutputSize,
|
||||
unsigned maxNbAttempts,
|
||||
limitedOutput_directive limit
|
||||
)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) source;
|
||||
const BYTE* anchor = ip;
|
||||
const BYTE* const iend = ip + inputSize;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = (iend - LASTLITERALS);
|
||||
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + maxOutputSize;
|
||||
|
||||
int ml, ml2, ml3, ml0;
|
||||
const BYTE* ref = NULL;
|
||||
const BYTE* start2 = NULL;
|
||||
const BYTE* ref2 = NULL;
|
||||
const BYTE* start3 = NULL;
|
||||
const BYTE* ref3 = NULL;
|
||||
const BYTE* start0;
|
||||
const BYTE* ref0;
|
||||
|
||||
/* init */
|
||||
ctx->end += inputSize;
|
||||
|
||||
ip++;
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit) {
|
||||
ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
|
||||
if (!ml) { ip++; continue; }
|
||||
|
||||
/* saved, in case we would skip too much */
|
||||
start0 = ip;
|
||||
ref0 = ref;
|
||||
ml0 = ml;
|
||||
|
||||
_Search2:
|
||||
if (ip+ml < mflimit)
|
||||
ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 0, matchlimit, ml, &ref2, &start2, maxNbAttempts);
|
||||
else ml2 = ml;
|
||||
|
||||
if (ml2 == ml) { /* No better match */
|
||||
if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start0 < ip) {
|
||||
if (start2 < ip + ml0) { /* empirical */
|
||||
ip = start0;
|
||||
ref = ref0;
|
||||
ml = ml0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Here, start0==ip */
|
||||
if ((start2 - ip) < 3) { /* First Match too small : removed */
|
||||
ml = ml2;
|
||||
ip = start2;
|
||||
ref =ref2;
|
||||
goto _Search2;
|
||||
}
|
||||
|
||||
_Search3:
|
||||
/*
|
||||
* Currently we have :
|
||||
* ml2 > ml1, and
|
||||
* ip1+3 <= ip2 (usually < ip1+ml1)
|
||||
*/
|
||||
if ((start2 - ip) < OPTIMAL_ML) {
|
||||
int correction;
|
||||
int new_ml = ml;
|
||||
if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
|
||||
if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
|
||||
correction = new_ml - (int)(start2 - ip);
|
||||
if (correction > 0) {
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
}
|
||||
}
|
||||
/* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
|
||||
|
||||
if (start2 + ml2 < mflimit)
|
||||
ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
|
||||
else ml3 = ml2;
|
||||
|
||||
if (ml3 == ml2) { /* No better match : 2 sequences to encode */
|
||||
/* ip & ref are known; Now for ml */
|
||||
if (start2 < ip+ml) ml = (int)(start2 - ip);
|
||||
/* Now, encode 2 sequences */
|
||||
if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
ip = start2;
|
||||
if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start3 < ip+ml+3) { /* Not enough space for match 2 : remove it */
|
||||
if (start3 >= (ip+ml)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
|
||||
if (start2 < ip+ml) {
|
||||
int correction = (int)(ip+ml - start2);
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
if (ml2 < MINMATCH) {
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
}
|
||||
}
|
||||
|
||||
if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
|
||||
start0 = start2;
|
||||
ref0 = ref2;
|
||||
ml0 = ml2;
|
||||
goto _Search2;
|
||||
}
|
||||
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
goto _Search3;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, now we have 3 ascending matches; let's write at least the first one
|
||||
* ip & ref are known; Now for ml
|
||||
*/
|
||||
if (start2 < ip+ml) {
|
||||
if ((start2 - ip) < (int)ML_MASK) {
|
||||
int correction;
|
||||
if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
|
||||
if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
|
||||
correction = ml - (int)(start2 - ip);
|
||||
if (correction > 0) {
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
}
|
||||
} else {
|
||||
ml = (int)(start2 - ip);
|
||||
}
|
||||
}
|
||||
if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
|
||||
ip = start2;
|
||||
ref = ref2;
|
||||
ml = ml2;
|
||||
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
|
||||
goto _Search3;
|
||||
}
|
||||
|
||||
/* Encode Last Literals */
|
||||
{ int lastRun = (int)(iend - anchor);
|
||||
if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */
|
||||
if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
|
||||
else *op++ = (BYTE)(lastRun<<ML_BITS);
|
||||
memcpy(op, anchor, iend - anchor);
|
||||
op += iend-anchor;
|
||||
}
|
||||
|
||||
/* End */
|
||||
return (int) (((char*)op)-dest);
|
||||
}
|
||||
|
||||
static int LZ4HC_getSearchNum(int compressionLevel)
|
||||
{
|
||||
switch (compressionLevel) {
|
||||
default: return 0; /* unused */
|
||||
case 11: return 128;
|
||||
case 12: return 1<<10;
|
||||
}
|
||||
}
|
||||
|
||||
static int LZ4HC_compress_generic (
|
||||
LZ4HC_CCtx_internal* const ctx,
|
||||
const char* const source,
|
||||
char* const dest,
|
||||
int const inputSize,
|
||||
int const maxOutputSize,
|
||||
int compressionLevel,
|
||||
limitedOutput_directive limit
|
||||
)
|
||||
{
|
||||
if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT;
|
||||
if (compressionLevel > 9) {
|
||||
switch (compressionLevel) {
|
||||
case 10: return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (16-1), limit);
|
||||
case 11: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, 128, 0);
|
||||
default:
|
||||
case 12: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, LZ4_OPT_NUM, 1);
|
||||
}
|
||||
}
|
||||
return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (compressionLevel-1), limit);
|
||||
}
|
||||
|
||||
|
||||
int LZ4_sizeofStateHC(void) { return sizeof(LZ4_streamHC_t); }
|
||||
|
||||
int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
LZ4HC_CCtx_internal* ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
|
||||
if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
|
||||
LZ4HC_init (ctx, (const BYTE*)src);
|
||||
if (maxDstSize < LZ4_compressBound(srcSize))
|
||||
return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
|
||||
else
|
||||
return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
|
||||
}
|
||||
|
||||
int LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
|
||||
LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t));
|
||||
#else
|
||||
LZ4_streamHC_t state;
|
||||
LZ4_streamHC_t* const statePtr = &state;
|
||||
#endif
|
||||
int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, maxDstSize, compressionLevel);
|
||||
#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
|
||||
free(statePtr);
|
||||
#endif
|
||||
return cSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Streaming Functions
|
||||
**************************************/
|
||||
/* allocation */
|
||||
LZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
|
||||
int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
|
||||
|
||||
|
||||
/* initialization */
|
||||
void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
|
||||
{
|
||||
LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= sizeof(size_t) * LZ4_STREAMHCSIZE_SIZET); /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
|
||||
LZ4_streamHCPtr->internal_donotuse.base = NULL;
|
||||
LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned)compressionLevel;
|
||||
LZ4_streamHCPtr->internal_donotuse.searchNum = LZ4HC_getSearchNum(compressionLevel);
|
||||
}
|
||||
|
||||
int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
|
||||
{
|
||||
LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
|
||||
if (dictSize > 64 KB) {
|
||||
dictionary += dictSize - 64 KB;
|
||||
dictSize = 64 KB;
|
||||
}
|
||||
LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
|
||||
ctxPtr->end = (const BYTE*)dictionary + dictSize;
|
||||
if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
|
||||
LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
|
||||
else
|
||||
if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
/* compression */
|
||||
|
||||
static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
|
||||
{
|
||||
if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
|
||||
LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
|
||||
else
|
||||
if (ctxPtr->end >= ctxPtr->base + 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
|
||||
|
||||
/* Only one memory segment for extDict, so any previous extDict is lost at this stage */
|
||||
ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
|
||||
ctxPtr->dictBase = ctxPtr->base;
|
||||
ctxPtr->base = newBlock - ctxPtr->dictLimit;
|
||||
ctxPtr->end = newBlock;
|
||||
ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
|
||||
}
|
||||
|
||||
static int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
|
||||
const char* source, char* dest,
|
||||
int inputSize, int maxOutputSize, limitedOutput_directive limit)
|
||||
{
|
||||
LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
|
||||
/* auto-init if forgotten */
|
||||
if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) source);
|
||||
|
||||
/* Check overflow */
|
||||
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
|
||||
size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
|
||||
if (dictSize > 64 KB) dictSize = 64 KB;
|
||||
LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
|
||||
}
|
||||
|
||||
/* Check if blocks follow each other */
|
||||
if ((const BYTE*)source != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
|
||||
|
||||
/* Check overlapping input/dictionary space */
|
||||
{ const BYTE* sourceEnd = (const BYTE*) source + inputSize;
|
||||
const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
|
||||
const BYTE* const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
|
||||
if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) {
|
||||
if (sourceEnd > dictEnd) sourceEnd = dictEnd;
|
||||
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
|
||||
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
|
||||
}
|
||||
|
||||
int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
if (maxOutputSize < LZ4_compressBound(inputSize))
|
||||
return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
|
||||
else
|
||||
return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
|
||||
}
|
||||
|
||||
|
||||
/* dictionary saving */
|
||||
|
||||
int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
|
||||
{
|
||||
LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
|
||||
int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
|
||||
if (dictSize > 64 KB) dictSize = 64 KB;
|
||||
if (dictSize < 4) dictSize = 0;
|
||||
if (dictSize > prefixSize) dictSize = prefixSize;
|
||||
memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
|
||||
{ U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
|
||||
streamPtr->end = (const BYTE*)safeBuffer + dictSize;
|
||||
streamPtr->base = streamPtr->end - endIndex;
|
||||
streamPtr->dictLimit = endIndex - dictSize;
|
||||
streamPtr->lowLimit = endIndex - dictSize;
|
||||
if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
|
||||
}
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Deprecated Functions
|
||||
***********************************/
|
||||
/* These functions currently generate deprecation warnings */
|
||||
/* Deprecated compression functions */
|
||||
int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
|
||||
int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
|
||||
int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
|
||||
int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
|
||||
int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
|
||||
int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
|
||||
int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
|
||||
int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
|
||||
int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }
|
||||
int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
|
||||
|
||||
|
||||
/* Deprecated streaming functions */
|
||||
int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
|
||||
|
||||
int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
|
||||
{
|
||||
LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
|
||||
if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */
|
||||
LZ4HC_init(ctx, (const BYTE*)inputBuffer);
|
||||
ctx->inputBuffer = (BYTE*)inputBuffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* LZ4_createHC (char* inputBuffer)
|
||||
{
|
||||
LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOCATOR(1, sizeof(LZ4_streamHC_t));
|
||||
if (hc4 == NULL) return NULL; /* not enough memory */
|
||||
LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
|
||||
hc4->internal_donotuse.inputBuffer = (BYTE*)inputBuffer;
|
||||
return hc4;
|
||||
}
|
||||
|
||||
int LZ4_freeHC (void* LZ4HC_Data) { FREEMEM(LZ4HC_Data); return 0; }
|
||||
|
||||
int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
|
||||
{
|
||||
return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, 0, compressionLevel, noLimit);
|
||||
}
|
||||
|
||||
int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
|
||||
{
|
||||
return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
|
||||
}
|
||||
|
||||
char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
|
||||
{
|
||||
LZ4HC_CCtx_internal* const hc4 = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
|
||||
int const dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
|
||||
return (char*)(hc4->inputBuffer + dictSize);
|
||||
}
|
||||
228
Kinc/Sources/kinc/io/lz4/lz4hc.h
Normal file
228
Kinc/Sources/kinc/io/lz4/lz4hc.h
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
LZ4 HC - High Compression Mode of LZ4
|
||||
Header File
|
||||
Copyright (C) 2011-2016, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
#ifndef LZ4_HC_H_19834876238432
|
||||
#define LZ4_HC_H_19834876238432
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* --- Dependency --- */
|
||||
/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
|
||||
#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
|
||||
|
||||
|
||||
/* --- Useful constants --- */
|
||||
#define LZ4HC_CLEVEL_MIN 3
|
||||
#define LZ4HC_CLEVEL_DEFAULT 9
|
||||
#define LZ4HC_CLEVEL_OPT_MIN 11
|
||||
#define LZ4HC_CLEVEL_MAX 12
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Block Compression
|
||||
**************************************/
|
||||
/*! LZ4_compress_HC() :
|
||||
* Compress data from `src` into `dst`, using the more powerful but slower "HC" algorithm.
|
||||
* `dst` must be already allocated.
|
||||
* Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h")
|
||||
* Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
|
||||
* `compressionLevel` : Recommended values are between 4 and 9, although any value between 1 and LZ4HC_MAX_CLEVEL will work.
|
||||
* Values >LZ4HC_MAX_CLEVEL behave the same as LZ4HC_MAX_CLEVEL.
|
||||
* @return : the number of bytes written into 'dst'
|
||||
* or 0 if compression fails.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);
|
||||
|
||||
|
||||
/* Note :
|
||||
* Decompression functions are provided within "lz4.h" (BSD license)
|
||||
*/
|
||||
|
||||
|
||||
/*! LZ4_compress_HC_extStateHC() :
|
||||
* Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.
|
||||
* `state` size is provided by LZ4_sizeofStateHC().
|
||||
* Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
LZ4LIB_API int LZ4_sizeofStateHC(void);
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Streaming Compression
|
||||
* Bufferless synchronous API
|
||||
**************************************/
|
||||
typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */
|
||||
|
||||
/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :
|
||||
* These functions create and release memory for LZ4 HC streaming state.
|
||||
* Newly created states are automatically initialized.
|
||||
* Existing states can be re-used several times, using LZ4_resetStreamHC().
|
||||
* These methods are API and ABI stable, they can be used in combination with a DLL.
|
||||
*/
|
||||
LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);
|
||||
LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
|
||||
|
||||
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
|
||||
LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
|
||||
|
||||
LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
|
||||
LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
|
||||
|
||||
/*
|
||||
These functions compress data in successive blocks of any size, using previous blocks as dictionary.
|
||||
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
|
||||
There is an exception for ring buffers, which can be smaller than 64 KB.
|
||||
Ring buffers scenario is automatically detected and handled by LZ4_compress_HC_continue().
|
||||
|
||||
Before starting compression, state must be properly initialized, using LZ4_resetStreamHC().
|
||||
A first "fictional block" can then be designated as initial dictionary, using LZ4_loadDictHC() (Optional).
|
||||
|
||||
Then, use LZ4_compress_HC_continue() to compress each successive block.
|
||||
Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.
|
||||
'dst' buffer should be sized to handle worst case scenarios, using LZ4_compressBound(), to ensure operation success.
|
||||
|
||||
If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,
|
||||
you must save it to a safer memory space, using LZ4_saveDictHC().
|
||||
Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.
|
||||
*/
|
||||
|
||||
|
||||
/*-******************************************
|
||||
* !!!!! STATIC LINKING ONLY !!!!!
|
||||
*******************************************/
|
||||
|
||||
/*-*************************************
|
||||
* PRIVATE DEFINITIONS :
|
||||
* Do not use these definitions.
|
||||
* They are exposed to allow static allocation of `LZ4_streamHC_t`.
|
||||
* Using these definitions makes the code vulnerable to potential API break when upgrading LZ4
|
||||
**************************************/
|
||||
#define LZ4HC_DICTIONARY_LOGSIZE 17
|
||||
#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)
|
||||
#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)
|
||||
|
||||
#define LZ4HC_HASH_LOG 15
|
||||
#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)
|
||||
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
|
||||
|
||||
|
||||
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t hashTable[LZ4HC_HASHTABLESIZE];
|
||||
uint16_t chainTable[LZ4HC_MAXD];
|
||||
const uint8_t* end; /* next block here to continue on current prefix */
|
||||
const uint8_t* base; /* All index relative to this position */
|
||||
const uint8_t* dictBase; /* alternate base for extDict */
|
||||
uint8_t* inputBuffer; /* deprecated */
|
||||
uint32_t dictLimit; /* below that point, need extDict */
|
||||
uint32_t lowLimit; /* below that point, no more dict */
|
||||
uint32_t nextToUpdate; /* index from which to continue dictionary update */
|
||||
uint32_t searchNum; /* only for optimal parser */
|
||||
uint32_t compressionLevel;
|
||||
} LZ4HC_CCtx_internal;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int hashTable[LZ4HC_HASHTABLESIZE];
|
||||
unsigned short chainTable[LZ4HC_MAXD];
|
||||
const unsigned char* end; /* next block here to continue on current prefix */
|
||||
const unsigned char* base; /* All index relative to this position */
|
||||
const unsigned char* dictBase; /* alternate base for extDict */
|
||||
unsigned char* inputBuffer; /* deprecated */
|
||||
unsigned int dictLimit; /* below that point, need extDict */
|
||||
unsigned int lowLimit; /* below that point, no more dict */
|
||||
unsigned int nextToUpdate; /* index from which to continue dictionary update */
|
||||
unsigned int searchNum; /* only for optimal parser */
|
||||
unsigned int compressionLevel;
|
||||
} LZ4HC_CCtx_internal;
|
||||
|
||||
#endif
|
||||
|
||||
#define LZ4_STREAMHCSIZE (4*LZ4HC_HASHTABLESIZE + 2*LZ4HC_MAXD + 56) /* 393268 */
|
||||
#define LZ4_STREAMHCSIZE_SIZET (LZ4_STREAMHCSIZE / sizeof(size_t))
|
||||
union LZ4_streamHC_u {
|
||||
size_t table[LZ4_STREAMHCSIZE_SIZET];
|
||||
LZ4HC_CCtx_internal internal_donotuse;
|
||||
}; /* previously typedef'd to LZ4_streamHC_t */
|
||||
/*
|
||||
LZ4_streamHC_t :
|
||||
This structure allows static allocation of LZ4 HC streaming state.
|
||||
State must be initialized using LZ4_resetStreamHC() before first use.
|
||||
|
||||
Static allocation shall only be used in combination with static linking.
|
||||
When invoking LZ4 from a DLL, use create/free functions instead, which are API and ABI stable.
|
||||
*/
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Deprecated Functions
|
||||
**************************************/
|
||||
/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */
|
||||
|
||||
/* deprecated compression functions */
|
||||
/* these functions will trigger warning messages in future releases */
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC (const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC() instead") int LZ4_compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Deprecated Streaming functions using older model; should no longer be used */
|
||||
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") void* LZ4_createHC (char* inputBuffer);
|
||||
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
|
||||
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") int LZ4_freeHC (void* LZ4HC_Data);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") int LZ4_sizeofStreamStateHC(void);
|
||||
LZ4_DEPRECATED("use LZ4_resetStreamHC() instead") int LZ4_resetStreamStateHC(void* state, char* inputBuffer);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LZ4_HC_H_19834876238432 */
|
||||
363
Kinc/Sources/kinc/io/lz4/lz4opt.h
Normal file
363
Kinc/Sources/kinc/io/lz4/lz4opt.h
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
lz4opt.h - Optimal Mode of LZ4
|
||||
Copyright (C) 2015-2016, Przemyslaw Skibinski <inikep@gmail.com>
|
||||
Note : this file is intended to be included within lz4hc.c
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
#define LZ4_OPT_NUM (1<<12)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int off;
|
||||
int len;
|
||||
} LZ4HC_match_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int price;
|
||||
int off;
|
||||
int mlen;
|
||||
int litlen;
|
||||
} LZ4HC_optimal_t;
|
||||
|
||||
|
||||
/* price in bits */
|
||||
FORCE_INLINE size_t LZ4HC_literalsPrice(size_t litlen)
|
||||
{
|
||||
size_t price = 8*litlen;
|
||||
if (litlen >= (size_t)RUN_MASK) price+=8*(1+(litlen-RUN_MASK)/255);
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
/* requires mlen >= MINMATCH */
|
||||
FORCE_INLINE size_t LZ4HC_sequencePrice(size_t litlen, size_t mlen)
|
||||
{
|
||||
size_t price = 16 + 8; /* 16-bit offset + token */
|
||||
|
||||
price += LZ4HC_literalsPrice(litlen);
|
||||
|
||||
mlen -= MINMATCH;
|
||||
if (mlen >= (size_t)ML_MASK) price+=8*(1+(mlen-ML_MASK)/255);
|
||||
|
||||
return price;
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Binary Tree search
|
||||
***************************************/
|
||||
FORCE_INLINE int LZ4HC_BinTree_InsertAndGetAllMatches (
|
||||
LZ4HC_CCtx_internal* ctx,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iHighLimit,
|
||||
size_t best_mlen,
|
||||
LZ4HC_match_t* matches,
|
||||
int* matchNum)
|
||||
{
|
||||
U16* const chainTable = ctx->chainTable;
|
||||
U32* const HashTable = ctx->hashTable;
|
||||
const BYTE* const base = ctx->base;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const U32 current = (U32)(ip - base);
|
||||
const U32 lowLimit = (ctx->lowLimit + MAX_DISTANCE > current) ? ctx->lowLimit : current - (MAX_DISTANCE - 1);
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* match;
|
||||
int nbAttempts = ctx->searchNum;
|
||||
int mnum = 0;
|
||||
U16 *ptr0, *ptr1, delta0, delta1;
|
||||
U32 matchIndex;
|
||||
size_t matchLength = 0;
|
||||
U32* HashPos;
|
||||
|
||||
if (ip + MINMATCH > iHighLimit) return 1;
|
||||
|
||||
/* HC4 match finder */
|
||||
HashPos = &HashTable[LZ4HC_hashPtr(ip)];
|
||||
matchIndex = *HashPos;
|
||||
*HashPos = current;
|
||||
|
||||
ptr0 = &DELTANEXTMAXD(current*2+1);
|
||||
ptr1 = &DELTANEXTMAXD(current*2);
|
||||
delta0 = delta1 = (U16)(current - matchIndex);
|
||||
|
||||
while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts)) {
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
matchLength = LZ4_count(ip, match, iHighLimit);
|
||||
} else {
|
||||
const BYTE* vLimit = ip + (dictLimit - matchIndex);
|
||||
match = dictBase + matchIndex;
|
||||
if (vLimit > iHighLimit) vLimit = iHighLimit;
|
||||
matchLength = LZ4_count(ip, match, vLimit);
|
||||
if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))
|
||||
matchLength += LZ4_count(ip+matchLength, base+dictLimit, iHighLimit);
|
||||
}
|
||||
|
||||
if (matchLength > best_mlen) {
|
||||
best_mlen = matchLength;
|
||||
if (matches) {
|
||||
if (matchIndex >= dictLimit)
|
||||
matches[mnum].off = (int)(ip - match);
|
||||
else
|
||||
matches[mnum].off = (int)(ip - (base + matchIndex)); /* virtual matchpos */
|
||||
matches[mnum].len = (int)matchLength;
|
||||
mnum++;
|
||||
}
|
||||
if (best_mlen > LZ4_OPT_NUM) break;
|
||||
}
|
||||
|
||||
if (ip+matchLength >= iHighLimit) /* equal : no way to know if inf or sup */
|
||||
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
|
||||
|
||||
if (*(ip+matchLength) < *(match+matchLength)) {
|
||||
*ptr0 = delta0;
|
||||
ptr0 = &DELTANEXTMAXD(matchIndex*2);
|
||||
if (*ptr0 == (U16)-1) break;
|
||||
delta0 = *ptr0;
|
||||
delta1 += delta0;
|
||||
matchIndex -= delta0;
|
||||
} else {
|
||||
*ptr1 = delta1;
|
||||
ptr1 = &DELTANEXTMAXD(matchIndex*2+1);
|
||||
if (*ptr1 == (U16)-1) break;
|
||||
delta1 = *ptr1;
|
||||
delta0 += delta1;
|
||||
matchIndex -= delta1;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr0 = (U16)-1;
|
||||
*ptr1 = (U16)-1;
|
||||
if (matchNum) *matchNum = mnum;
|
||||
/* if (best_mlen > 8) return best_mlen-8; */
|
||||
if (!matchNum) return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE void LZ4HC_updateBinTree(LZ4HC_CCtx_internal* ctx, const BYTE* const ip, const BYTE* const iHighLimit)
|
||||
{
|
||||
const BYTE* const base = ctx->base;
|
||||
const U32 target = (U32)(ip - base);
|
||||
U32 idx = ctx->nextToUpdate;
|
||||
while(idx < target)
|
||||
idx += LZ4HC_BinTree_InsertAndGetAllMatches(ctx, base+idx, iHighLimit, 8, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Tree updater, providing best match */
|
||||
FORCE_INLINE int LZ4HC_BinTree_GetAllMatches (
|
||||
LZ4HC_CCtx_internal* ctx,
|
||||
const BYTE* const ip, const BYTE* const iHighLimit,
|
||||
size_t best_mlen, LZ4HC_match_t* matches, const int fullUpdate)
|
||||
{
|
||||
int mnum = 0;
|
||||
if (ip < ctx->base + ctx->nextToUpdate) return 0; /* skipped area */
|
||||
if (fullUpdate) LZ4HC_updateBinTree(ctx, ip, iHighLimit);
|
||||
best_mlen = LZ4HC_BinTree_InsertAndGetAllMatches(ctx, ip, iHighLimit, best_mlen, matches, &mnum);
|
||||
ctx->nextToUpdate = (U32)(ip - ctx->base + best_mlen);
|
||||
return mnum;
|
||||
}
|
||||
|
||||
|
||||
#define SET_PRICE(pos, mlen, offset, litlen, price) \
|
||||
{ \
|
||||
while (last_pos < pos) { opt[last_pos+1].price = 1<<30; last_pos++; } \
|
||||
opt[pos].mlen = (int)mlen; \
|
||||
opt[pos].off = (int)offset; \
|
||||
opt[pos].litlen = (int)litlen; \
|
||||
opt[pos].price = (int)price; \
|
||||
}
|
||||
|
||||
|
||||
static int LZ4HC_compress_optimal (
|
||||
LZ4HC_CCtx_internal* ctx,
|
||||
const char* const source,
|
||||
char* dest,
|
||||
int inputSize,
|
||||
int maxOutputSize,
|
||||
limitedOutput_directive limit,
|
||||
const size_t sufficient_len,
|
||||
const int fullUpdate
|
||||
)
|
||||
{
|
||||
LZ4HC_optimal_t opt[LZ4_OPT_NUM + 1];
|
||||
LZ4HC_match_t matches[LZ4_OPT_NUM + 1];
|
||||
const BYTE *inr = NULL;
|
||||
size_t res, cur, cur2;
|
||||
size_t i, llen, litlen, mlen, best_mlen, price, offset, best_off, match_num, last_pos;
|
||||
|
||||
const BYTE* ip = (const BYTE*) source;
|
||||
const BYTE* anchor = ip;
|
||||
const BYTE* const iend = ip + inputSize;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = (iend - LASTLITERALS);
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + maxOutputSize;
|
||||
|
||||
/* init */
|
||||
ctx->end += inputSize;
|
||||
ip++;
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit) {
|
||||
memset(opt, 0, sizeof(LZ4HC_optimal_t));
|
||||
last_pos = 0;
|
||||
llen = ip - anchor;
|
||||
match_num = LZ4HC_BinTree_GetAllMatches(ctx, ip, matchlimit, MINMATCH-1, matches, fullUpdate);
|
||||
if (!match_num) { ip++; continue; }
|
||||
|
||||
if ((size_t)matches[match_num-1].len > sufficient_len) {
|
||||
best_mlen = matches[match_num-1].len;
|
||||
best_off = matches[match_num-1].off;
|
||||
cur = 0;
|
||||
last_pos = 1;
|
||||
goto encode;
|
||||
}
|
||||
|
||||
/* set prices using matches at position = 0 */
|
||||
for (i = 0; i < match_num; i++) {
|
||||
mlen = (i>0) ? (size_t)matches[i-1].len+1 : MINMATCH;
|
||||
best_mlen = (matches[i].len < LZ4_OPT_NUM) ? matches[i].len : LZ4_OPT_NUM;
|
||||
while (mlen <= best_mlen) {
|
||||
litlen = 0;
|
||||
price = LZ4HC_sequencePrice(llen + litlen, mlen) - LZ4HC_literalsPrice(llen);
|
||||
SET_PRICE(mlen, mlen, matches[i].off, litlen, price);
|
||||
mlen++;
|
||||
}
|
||||
}
|
||||
|
||||
if (last_pos < MINMATCH) { ip++; continue; }
|
||||
|
||||
/* check further positions */
|
||||
opt[0].mlen = opt[1].mlen = 1;
|
||||
for (cur = 1; cur <= last_pos; cur++) {
|
||||
inr = ip + cur;
|
||||
|
||||
if (opt[cur-1].mlen == 1) {
|
||||
litlen = opt[cur-1].litlen + 1;
|
||||
if (cur != litlen) {
|
||||
price = opt[cur - litlen].price + LZ4HC_literalsPrice(litlen);
|
||||
} else {
|
||||
price = LZ4HC_literalsPrice(llen + litlen) - LZ4HC_literalsPrice(llen);
|
||||
}
|
||||
} else {
|
||||
litlen = 1;
|
||||
price = opt[cur - 1].price + LZ4HC_literalsPrice(litlen);
|
||||
}
|
||||
|
||||
mlen = 1;
|
||||
best_mlen = 0;
|
||||
if (cur > last_pos || price < (size_t)opt[cur].price)
|
||||
SET_PRICE(cur, mlen, best_mlen, litlen, price);
|
||||
|
||||
if (cur == last_pos || inr >= mflimit) break;
|
||||
|
||||
match_num = LZ4HC_BinTree_GetAllMatches(ctx, inr, matchlimit, MINMATCH-1, matches, fullUpdate);
|
||||
if (match_num > 0 && (size_t)matches[match_num-1].len > sufficient_len) {
|
||||
best_mlen = matches[match_num-1].len;
|
||||
best_off = matches[match_num-1].off;
|
||||
last_pos = cur + 1;
|
||||
goto encode;
|
||||
}
|
||||
|
||||
/* set prices using matches at position = cur */
|
||||
for (i = 0; i < match_num; i++) {
|
||||
mlen = (i>0) ? (size_t)matches[i-1].len+1 : MINMATCH;
|
||||
cur2 = cur;
|
||||
best_mlen = (cur2 + matches[i].len < LZ4_OPT_NUM) ? (size_t)matches[i].len : LZ4_OPT_NUM - cur2;
|
||||
|
||||
while (mlen <= best_mlen) {
|
||||
if (opt[cur2].mlen == 1) {
|
||||
litlen = opt[cur2].litlen;
|
||||
|
||||
if (cur2 != litlen)
|
||||
price = opt[cur2 - litlen].price + LZ4HC_sequencePrice(litlen, mlen);
|
||||
else
|
||||
price = LZ4HC_sequencePrice(llen + litlen, mlen) - LZ4HC_literalsPrice(llen);
|
||||
} else {
|
||||
litlen = 0;
|
||||
price = opt[cur2].price + LZ4HC_sequencePrice(litlen, mlen);
|
||||
}
|
||||
|
||||
if (cur2 + mlen > last_pos || price < (size_t)opt[cur2 + mlen].price) { // || (((int)price == opt[cur2 + mlen].price) && (opt[cur2 + mlen-1].mlen == 1))) {
|
||||
SET_PRICE(cur2 + mlen, mlen, matches[i].off, litlen, price);
|
||||
}
|
||||
mlen++;
|
||||
}
|
||||
}
|
||||
} /* for (cur = 1; cur <= last_pos; cur++) */
|
||||
|
||||
best_mlen = opt[last_pos].mlen;
|
||||
best_off = opt[last_pos].off;
|
||||
cur = last_pos - best_mlen;
|
||||
|
||||
encode: /* cur, last_pos, best_mlen, best_off have to be set */
|
||||
opt[0].mlen = 1;
|
||||
while (1) {
|
||||
mlen = opt[cur].mlen;
|
||||
offset = opt[cur].off;
|
||||
opt[cur].mlen = (int)best_mlen;
|
||||
opt[cur].off = (int)best_off;
|
||||
best_mlen = mlen;
|
||||
best_off = offset;
|
||||
if (mlen > cur) break;
|
||||
cur -= mlen;
|
||||
}
|
||||
|
||||
cur = 0;
|
||||
while (cur < last_pos) {
|
||||
mlen = opt[cur].mlen;
|
||||
if (mlen == 1) { ip++; cur++; continue; }
|
||||
offset = opt[cur].off;
|
||||
cur += mlen;
|
||||
|
||||
res = LZ4HC_encodeSequence(&ip, &op, &anchor, (int)mlen, ip - offset, limit, oend);
|
||||
if (res) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode Last Literals */
|
||||
{ int lastRun = (int)(iend - anchor);
|
||||
if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */
|
||||
if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
|
||||
else *op++ = (BYTE)(lastRun<<ML_BITS);
|
||||
memcpy(op, anchor, iend - anchor);
|
||||
op += iend-anchor;
|
||||
}
|
||||
|
||||
/* End */
|
||||
return (int) ((char*)op-dest);
|
||||
}
|
||||
889
Kinc/Sources/kinc/io/lz4/xxhash.c
Normal file
889
Kinc/Sources/kinc/io/lz4/xxhash.c
Normal file
@ -0,0 +1,889 @@
|
||||
/*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (C) 2012-2016, Yann Collet
|
||||
*
|
||||
* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: http://www.xxhash.com
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Tuning parameters
|
||||
***************************************/
|
||||
/*!XXH_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
|
||||
* It can generate buggy code on targets which do not support unaligned memory accesses.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://stackoverflow.com/a/32095106/646947 for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
|
||||
# define XXH_FORCE_MEMORY_ACCESS 2
|
||||
# elif defined(__INTEL_COMPILER) || \
|
||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
|
||||
# define XXH_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*!XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
* If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
* When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
* By default, this option is disabled. To enable it, uncomment below define :
|
||||
*/
|
||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||
|
||||
/*!XXH_FORCE_NATIVE_FORMAT :
|
||||
* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
|
||||
* Results are therefore identical for little-endian and big-endian CPU.
|
||||
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
* Should endian-independence be of no importance for your application, you may set the #define below to 1,
|
||||
* to improve speed for Big-endian CPU.
|
||||
* This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */
|
||||
# define XXH_FORCE_NATIVE_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*!XXH_FORCE_ALIGN_CHECK :
|
||||
* This is a minor performance trick, only useful with lots of very small keys.
|
||||
* It means : check for aligned/unaligned input.
|
||||
* The check costs one initial branch per hash; set to 0 when the input data
|
||||
* is guaranteed to be aligned.
|
||||
*/
|
||||
#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
|
||||
# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_FORCE_ALIGN_CHECK 0
|
||||
# else
|
||||
# define XXH_FORCE_ALIGN_CHECK 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Includes & Memory related functions
|
||||
***************************************/
|
||||
/*! Modify the local functions below should you wish to use some other memory routines
|
||||
* for malloc(), free() */
|
||||
#include <stdlib.h>
|
||||
static void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
static void XXH_free (void* p) { free(p); }
|
||||
/*! and for memcpy() */
|
||||
#include <string.h>
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
#include "xxhash.h"
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Compiler Specific Options
|
||||
***************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Basic Types
|
||||
***************************************/
|
||||
#ifndef MEM_MODULE
|
||||
# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
# else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
|
||||
|
||||
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
|
||||
static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
|
||||
#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U32 u32; } __attribute__((packed)) unalign;
|
||||
static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
|
||||
#else
|
||||
|
||||
/* portable and safe solution. Generally efficient.
|
||||
* see : http://stackoverflow.com/a/32095106/646947
|
||||
*/
|
||||
static U32 XXH_read32(const void* memPtr)
|
||||
{
|
||||
U32 val;
|
||||
memcpy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* Compiler-specific Functions and Macros
|
||||
******************************************/
|
||||
#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
#elif XXH_GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
#else
|
||||
static U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Architecture Macros
|
||||
***************************************/
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
|
||||
/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN
|
||||
static const int g_one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one))
|
||||
#endif
|
||||
|
||||
|
||||
/* ***************************
|
||||
* Memory reads
|
||||
*****************************/
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
static U32 XXH_readBE32(const void* ptr)
|
||||
{
|
||||
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
|
||||
}
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Macros
|
||||
***************************************/
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
|
||||
|
||||
|
||||
/* *******************************************************************
|
||||
* 32-bits hash functions
|
||||
*********************************************************************/
|
||||
static const U32 PRIME32_1 = 2654435761U;
|
||||
static const U32 PRIME32_2 = 2246822519U;
|
||||
static const U32 PRIME32_3 = 3266489917U;
|
||||
static const U32 PRIME32_4 = 668265263U;
|
||||
static const U32 PRIME32_5 = 374761393U;
|
||||
|
||||
static U32 XXH32_round(U32 seed, U32 input)
|
||||
{
|
||||
seed += input * PRIME32_2;
|
||||
seed = XXH_rotl32(seed, 13);
|
||||
seed *= PRIME32_1;
|
||||
return seed;
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) {
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16) {
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do {
|
||||
v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
|
||||
v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
|
||||
v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
|
||||
v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
} else {
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p+4<=bEnd) {
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH32_state_t state;
|
||||
XXH32_reset(&state, seed);
|
||||
XXH32_update(&state, input, len);
|
||||
return XXH32_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if (XXH_FORCE_ALIGN_CHECK) {
|
||||
if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
} }
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*====== Hash streaming ======*/
|
||||
|
||||
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
|
||||
{
|
||||
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
|
||||
}
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
|
||||
{
|
||||
memcpy(dstState, srcState, sizeof(*dstState));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
|
||||
{
|
||||
XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
|
||||
memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */
|
||||
state.v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state.v2 = seed + PRIME32_2;
|
||||
state.v3 = seed + 0;
|
||||
state.v4 = seed - PRIME32_1;
|
||||
memcpy(statePtr, &state, sizeof(state));
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len_32 += (unsigned)len;
|
||||
state->large_len |= (len>=16) | (state->total_len_32>=16);
|
||||
|
||||
if (state->memsize + len < 16) { /* fill in tmp buffer */
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (unsigned)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) { /* some data left from previous update */
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{ const U32* p32 = state->mem32;
|
||||
state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
|
||||
state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16) {
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do {
|
||||
v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
|
||||
v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
|
||||
v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
|
||||
v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
|
||||
} while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd) {
|
||||
XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
|
||||
state->memsize = (unsigned)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->large_len) {
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
} else {
|
||||
h32 = state->v3 /* == seed */ + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += state->total_len_32;
|
||||
|
||||
while (p+4<=bEnd) {
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
/*====== Canonical representation ======*/
|
||||
|
||||
/*! Default XXH result types are basic unsigned 32 and 64 bits.
|
||||
* The canonical representation follows human-readable write convention, aka big-endian (large digits first).
|
||||
* These functions allow transformation of hash result into and from its canonical format.
|
||||
* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.
|
||||
*/
|
||||
|
||||
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
|
||||
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
|
||||
memcpy(dst, &hash, sizeof(*dst));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
|
||||
{
|
||||
return XXH_readBE32(src);
|
||||
}
|
||||
|
||||
|
||||
#ifndef XXH_NO_LONG_LONG
|
||||
|
||||
/* *******************************************************************
|
||||
* 64-bits hash functions
|
||||
*********************************************************************/
|
||||
|
||||
/*====== Memory access ======*/
|
||||
|
||||
#ifndef MEM_MODULE
|
||||
# define MEM_MODULE
|
||||
# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
|
||||
# include <stdint.h>
|
||||
typedef uint64_t U64;
|
||||
# else
|
||||
typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
|
||||
|
||||
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
|
||||
static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64;
|
||||
static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; }
|
||||
|
||||
#else
|
||||
|
||||
/* portable and safe solution. Generally efficient.
|
||||
* see : http://stackoverflow.com/a/32095106/646947
|
||||
*/
|
||||
|
||||
static U64 XXH_read64(const void* memPtr)
|
||||
{
|
||||
U64 val;
|
||||
memcpy(&val, memPtr, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif XXH_GCC_VERSION >= 403
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
static U64 XXH_readBE64(const void* ptr)
|
||||
{
|
||||
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*====== xxh64 ======*/
|
||||
|
||||
static const U64 PRIME64_1 = 11400714785074694791ULL;
|
||||
static const U64 PRIME64_2 = 14029467366897019727ULL;
|
||||
static const U64 PRIME64_3 = 1609587929392839161ULL;
|
||||
static const U64 PRIME64_4 = 9650029242287828579ULL;
|
||||
static const U64 PRIME64_5 = 2870177450012600261ULL;
|
||||
|
||||
static U64 XXH64_round(U64 acc, U64 input)
|
||||
{
|
||||
acc += input * PRIME64_2;
|
||||
acc = XXH_rotl64(acc, 31);
|
||||
acc *= PRIME64_1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
static U64 XXH64_mergeRound(U64 acc, U64 val)
|
||||
{
|
||||
val = XXH64_round(0, val);
|
||||
acc ^= val;
|
||||
acc = acc * PRIME64_1 + PRIME64_4;
|
||||
return acc;
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL) {
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=32) {
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do {
|
||||
v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
|
||||
v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
|
||||
v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
|
||||
v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
|
||||
} while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
h64 = XXH64_mergeRound(h64, v1);
|
||||
h64 = XXH64_mergeRound(h64, v2);
|
||||
h64 = XXH64_mergeRound(h64, v3);
|
||||
h64 = XXH64_mergeRound(h64, v4);
|
||||
|
||||
} else {
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd) {
|
||||
U64 const k1 = XXH64_round(0, XXH_get64bits(p));
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd) {
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XXH64_state_t state;
|
||||
XXH64_reset(&state, seed);
|
||||
XXH64_update(&state, input, len);
|
||||
return XXH64_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if (XXH_FORCE_ALIGN_CHECK) {
|
||||
if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
} }
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*====== Hash Streaming ======*/
|
||||
|
||||
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
|
||||
{
|
||||
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
|
||||
}
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState)
|
||||
{
|
||||
memcpy(dstState, srcState, sizeof(*dstState));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
|
||||
{
|
||||
XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
|
||||
memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */
|
||||
state.v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state.v2 = seed + PRIME64_2;
|
||||
state.v3 = seed + 0;
|
||||
state.v4 = seed - PRIME64_1;
|
||||
memcpy(statePtr, &state, sizeof(state));
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) { /* fill in tmp buffer */
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) { /* tmp buffer is full */
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
|
||||
state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
|
||||
state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
|
||||
state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd) {
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do {
|
||||
v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
|
||||
v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
|
||||
v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
|
||||
v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
|
||||
} while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd) {
|
||||
XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
|
||||
state->memsize = (unsigned)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32) {
|
||||
U64 const v1 = state->v1;
|
||||
U64 const v2 = state->v2;
|
||||
U64 const v3 = state->v3;
|
||||
U64 const v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
h64 = XXH64_mergeRound(h64, v1);
|
||||
h64 = XXH64_mergeRound(h64, v2);
|
||||
h64 = XXH64_mergeRound(h64, v3);
|
||||
h64 = XXH64_mergeRound(h64, v4);
|
||||
} else {
|
||||
h64 = state->v3 + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd) {
|
||||
U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd) {
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd) {
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
/*====== Canonical representation ======*/
|
||||
|
||||
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
|
||||
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
|
||||
memcpy(dst, &hash, sizeof(*dst));
|
||||
}
|
||||
|
||||
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
|
||||
{
|
||||
return XXH_readBE64(src);
|
||||
}
|
||||
|
||||
#endif /* XXH_NO_LONG_LONG */
|
||||
293
Kinc/Sources/kinc/io/lz4/xxhash.h
Normal file
293
Kinc/Sources/kinc/io/lz4/xxhash.h
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
/* Notice extracted from xxHash homepage :
|
||||
|
||||
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
|
||||
It also successfully passes all tests from the SMHasher suite.
|
||||
|
||||
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
|
||||
|
||||
Name Speed Q.Score Author
|
||||
xxHash 5.4 GB/s 10
|
||||
CrapWow 3.2 GB/s 2 Andrew
|
||||
MumurHash 3a 2.7 GB/s 10 Austin Appleby
|
||||
SpookyHash 2.0 GB/s 10 Bob Jenkins
|
||||
SBox 1.4 GB/s 9 Bret Mulvey
|
||||
Lookup3 1.2 GB/s 9 Bob Jenkins
|
||||
SuperFastHash 1.2 GB/s 1 Paul Hsieh
|
||||
CityHash64 1.05 GB/s 10 Pike & Alakuijala
|
||||
FNV 0.55 GB/s 5 Fowler, Noll, Vo
|
||||
CRC32 0.43 GB/s 9
|
||||
MD5-32 0.33 GB/s 10 Ronald L. Rivest
|
||||
SHA1-32 0.28 GB/s 10
|
||||
|
||||
Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
|
||||
A 64-bits version, named XXH64, is available since r35.
|
||||
It offers much better speed, but for 64-bits applications only.
|
||||
Name Speed on 64 bits Speed on 32 bits
|
||||
XXH64 13.8 GB/s 1.9 GB/s
|
||||
XXH32 6.8 GB/s 6.0 GB/s
|
||||
*/
|
||||
|
||||
#ifndef XXHASH_H_5627135585666179
|
||||
#define XXHASH_H_5627135585666179 1
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ****************************
|
||||
* Definitions
|
||||
******************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
/* ****************************
|
||||
* API modifier
|
||||
******************************/
|
||||
/** XXH_PRIVATE_API
|
||||
* This is useful to include xxhash functions in `static` mode
|
||||
* in order to inline them, and remove their symbol from the public list.
|
||||
* Methodology :
|
||||
* #define XXH_PRIVATE_API
|
||||
* #include "xxhash.h"
|
||||
* `xxhash.c` is automatically included.
|
||||
* It's not useful to compile and link it as a separate module.
|
||||
*/
|
||||
#ifdef XXH_PRIVATE_API
|
||||
# ifndef XXH_STATIC_LINKING_ONLY
|
||||
# define XXH_STATIC_LINKING_ONLY
|
||||
# endif
|
||||
# if defined(__GNUC__)
|
||||
# define XXH_PUBLIC_API static __inline __attribute__((unused))
|
||||
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
# define XXH_PUBLIC_API static inline
|
||||
# elif defined(_MSC_VER)
|
||||
# define XXH_PUBLIC_API static __inline
|
||||
# else
|
||||
# define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
||||
# endif
|
||||
#else
|
||||
# define XXH_PUBLIC_API /* do nothing */
|
||||
#endif /* XXH_PRIVATE_API */
|
||||
|
||||
/*!XXH_NAMESPACE, aka Namespace Emulation :
|
||||
|
||||
If you want to include _and expose_ xxHash functions from within your own library,
|
||||
but also want to avoid symbol collisions with other libraries which may also include xxHash,
|
||||
|
||||
you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
|
||||
with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
|
||||
|
||||
Note that no change is required within the calling program as long as it includes `xxhash.h` :
|
||||
regular symbol name will be automatically translated by this header.
|
||||
*/
|
||||
#ifdef XXH_NAMESPACE
|
||||
# define XXH_CAT(A,B) A##B
|
||||
# define XXH_NAME2(A,B) XXH_CAT(A,B)
|
||||
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
|
||||
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
|
||||
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
|
||||
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
|
||||
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
|
||||
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
|
||||
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
|
||||
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
|
||||
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
|
||||
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
|
||||
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
|
||||
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
|
||||
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
|
||||
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
|
||||
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
|
||||
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
|
||||
# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
|
||||
# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
|
||||
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
|
||||
#endif
|
||||
|
||||
|
||||
/* *************************************
|
||||
* Version
|
||||
***************************************/
|
||||
#define XXH_VERSION_MAJOR 0
|
||||
#define XXH_VERSION_MINOR 6
|
||||
#define XXH_VERSION_RELEASE 2
|
||||
#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
|
||||
XXH_PUBLIC_API unsigned XXH_versionNumber (void);
|
||||
|
||||
|
||||
/*-**********************************************************************
|
||||
* 32-bits hash
|
||||
************************************************************************/
|
||||
typedef unsigned int XXH32_hash_t;
|
||||
|
||||
/*! XXH32() :
|
||||
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
||||
The memory between input & input+length must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */
|
||||
XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
|
||||
|
||||
/*====== Streaming ======*/
|
||||
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
|
||||
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
|
||||
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
|
||||
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
|
||||
XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions generate the xxHash of an input provided in multiple segments.
|
||||
Note that, for small input, they are slower than single-call functions, due to state management.
|
||||
For small input, prefer `XXH32()` and `XXH64()` .
|
||||
|
||||
XXH state must first be allocated, using XXH*_createState() .
|
||||
|
||||
Start a new hash by initializing state with a seed, using XXH*_reset().
|
||||
|
||||
Then, feed the hash state by calling XXH*_update() as many times as necessary.
|
||||
Obviously, input must be allocated and read accessible.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
|
||||
Finally, a hash value can be produced anytime, by using XXH*_digest().
|
||||
This function returns the nn-bits hash as an int or long long.
|
||||
|
||||
It's still possible to continue inserting input into the hash state after a digest,
|
||||
and generate some new hashes later on, by calling again XXH*_digest().
|
||||
|
||||
When done, free XXH state space if it was allocated dynamically.
|
||||
*/
|
||||
|
||||
/*====== Canonical representation ======*/
|
||||
|
||||
typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
|
||||
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
|
||||
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
|
||||
|
||||
/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
|
||||
* The canonical representation uses human-readable write convention, aka big-endian (large digits first).
|
||||
* These functions allow transformation of hash result into and from its canonical format.
|
||||
* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef XXH_NO_LONG_LONG
|
||||
/*-**********************************************************************
|
||||
* 64-bits hash
|
||||
************************************************************************/
|
||||
typedef unsigned long long XXH64_hash_t;
|
||||
|
||||
/*! XXH64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function runs faster on 64-bits systems, but slower on 32-bits systems (see benchmark).
|
||||
*/
|
||||
XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
|
||||
|
||||
/*====== Streaming ======*/
|
||||
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
|
||||
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
|
||||
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state);
|
||||
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
|
||||
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
|
||||
XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
|
||||
|
||||
/*====== Canonical representation ======*/
|
||||
typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
|
||||
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
|
||||
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
|
||||
#endif /* XXH_NO_LONG_LONG */
|
||||
|
||||
|
||||
#ifdef XXH_STATIC_LINKING_ONLY
|
||||
|
||||
/* ================================================================================================
|
||||
This section contains definitions which are not guaranteed to remain stable.
|
||||
They may change in future versions, becoming incompatible with a different version of the library.
|
||||
They shall only be used with static linking.
|
||||
Never use these definitions in association with dynamic linking !
|
||||
=================================================================================================== */
|
||||
|
||||
/* These definitions are only meant to allow allocation of XXH state
|
||||
statically, on stack, or in a struct for example.
|
||||
Do not use members directly. */
|
||||
|
||||
struct XXH32_state_s {
|
||||
unsigned total_len_32;
|
||||
unsigned large_len;
|
||||
unsigned v1;
|
||||
unsigned v2;
|
||||
unsigned v3;
|
||||
unsigned v4;
|
||||
unsigned mem32[4]; /* buffer defined as U32 for alignment */
|
||||
unsigned memsize;
|
||||
unsigned reserved; /* never read nor write, will be removed in a future version */
|
||||
}; /* typedef'd to XXH32_state_t */
|
||||
|
||||
#ifndef XXH_NO_LONG_LONG
|
||||
struct XXH64_state_s {
|
||||
unsigned long long total_len;
|
||||
unsigned long long v1;
|
||||
unsigned long long v2;
|
||||
unsigned long long v3;
|
||||
unsigned long long v4;
|
||||
unsigned long long mem64[4]; /* buffer defined as U64 for alignment */
|
||||
unsigned memsize;
|
||||
unsigned reserved[2]; /* never read nor write, will be removed in a future version */
|
||||
}; /* typedef'd to XXH64_state_t */
|
||||
#endif
|
||||
|
||||
# ifdef XXH_PRIVATE_API
|
||||
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
|
||||
# endif
|
||||
|
||||
#endif /* XXH_STATIC_LINKING_ONLY */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XXHASH_H_5627135585666179 */
|
||||
2
Kinc/Sources/kinc/libs/.clang-format
Normal file
2
Kinc/Sources/kinc/libs/.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
||||
704
Kinc/Sources/kinc/libs/lz4x.h
Normal file
704
Kinc/Sources/kinc/libs/lz4x.h
Normal file
@ -0,0 +1,704 @@
|
||||
/*
|
||||
|
||||
LZ4X - An optimized LZ4 compressor
|
||||
|
||||
Written and placed in the public domain by Ilya Muravyov
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#define _CRT_DISABLE_PERFCRIT_LOCKS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define NO_UTIME
|
||||
|
||||
#ifndef NO_UTIME
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# include <sys/utime.h>
|
||||
# else
|
||||
# include <utime.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define _ftelli64 ftello64
|
||||
#endif
|
||||
|
||||
typedef unsigned char U8;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
|
||||
//FILE* g_in;
|
||||
//FILE* g_out;
|
||||
|
||||
#define LZ4_MAGIC 0x184C2102
|
||||
#define BLOCK_SIZE (8<<20) // 8 MB
|
||||
#define PADDING_LITERALS 5
|
||||
|
||||
#define WINDOW_BITS 16
|
||||
#define WINDOW_SIZE (1<<WINDOW_BITS)
|
||||
#define WINDOW_MASK (WINDOW_SIZE-1)
|
||||
|
||||
#define MIN_MATCH 4
|
||||
|
||||
#define EXCESS (16+(BLOCK_SIZE/255))
|
||||
|
||||
static U8 g_buf[BLOCK_SIZE+BLOCK_SIZE+EXCESS];
|
||||
|
||||
#define MIN(a, b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a, b) (((a)>(b))?(a):(b))
|
||||
|
||||
#define LOAD_16(p) (*(const U16*)(&g_buf[p]))
|
||||
#define LOAD_32(p) (*(const U32*)(&g_buf[p]))
|
||||
#define STORE_16(p, x) (*(U16*)(&g_buf[p])=(x))
|
||||
#define COPY_32(d, s) (*(U32*)(&g_buf[d])=LOAD_32(s))
|
||||
|
||||
#define HASH_BITS 18
|
||||
#define HASH_SIZE (1<<HASH_BITS)
|
||||
#define NIL (-1)
|
||||
|
||||
#define HASH_32(p) ((LOAD_32(p)*0x9E3779B9)>>(32-HASH_BITS))
|
||||
|
||||
static inline void wild_copy(int d, int s, int n)
|
||||
{
|
||||
COPY_32(d, s);
|
||||
COPY_32(d+4, s+4);
|
||||
|
||||
for (int i=8; i<n; i+=8)
|
||||
{
|
||||
COPY_32(d+i, s+i);
|
||||
COPY_32(d+4+i, s+4+i);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void compress(const int max_chain)
|
||||
{
|
||||
static int head[HASH_SIZE];
|
||||
static int tail[WINDOW_SIZE];
|
||||
|
||||
int n;
|
||||
while ((n=fread(g_buf, 1, BLOCK_SIZE, g_in))>0)
|
||||
{
|
||||
for (int i=0; i<HASH_SIZE; ++i)
|
||||
head[i]=NIL;
|
||||
|
||||
int op=BLOCK_SIZE;
|
||||
int pp=0;
|
||||
|
||||
int p=0;
|
||||
while (p<n)
|
||||
{
|
||||
int best_len=0;
|
||||
int dist=0;
|
||||
|
||||
const int max_match=(n-PADDING_LITERALS)-p;
|
||||
if (max_match>=MAX(12-PADDING_LITERALS, MIN_MATCH))
|
||||
{
|
||||
const int limit=MAX(p-WINDOW_SIZE, NIL);
|
||||
int chain_len=max_chain;
|
||||
|
||||
int s=head[HASH_32(p)];
|
||||
while (s>limit)
|
||||
{
|
||||
if (g_buf[s+best_len]==g_buf[p+best_len] && LOAD_32(s)==LOAD_32(p))
|
||||
{
|
||||
int len=MIN_MATCH;
|
||||
while (len<max_match && g_buf[s+len]==g_buf[p+len])
|
||||
++len;
|
||||
|
||||
if (len>best_len)
|
||||
{
|
||||
best_len=len;
|
||||
dist=p-s;
|
||||
|
||||
if (len==max_match)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (--chain_len==0)
|
||||
break;
|
||||
|
||||
s=tail[s&WINDOW_MASK];
|
||||
}
|
||||
}
|
||||
|
||||
if (best_len>=MIN_MATCH)
|
||||
{
|
||||
int len=best_len-MIN_MATCH;
|
||||
const int nib=MIN(len, 15);
|
||||
|
||||
if (pp!=p)
|
||||
{
|
||||
const int run=p-pp;
|
||||
if (run>=15)
|
||||
{
|
||||
g_buf[op++]=(15<<4)+nib;
|
||||
|
||||
int j=run-15;
|
||||
for (; j>=255; j-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=j;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=(run<<4)+nib;
|
||||
|
||||
wild_copy(op, pp, run);
|
||||
op+=run;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=nib;
|
||||
|
||||
STORE_16(op, dist);
|
||||
op+=2;
|
||||
|
||||
if (len>=15)
|
||||
{
|
||||
len-=15;
|
||||
for (; len>=255; len-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=len;
|
||||
}
|
||||
|
||||
pp=p+best_len;
|
||||
|
||||
while (p<pp)
|
||||
{
|
||||
const U32 h=HASH_32(p);
|
||||
tail[p&WINDOW_MASK]=head[h];
|
||||
head[h]=p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const U32 h=HASH_32(p);
|
||||
tail[p&WINDOW_MASK]=head[h];
|
||||
head[h]=p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pp!=p)
|
||||
{
|
||||
const int run=p-pp;
|
||||
if (run>=15)
|
||||
{
|
||||
g_buf[op++]=15<<4;
|
||||
|
||||
int j=run-15;
|
||||
for (; j>=255; j-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=j;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=run<<4;
|
||||
|
||||
wild_copy(op, pp, run);
|
||||
op+=run;
|
||||
}
|
||||
|
||||
const int comp_len=op-BLOCK_SIZE;
|
||||
fwrite(&comp_len, 1, sizeof(comp_len), g_out);
|
||||
fwrite(&g_buf[BLOCK_SIZE], 1, comp_len, g_out);
|
||||
|
||||
fprintf(stderr, "%lld -> %lld\r", _ftelli64(g_in), _ftelli64(g_out));
|
||||
}
|
||||
}
|
||||
|
||||
void compress_optimal()
|
||||
{
|
||||
static int head[HASH_SIZE];
|
||||
static int nodes[WINDOW_SIZE][2];
|
||||
static struct
|
||||
{
|
||||
int cum;
|
||||
|
||||
int len;
|
||||
int dist;
|
||||
} path[BLOCK_SIZE+1];
|
||||
|
||||
int n;
|
||||
while ((n=fread(g_buf, 1, BLOCK_SIZE, g_in))>0)
|
||||
{
|
||||
// Pass 1: Find all matches
|
||||
|
||||
for (int i=0; i<HASH_SIZE; ++i)
|
||||
head[i]=NIL;
|
||||
|
||||
for (int p=0; p<n; ++p)
|
||||
{
|
||||
int best_len=0;
|
||||
int dist=0;
|
||||
|
||||
const int max_match=(n-PADDING_LITERALS)-p;
|
||||
if (max_match>=MAX(12-PADDING_LITERALS, MIN_MATCH))
|
||||
{
|
||||
const int limit=MAX(p-WINDOW_SIZE, NIL);
|
||||
|
||||
int* left=&nodes[p&WINDOW_MASK][1];
|
||||
int* right=&nodes[p&WINDOW_MASK][0];
|
||||
|
||||
int left_len=0;
|
||||
int right_len=0;
|
||||
|
||||
const U32 h=HASH_32(p);
|
||||
int s=head[h];
|
||||
head[h]=p;
|
||||
|
||||
while (s>limit)
|
||||
{
|
||||
int len=MIN(left_len, right_len);
|
||||
|
||||
if (g_buf[s+len]==g_buf[p+len])
|
||||
{
|
||||
while (++len<max_match && g_buf[s+len]==g_buf[p+len]);
|
||||
|
||||
if (len>best_len)
|
||||
{
|
||||
best_len=len;
|
||||
dist=p-s;
|
||||
|
||||
if (len==max_match || len>=(1<<16))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_buf[s+len]<g_buf[p+len])
|
||||
{
|
||||
*right=s;
|
||||
right=&nodes[s&WINDOW_MASK][1];
|
||||
s=*right;
|
||||
right_len=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*left=s;
|
||||
left=&nodes[s&WINDOW_MASK][0];
|
||||
s=*left;
|
||||
left_len=len;
|
||||
}
|
||||
}
|
||||
|
||||
*left=NIL;
|
||||
*right=NIL;
|
||||
}
|
||||
|
||||
path[p].len=best_len;
|
||||
path[p].dist=dist;
|
||||
}
|
||||
|
||||
// Pass 2: Build the shortest path
|
||||
|
||||
path[n].cum=0;
|
||||
|
||||
int count=15;
|
||||
|
||||
for (int p=n-1; p>0; --p)
|
||||
{
|
||||
int c0=path[p+1].cum+1;
|
||||
|
||||
if (--count==0)
|
||||
{
|
||||
count=255;
|
||||
++c0;
|
||||
}
|
||||
|
||||
int len=path[p].len;
|
||||
if (len>=MIN_MATCH)
|
||||
{
|
||||
int c1=1<<30;
|
||||
|
||||
const int j=MAX(len-255, MIN_MATCH);
|
||||
for (int i=len; i>=j; --i)
|
||||
{
|
||||
int tmp=path[p+i].cum+3;
|
||||
|
||||
if (i>=(15+MIN_MATCH))
|
||||
tmp+=1+((i-(15+MIN_MATCH))/255);
|
||||
|
||||
if (tmp<c1)
|
||||
{
|
||||
c1=tmp;
|
||||
len=i;
|
||||
}
|
||||
}
|
||||
|
||||
if (c1<=c0)
|
||||
{
|
||||
path[p].cum=c1;
|
||||
path[p].len=len;
|
||||
|
||||
count=15;
|
||||
}
|
||||
else
|
||||
{
|
||||
path[p].cum=c0;
|
||||
path[p].len=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
path[p].cum=c0;
|
||||
}
|
||||
|
||||
// Pass 3: Output the codes
|
||||
|
||||
int op=BLOCK_SIZE;
|
||||
int pp=0;
|
||||
|
||||
int p=0;
|
||||
while (p<n)
|
||||
{
|
||||
if (path[p].len>=MIN_MATCH)
|
||||
{
|
||||
int len=path[p].len-MIN_MATCH;
|
||||
const int nib=MIN(len, 15);
|
||||
|
||||
if (pp!=p)
|
||||
{
|
||||
const int run=p-pp;
|
||||
if (run>=15)
|
||||
{
|
||||
g_buf[op++]=(15<<4)+nib;
|
||||
|
||||
int j=run-15;
|
||||
for (; j>=255; j-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=j;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=(run<<4)+nib;
|
||||
|
||||
wild_copy(op, pp, run);
|
||||
op+=run;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=nib;
|
||||
|
||||
STORE_16(op, path[p].dist);
|
||||
op+=2;
|
||||
|
||||
if (len>=15)
|
||||
{
|
||||
len-=15;
|
||||
for (; len>=255; len-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=len;
|
||||
}
|
||||
|
||||
p+=path[p].len;
|
||||
|
||||
pp=p;
|
||||
}
|
||||
else
|
||||
++p;
|
||||
}
|
||||
|
||||
if (pp!=p)
|
||||
{
|
||||
const int run=p-pp;
|
||||
if (run>=15)
|
||||
{
|
||||
g_buf[op++]=15<<4;
|
||||
|
||||
int j=run-15;
|
||||
for (; j>=255; j-=255)
|
||||
g_buf[op++]=255;
|
||||
g_buf[op++]=j;
|
||||
}
|
||||
else
|
||||
g_buf[op++]=run<<4;
|
||||
|
||||
wild_copy(op, pp, run);
|
||||
op+=run;
|
||||
}
|
||||
|
||||
const int comp_len=op-BLOCK_SIZE;
|
||||
fwrite(&comp_len, 1, sizeof(comp_len), g_out);
|
||||
fwrite(&g_buf[BLOCK_SIZE], 1, comp_len, g_out);
|
||||
|
||||
fprintf(stderr, "%lld -> %lld\r", _ftelli64(g_in), _ftelli64(g_out));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t kread(void* dst, size_t size, const char* src, size_t* offset, size_t compressedSize) {
|
||||
size_t realSize = MIN(size, compressedSize - *offset);
|
||||
memcpy(dst, &src[*offset], realSize);
|
||||
*offset += realSize;
|
||||
return realSize;
|
||||
}
|
||||
|
||||
static size_t kwrite(void* src, size_t size, char* dst, size_t* offset, int maxOutputSize) {
|
||||
size_t realSize = MIN(size, maxOutputSize - *offset);
|
||||
memcpy(&dst[*offset], src, size);
|
||||
*offset += realSize;
|
||||
return realSize;
|
||||
}
|
||||
|
||||
//int decompress()
|
||||
#ifdef KORE_LZ4X
|
||||
int LZ4_decompress_safe(const char *source, char *buf, int compressedSize, int maxOutputSize)
|
||||
{
|
||||
size_t read_offset = 0;
|
||||
size_t write_offset = 0;
|
||||
int comp_len;
|
||||
while (kread(&comp_len, sizeof(comp_len), source, &read_offset, compressedSize)>0)
|
||||
{
|
||||
if (comp_len<2 || comp_len>(BLOCK_SIZE+EXCESS)
|
||||
|| kread(&g_buf[BLOCK_SIZE], comp_len, source, &read_offset, compressedSize)!=comp_len)
|
||||
return -1;
|
||||
|
||||
int p=0;
|
||||
|
||||
int ip=BLOCK_SIZE;
|
||||
const int ip_end=ip+comp_len;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const int token=g_buf[ip++];
|
||||
if (token>=16)
|
||||
{
|
||||
int run=token>>4;
|
||||
if (run==15)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const int c=g_buf[ip++];
|
||||
run+=c;
|
||||
if (c!=255)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((p+run)>BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
wild_copy(p, ip, run);
|
||||
p+=run;
|
||||
ip+=run;
|
||||
if (ip>=ip_end)
|
||||
break;
|
||||
}
|
||||
|
||||
int s=p-LOAD_16(ip);
|
||||
ip+=2;
|
||||
if (s<0)
|
||||
return -1;
|
||||
|
||||
int len=(token&15)+MIN_MATCH;
|
||||
if (len==(15+MIN_MATCH))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const int c=g_buf[ip++];
|
||||
len+=c;
|
||||
if (c!=255)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((p+len)>BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
if ((p-s)>=4)
|
||||
{
|
||||
wild_copy(p, s, len);
|
||||
p+=len;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--!=0)
|
||||
g_buf[p++]=g_buf[s++];
|
||||
}
|
||||
}
|
||||
|
||||
if (kwrite(g_buf, p, buf, &write_offset, maxOutputSize)!=p)
|
||||
{
|
||||
kinc_error_message("Fwrite() failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const clock_t start=clock();
|
||||
|
||||
int level=4;
|
||||
bool do_decomp=false;
|
||||
bool overwrite=false;
|
||||
|
||||
while (argc>1 && *argv[1]=='-')
|
||||
{
|
||||
for (int i=1; argv[1][i]!='\0'; ++i)
|
||||
{
|
||||
switch (argv[1][i])
|
||||
{
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
level=argv[1][i]-'0';
|
||||
break;
|
||||
case 'd':
|
||||
do_decomp=true;
|
||||
break;
|
||||
case 'f':
|
||||
overwrite=true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option: -%c\n", argv[1][i]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (argc<2)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"LZ4X - An optimized LZ4 compressor, v1.60\n"
|
||||
"Written and placed in the public domain by Ilya Muravyov\n"
|
||||
"\n"
|
||||
"Usage: LZ4X [options] infile [outfile]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -1 Compress faster\n"
|
||||
" -9 Compress better\n"
|
||||
" -d Decompress\n"
|
||||
" -f Force overwrite of output file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_in=fopen(argv[1], "rb");
|
||||
if (!g_in)
|
||||
{
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char out_name[FILENAME_MAX];
|
||||
if (argc<3)
|
||||
{
|
||||
strcpy(out_name, argv[1]);
|
||||
if (do_decomp)
|
||||
{
|
||||
const int p=strlen(out_name)-4;
|
||||
if (p>0 && strcmp(&out_name[p], ".lz4")==0)
|
||||
out_name[p]='\0';
|
||||
else
|
||||
strcat(out_name, ".out");
|
||||
}
|
||||
else
|
||||
strcat(out_name, ".lz4");
|
||||
}
|
||||
else
|
||||
strcpy(out_name, argv[2]);
|
||||
|
||||
if (!overwrite)
|
||||
{
|
||||
FILE* f=fopen(out_name, "rb");
|
||||
if (f)
|
||||
{
|
||||
fclose(f);
|
||||
|
||||
fprintf(stderr, "%s already exists. Overwrite (y/n)? ", out_name);
|
||||
fflush(stderr);
|
||||
|
||||
if (getchar()!='y')
|
||||
{
|
||||
fprintf(stderr, "Not overwritten\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_decomp)
|
||||
{
|
||||
int magic;
|
||||
fread(&magic, 1, sizeof(magic), g_in);
|
||||
if (magic!=LZ4_MAGIC)
|
||||
{
|
||||
fprintf(stderr, "%s: Not in Legacy format\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_out=fopen(out_name, "wb");
|
||||
if (!g_out)
|
||||
{
|
||||
perror(out_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Decompressing %s:\n", argv[1]);
|
||||
|
||||
if (decompress()!=0)
|
||||
{
|
||||
fprintf(stderr, "%s: Corrupt input\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_out=fopen(out_name, "wb");
|
||||
if (!g_out)
|
||||
{
|
||||
perror(out_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const int magic=LZ4_MAGIC;
|
||||
fwrite(&magic, 1, sizeof(magic), g_out);
|
||||
|
||||
fprintf(stderr, "Compressing %s:\n", argv[1]);
|
||||
|
||||
if (level==9)
|
||||
compress_optimal();
|
||||
else
|
||||
compress((level<8)?1<<level:WINDOW_SIZE);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%lld -> %lld in %1.3f sec\n", _ftelli64(g_in),
|
||||
_ftelli64(g_out), double(clock()-start)/CLOCKS_PER_SEC);
|
||||
|
||||
fclose(g_in);
|
||||
fclose(g_out);
|
||||
|
||||
#ifndef NO_UTIME
|
||||
struct _stati64 sb;
|
||||
if (_stati64(argv[1], &sb)!=0)
|
||||
{
|
||||
perror("Stat() failed");
|
||||
exit(1);
|
||||
}
|
||||
struct utimbuf ub;
|
||||
ub.actime=sb.st_atime;
|
||||
ub.modtime=sb.st_mtime;
|
||||
if (utime(out_name, &ub)!=0)
|
||||
{
|
||||
perror("Utime() failed");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
301
Kinc/Sources/kinc/libs/neon_mathfun.h
Normal file
301
Kinc/Sources/kinc/libs/neon_mathfun.h
Normal file
@ -0,0 +1,301 @@
|
||||
/* NEON implementation of sin, cos, exp and log
|
||||
|
||||
Inspired by Intel Approximate Math library, and based on the
|
||||
corresponding algorithms of the cephes math library
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2011 Julien Pommier
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
(this is the zlib license)
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
typedef float32x4_t v4sf; // vector of 4 float
|
||||
typedef uint32x4_t v4su; // vector of 4 uint32
|
||||
typedef int32x4_t v4si; // vector of 4 uint32
|
||||
|
||||
#define c_inv_mant_mask ~0x7f800000u
|
||||
#define c_cephes_SQRTHF 0.707106781186547524
|
||||
#define c_cephes_log_p0 7.0376836292E-2
|
||||
#define c_cephes_log_p1 - 1.1514610310E-1
|
||||
#define c_cephes_log_p2 1.1676998740E-1
|
||||
#define c_cephes_log_p3 - 1.2420140846E-1
|
||||
#define c_cephes_log_p4 + 1.4249322787E-1
|
||||
#define c_cephes_log_p5 - 1.6668057665E-1
|
||||
#define c_cephes_log_p6 + 2.0000714765E-1
|
||||
#define c_cephes_log_p7 - 2.4999993993E-1
|
||||
#define c_cephes_log_p8 + 3.3333331174E-1
|
||||
#define c_cephes_log_q1 -2.12194440e-4
|
||||
#define c_cephes_log_q2 0.693359375
|
||||
|
||||
/* natural logarithm computed for 4 simultaneous float
|
||||
return NaN for x <= 0
|
||||
*/
|
||||
v4sf log_ps(v4sf x) {
|
||||
v4sf one = vdupq_n_f32(1);
|
||||
|
||||
x = vmaxq_f32(x, vdupq_n_f32(0)); /* force flush to zero on denormal values */
|
||||
v4su invalid_mask = vcleq_f32(x, vdupq_n_f32(0));
|
||||
|
||||
v4si ux = vreinterpretq_s32_f32(x);
|
||||
|
||||
v4si emm0 = vshrq_n_s32(ux, 23);
|
||||
|
||||
/* keep only the fractional part */
|
||||
ux = vandq_s32(ux, vdupq_n_s32(c_inv_mant_mask));
|
||||
ux = vorrq_s32(ux, vreinterpretq_s32_f32(vdupq_n_f32(0.5f)));
|
||||
x = vreinterpretq_f32_s32(ux);
|
||||
|
||||
emm0 = vsubq_s32(emm0, vdupq_n_s32(0x7f));
|
||||
v4sf e = vcvtq_f32_s32(emm0);
|
||||
|
||||
e = vaddq_f32(e, one);
|
||||
|
||||
/* part2:
|
||||
if( x < SQRTHF ) {
|
||||
e -= 1;
|
||||
x = x + x - 1.0;
|
||||
} else { x = x - 1.0; }
|
||||
*/
|
||||
v4su mask = vcltq_f32(x, vdupq_n_f32(c_cephes_SQRTHF));
|
||||
v4sf tmp = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(x), mask));
|
||||
x = vsubq_f32(x, one);
|
||||
e = vsubq_f32(e, vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(one), mask)));
|
||||
x = vaddq_f32(x, tmp);
|
||||
|
||||
v4sf z = vmulq_f32(x,x);
|
||||
|
||||
v4sf y = vdupq_n_f32(c_cephes_log_p0);
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p1));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p2));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p3));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p4));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p5));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p6));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p7));
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p8));
|
||||
y = vmulq_f32(y, x);
|
||||
|
||||
y = vmulq_f32(y, z);
|
||||
|
||||
|
||||
tmp = vmulq_f32(e, vdupq_n_f32(c_cephes_log_q1));
|
||||
y = vaddq_f32(y, tmp);
|
||||
|
||||
|
||||
tmp = vmulq_f32(z, vdupq_n_f32(0.5f));
|
||||
y = vsubq_f32(y, tmp);
|
||||
|
||||
tmp = vmulq_f32(e, vdupq_n_f32(c_cephes_log_q2));
|
||||
x = vaddq_f32(x, y);
|
||||
x = vaddq_f32(x, tmp);
|
||||
x = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(x), invalid_mask)); // negative arg will be NAN
|
||||
return x;
|
||||
}
|
||||
|
||||
#define c_exp_hi 88.3762626647949f
|
||||
#define c_exp_lo -88.3762626647949f
|
||||
|
||||
#define c_cephes_LOG2EF 1.44269504088896341
|
||||
#define c_cephes_exp_C1 0.693359375
|
||||
#define c_cephes_exp_C2 -2.12194440e-4
|
||||
|
||||
#define c_cephes_exp_p0 1.9875691500E-4
|
||||
#define c_cephes_exp_p1 1.3981999507E-3
|
||||
#define c_cephes_exp_p2 8.3334519073E-3
|
||||
#define c_cephes_exp_p3 4.1665795894E-2
|
||||
#define c_cephes_exp_p4 1.6666665459E-1
|
||||
#define c_cephes_exp_p5 5.0000001201E-1
|
||||
|
||||
/* exp() computed for 4 float at once */
|
||||
v4sf exp_ps(v4sf x) {
|
||||
v4sf tmp, fx;
|
||||
|
||||
v4sf one = vdupq_n_f32(1);
|
||||
x = vminq_f32(x, vdupq_n_f32(c_exp_hi));
|
||||
x = vmaxq_f32(x, vdupq_n_f32(c_exp_lo));
|
||||
|
||||
/* express exp(x) as exp(g + n*log(2)) */
|
||||
fx = vmlaq_f32(vdupq_n_f32(0.5f), x, vdupq_n_f32(c_cephes_LOG2EF));
|
||||
|
||||
/* perform a floorf */
|
||||
tmp = vcvtq_f32_s32(vcvtq_s32_f32(fx));
|
||||
|
||||
/* if greater, substract 1 */
|
||||
v4su mask = vcgtq_f32(tmp, fx);
|
||||
mask = vandq_u32(mask, vreinterpretq_u32_f32(one));
|
||||
|
||||
|
||||
fx = vsubq_f32(tmp, vreinterpretq_f32_u32(mask));
|
||||
|
||||
tmp = vmulq_f32(fx, vdupq_n_f32(c_cephes_exp_C1));
|
||||
v4sf z = vmulq_f32(fx, vdupq_n_f32(c_cephes_exp_C2));
|
||||
x = vsubq_f32(x, tmp);
|
||||
x = vsubq_f32(x, z);
|
||||
|
||||
static const float cephes_exp_p[6] = { c_cephes_exp_p0, c_cephes_exp_p1, c_cephes_exp_p2, c_cephes_exp_p3, c_cephes_exp_p4, c_cephes_exp_p5 };
|
||||
v4sf y = vld1q_dup_f32(cephes_exp_p+0);
|
||||
v4sf c1 = vld1q_dup_f32(cephes_exp_p+1);
|
||||
v4sf c2 = vld1q_dup_f32(cephes_exp_p+2);
|
||||
v4sf c3 = vld1q_dup_f32(cephes_exp_p+3);
|
||||
v4sf c4 = vld1q_dup_f32(cephes_exp_p+4);
|
||||
v4sf c5 = vld1q_dup_f32(cephes_exp_p+5);
|
||||
|
||||
y = vmulq_f32(y, x);
|
||||
z = vmulq_f32(x,x);
|
||||
y = vaddq_f32(y, c1);
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, c2);
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, c3);
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, c4);
|
||||
y = vmulq_f32(y, x);
|
||||
y = vaddq_f32(y, c5);
|
||||
|
||||
y = vmulq_f32(y, z);
|
||||
y = vaddq_f32(y, x);
|
||||
y = vaddq_f32(y, one);
|
||||
|
||||
/* build 2^n */
|
||||
int32x4_t mm;
|
||||
mm = vcvtq_s32_f32(fx);
|
||||
mm = vaddq_s32(mm, vdupq_n_s32(0x7f));
|
||||
mm = vshlq_n_s32(mm, 23);
|
||||
v4sf pow2n = vreinterpretq_f32_s32(mm);
|
||||
|
||||
y = vmulq_f32(y, pow2n);
|
||||
return y;
|
||||
}
|
||||
|
||||
#define c_minus_cephes_DP1 -0.78515625
|
||||
#define c_minus_cephes_DP2 -2.4187564849853515625e-4
|
||||
#define c_minus_cephes_DP3 -3.77489497744594108e-8
|
||||
#define c_sincof_p0 -1.9515295891E-4
|
||||
#define c_sincof_p1 8.3321608736E-3
|
||||
#define c_sincof_p2 -1.6666654611E-1
|
||||
#define c_coscof_p0 2.443315711809948E-005
|
||||
#define c_coscof_p1 -1.388731625493765E-003
|
||||
#define c_coscof_p2 4.166664568298827E-002
|
||||
#define c_cephes_FOPI 1.27323954473516 // 4 / M_PI
|
||||
|
||||
/* evaluation of 4 sines & cosines at once.
|
||||
|
||||
The code is the exact rewriting of the cephes sinf function.
|
||||
Precision is excellent as long as x < 8192 (I did not bother to
|
||||
take into account the special handling they have for greater values
|
||||
-- it does not return garbage for arguments over 8192, though, but
|
||||
the extra precision is missing).
|
||||
|
||||
Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the
|
||||
surprising but correct result.
|
||||
|
||||
Note also that when you compute sin(x), cos(x) is available at
|
||||
almost no extra price so both sin_ps and cos_ps make use of
|
||||
sincos_ps..
|
||||
*/
|
||||
void sincos_ps(v4sf x, v4sf *ysin, v4sf *ycos) { // any x
|
||||
v4sf xmm1, xmm2, xmm3, y;
|
||||
|
||||
v4su emm2;
|
||||
|
||||
v4su sign_mask_sin, sign_mask_cos;
|
||||
sign_mask_sin = vcltq_f32(x, vdupq_n_f32(0));
|
||||
x = vabsq_f32(x);
|
||||
|
||||
/* scale by 4/Pi */
|
||||
y = vmulq_f32(x, vdupq_n_f32(c_cephes_FOPI));
|
||||
|
||||
/* store the integer part of y in mm0 */
|
||||
emm2 = vcvtq_u32_f32(y);
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
emm2 = vaddq_u32(emm2, vdupq_n_u32(1));
|
||||
emm2 = vandq_u32(emm2, vdupq_n_u32(~1));
|
||||
y = vcvtq_f32_u32(emm2);
|
||||
|
||||
/* get the polynom selection mask
|
||||
there is one polynom for 0 <= x <= Pi/4
|
||||
and another one for Pi/4<x<=Pi/2
|
||||
|
||||
Both branches will be computed.
|
||||
*/
|
||||
v4su poly_mask = vtstq_u32(emm2, vdupq_n_u32(2));
|
||||
|
||||
/* The magic pass: "Extended precision modular arithmetic"
|
||||
x = ((x - y * DP1) - y * DP2) - y * DP3; */
|
||||
xmm1 = vmulq_n_f32(y, c_minus_cephes_DP1);
|
||||
xmm2 = vmulq_n_f32(y, c_minus_cephes_DP2);
|
||||
xmm3 = vmulq_n_f32(y, c_minus_cephes_DP3);
|
||||
x = vaddq_f32(x, xmm1);
|
||||
x = vaddq_f32(x, xmm2);
|
||||
x = vaddq_f32(x, xmm3);
|
||||
|
||||
sign_mask_sin = veorq_u32(sign_mask_sin, vtstq_u32(emm2, vdupq_n_u32(4)));
|
||||
sign_mask_cos = vtstq_u32(vsubq_u32(emm2, vdupq_n_u32(2)), vdupq_n_u32(4));
|
||||
|
||||
/* Evaluate the first polynom (0 <= x <= Pi/4) in y1,
|
||||
and the second polynom (Pi/4 <= x <= 0) in y2 */
|
||||
v4sf z = vmulq_f32(x,x);
|
||||
v4sf y1, y2;
|
||||
|
||||
y1 = vmulq_n_f32(z, c_coscof_p0);
|
||||
y2 = vmulq_n_f32(z, c_sincof_p0);
|
||||
y1 = vaddq_f32(y1, vdupq_n_f32(c_coscof_p1));
|
||||
y2 = vaddq_f32(y2, vdupq_n_f32(c_sincof_p1));
|
||||
y1 = vmulq_f32(y1, z);
|
||||
y2 = vmulq_f32(y2, z);
|
||||
y1 = vaddq_f32(y1, vdupq_n_f32(c_coscof_p2));
|
||||
y2 = vaddq_f32(y2, vdupq_n_f32(c_sincof_p2));
|
||||
y1 = vmulq_f32(y1, z);
|
||||
y2 = vmulq_f32(y2, z);
|
||||
y1 = vmulq_f32(y1, z);
|
||||
y2 = vmulq_f32(y2, x);
|
||||
y1 = vsubq_f32(y1, vmulq_f32(z, vdupq_n_f32(0.5f)));
|
||||
y2 = vaddq_f32(y2, x);
|
||||
y1 = vaddq_f32(y1, vdupq_n_f32(1));
|
||||
|
||||
/* select the correct result from the two polynoms */
|
||||
v4sf ys = vbslq_f32(poly_mask, y1, y2);
|
||||
v4sf yc = vbslq_f32(poly_mask, y2, y1);
|
||||
*ysin = vbslq_f32(sign_mask_sin, vnegq_f32(ys), ys);
|
||||
*ycos = vbslq_f32(sign_mask_cos, yc, vnegq_f32(yc));
|
||||
}
|
||||
|
||||
v4sf sin_ps(v4sf x) {
|
||||
v4sf ysin, ycos;
|
||||
sincos_ps(x, &ysin, &ycos);
|
||||
return ysin;
|
||||
}
|
||||
|
||||
v4sf cos_ps(v4sf x) {
|
||||
v4sf ysin, ycos;
|
||||
sincos_ps(x, &ysin, &ycos);
|
||||
return ycos;
|
||||
}
|
||||
|
||||
|
||||
711
Kinc/Sources/kinc/libs/sse_mathfun.h
Normal file
711
Kinc/Sources/kinc/libs/sse_mathfun.h
Normal file
@ -0,0 +1,711 @@
|
||||
/* SIMD (SSE1+MMX or SSE2) implementation of sin, cos, exp and log
|
||||
|
||||
Inspired by Intel Approximate Math library, and based on the
|
||||
corresponding algorithms of the cephes math library
|
||||
|
||||
The default is to use the SSE1 version. If you define USE_SSE2 the
|
||||
the SSE2 intrinsics will be used in place of the MMX intrinsics. Do
|
||||
not expect any significant performance improvement with SSE2.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2007 Julien Pommier
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
(this is the zlib license)
|
||||
*/
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
/* yes I know, the top of this file is quite ugly */
|
||||
|
||||
#ifdef _MSC_VER /* visual c++ */
|
||||
# define ALIGN16_BEG __declspec(align(16))
|
||||
# define ALIGN16_END
|
||||
#else /* gcc or icc */
|
||||
# define ALIGN16_BEG
|
||||
# define ALIGN16_END __attribute__((aligned(16)))
|
||||
#endif
|
||||
|
||||
/* __m128 is ugly to write */
|
||||
typedef __m128 v4sf; // vector of 4 float (sse1)
|
||||
|
||||
#ifdef USE_SSE2
|
||||
# include <emmintrin.h>
|
||||
typedef __m128i v4si; // vector of 4 int (sse2)
|
||||
#else
|
||||
typedef __m64 v2si; // vector of 2 int (mmx)
|
||||
#endif
|
||||
|
||||
/* declare some SSE constants -- why can't I figure a better way to do that? */
|
||||
#define _PS_CONST(Name, Val) \
|
||||
static const ALIGN16_BEG float _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
|
||||
#define _PI32_CONST(Name, Val) \
|
||||
static const ALIGN16_BEG int _pi32_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
|
||||
#define _PS_CONST_TYPE(Name, Type, Val) \
|
||||
static const ALIGN16_BEG Type _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
|
||||
|
||||
_PS_CONST(1 , 1.0f);
|
||||
_PS_CONST(0p5, 0.5f);
|
||||
/* the smallest non denormalized float number */
|
||||
_PS_CONST_TYPE(min_norm_pos, int, 0x00800000);
|
||||
_PS_CONST_TYPE(mant_mask, int, 0x7f800000);
|
||||
_PS_CONST_TYPE(inv_mant_mask, int, ~0x7f800000);
|
||||
|
||||
_PS_CONST_TYPE(sign_mask, int, (int)0x80000000);
|
||||
_PS_CONST_TYPE(inv_sign_mask, int, ~0x80000000);
|
||||
|
||||
_PI32_CONST(1, 1);
|
||||
_PI32_CONST(inv1, ~1);
|
||||
_PI32_CONST(2, 2);
|
||||
_PI32_CONST(4, 4);
|
||||
_PI32_CONST(0x7f, 0x7f);
|
||||
|
||||
_PS_CONST(cephes_SQRTHF, 0.707106781186547524);
|
||||
_PS_CONST(cephes_log_p0, 7.0376836292E-2);
|
||||
_PS_CONST(cephes_log_p1, - 1.1514610310E-1);
|
||||
_PS_CONST(cephes_log_p2, 1.1676998740E-1);
|
||||
_PS_CONST(cephes_log_p3, - 1.2420140846E-1);
|
||||
_PS_CONST(cephes_log_p4, + 1.4249322787E-1);
|
||||
_PS_CONST(cephes_log_p5, - 1.6668057665E-1);
|
||||
_PS_CONST(cephes_log_p6, + 2.0000714765E-1);
|
||||
_PS_CONST(cephes_log_p7, - 2.4999993993E-1);
|
||||
_PS_CONST(cephes_log_p8, + 3.3333331174E-1);
|
||||
_PS_CONST(cephes_log_q1, -2.12194440e-4);
|
||||
_PS_CONST(cephes_log_q2, 0.693359375);
|
||||
|
||||
#ifndef USE_SSE2
|
||||
typedef union xmm_mm_union {
|
||||
__m128 xmm;
|
||||
__m64 mm[2];
|
||||
} xmm_mm_union;
|
||||
|
||||
#define COPY_XMM_TO_MM(xmm_, mm0_, mm1_) { \
|
||||
xmm_mm_union u; u.xmm = xmm_; \
|
||||
mm0_ = u.mm[0]; \
|
||||
mm1_ = u.mm[1]; \
|
||||
}
|
||||
|
||||
#define COPY_MM_TO_XMM(mm0_, mm1_, xmm_) { \
|
||||
xmm_mm_union u; u.mm[0]=mm0_; u.mm[1]=mm1_; xmm_ = u.xmm; \
|
||||
}
|
||||
|
||||
#endif // USE_SSE2
|
||||
|
||||
/* natural logarithm computed for 4 simultaneous float
|
||||
return NaN for x <= 0
|
||||
*/
|
||||
v4sf log_ps(v4sf x) {
|
||||
#ifdef USE_SSE2
|
||||
v4si emm0;
|
||||
#else
|
||||
v2si mm0, mm1;
|
||||
#endif
|
||||
v4sf one = *(v4sf*)_ps_1;
|
||||
|
||||
v4sf invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps());
|
||||
|
||||
x = _mm_max_ps(x, *(v4sf*)_ps_min_norm_pos); /* cut off denormalized stuff */
|
||||
|
||||
#ifndef USE_SSE2
|
||||
/* part 1: x = frexpf(x, &e); */
|
||||
COPY_XMM_TO_MM(x, mm0, mm1);
|
||||
mm0 = _mm_srli_pi32(mm0, 23);
|
||||
mm1 = _mm_srli_pi32(mm1, 23);
|
||||
#else
|
||||
emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23);
|
||||
#endif
|
||||
/* keep only the fractional part */
|
||||
x = _mm_and_ps(x, *(v4sf*)_ps_inv_mant_mask);
|
||||
x = _mm_or_ps(x, *(v4sf*)_ps_0p5);
|
||||
|
||||
#ifndef USE_SSE2
|
||||
/* now e=mm0:mm1 contain the really base-2 exponent */
|
||||
mm0 = _mm_sub_pi32(mm0, *(v2si*)_pi32_0x7f);
|
||||
mm1 = _mm_sub_pi32(mm1, *(v2si*)_pi32_0x7f);
|
||||
v4sf e = _mm_cvtpi32x2_ps(mm0, mm1);
|
||||
_mm_empty(); /* bye bye mmx */
|
||||
#else
|
||||
emm0 = _mm_sub_epi32(emm0, *(v4si*)_pi32_0x7f);
|
||||
v4sf e = _mm_cvtepi32_ps(emm0);
|
||||
#endif
|
||||
|
||||
e = _mm_add_ps(e, one);
|
||||
|
||||
/* part2:
|
||||
if( x < SQRTHF ) {
|
||||
e -= 1;
|
||||
x = x + x - 1.0;
|
||||
} else { x = x - 1.0; }
|
||||
*/
|
||||
v4sf mask = _mm_cmplt_ps(x, *(v4sf*)_ps_cephes_SQRTHF);
|
||||
v4sf tmp = _mm_and_ps(x, mask);
|
||||
x = _mm_sub_ps(x, one);
|
||||
e = _mm_sub_ps(e, _mm_and_ps(one, mask));
|
||||
x = _mm_add_ps(x, tmp);
|
||||
|
||||
|
||||
v4sf z = _mm_mul_ps(x,x);
|
||||
|
||||
v4sf y = *(v4sf*)_ps_cephes_log_p0;
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p1);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p2);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p3);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p4);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p5);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p6);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p7);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p8);
|
||||
y = _mm_mul_ps(y, x);
|
||||
|
||||
y = _mm_mul_ps(y, z);
|
||||
|
||||
|
||||
tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q1);
|
||||
y = _mm_add_ps(y, tmp);
|
||||
|
||||
|
||||
tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
|
||||
y = _mm_sub_ps(y, tmp);
|
||||
|
||||
tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q2);
|
||||
x = _mm_add_ps(x, y);
|
||||
x = _mm_add_ps(x, tmp);
|
||||
x = _mm_or_ps(x, invalid_mask); // negative arg will be NAN
|
||||
return x;
|
||||
}
|
||||
|
||||
_PS_CONST(exp_hi, 88.3762626647949f);
|
||||
_PS_CONST(exp_lo, -88.3762626647949f);
|
||||
|
||||
_PS_CONST(cephes_LOG2EF, 1.44269504088896341);
|
||||
_PS_CONST(cephes_exp_C1, 0.693359375);
|
||||
_PS_CONST(cephes_exp_C2, -2.12194440e-4);
|
||||
|
||||
_PS_CONST(cephes_exp_p0, 1.9875691500E-4);
|
||||
_PS_CONST(cephes_exp_p1, 1.3981999507E-3);
|
||||
_PS_CONST(cephes_exp_p2, 8.3334519073E-3);
|
||||
_PS_CONST(cephes_exp_p3, 4.1665795894E-2);
|
||||
_PS_CONST(cephes_exp_p4, 1.6666665459E-1);
|
||||
_PS_CONST(cephes_exp_p5, 5.0000001201E-1);
|
||||
|
||||
v4sf exp_ps(v4sf x) {
|
||||
v4sf tmp = _mm_setzero_ps(), fx;
|
||||
#ifdef USE_SSE2
|
||||
v4si emm0;
|
||||
#else
|
||||
v2si mm0, mm1;
|
||||
#endif
|
||||
v4sf one = *(v4sf*)_ps_1;
|
||||
|
||||
x = _mm_min_ps(x, *(v4sf*)_ps_exp_hi);
|
||||
x = _mm_max_ps(x, *(v4sf*)_ps_exp_lo);
|
||||
|
||||
/* express exp(x) as exp(g + n*log(2)) */
|
||||
fx = _mm_mul_ps(x, *(v4sf*)_ps_cephes_LOG2EF);
|
||||
fx = _mm_add_ps(fx, *(v4sf*)_ps_0p5);
|
||||
|
||||
/* how to perform a floorf with SSE: just below */
|
||||
#ifndef USE_SSE2
|
||||
/* step 1 : cast to int */
|
||||
tmp = _mm_movehl_ps(tmp, fx);
|
||||
mm0 = _mm_cvttps_pi32(fx);
|
||||
mm1 = _mm_cvttps_pi32(tmp);
|
||||
/* step 2 : cast back to float */
|
||||
tmp = _mm_cvtpi32x2_ps(mm0, mm1);
|
||||
#else
|
||||
emm0 = _mm_cvttps_epi32(fx);
|
||||
tmp = _mm_cvtepi32_ps(emm0);
|
||||
#endif
|
||||
/* if greater, substract 1 */
|
||||
v4sf mask = _mm_cmpgt_ps(tmp, fx);
|
||||
mask = _mm_and_ps(mask, one);
|
||||
fx = _mm_sub_ps(tmp, mask);
|
||||
|
||||
tmp = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C1);
|
||||
v4sf z = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C2);
|
||||
x = _mm_sub_ps(x, tmp);
|
||||
x = _mm_sub_ps(x, z);
|
||||
|
||||
z = _mm_mul_ps(x,x);
|
||||
|
||||
v4sf y = *(v4sf*)_ps_cephes_exp_p0;
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p1);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p2);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p3);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p4);
|
||||
y = _mm_mul_ps(y, x);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p5);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, x);
|
||||
y = _mm_add_ps(y, one);
|
||||
|
||||
/* build 2^n */
|
||||
#ifndef USE_SSE2
|
||||
z = _mm_movehl_ps(z, fx);
|
||||
mm0 = _mm_cvttps_pi32(fx);
|
||||
mm1 = _mm_cvttps_pi32(z);
|
||||
mm0 = _mm_add_pi32(mm0, *(v2si*)_pi32_0x7f);
|
||||
mm1 = _mm_add_pi32(mm1, *(v2si*)_pi32_0x7f);
|
||||
mm0 = _mm_slli_pi32(mm0, 23);
|
||||
mm1 = _mm_slli_pi32(mm1, 23);
|
||||
|
||||
v4sf pow2n;
|
||||
COPY_MM_TO_XMM(mm0, mm1, pow2n);
|
||||
_mm_empty();
|
||||
#else
|
||||
emm0 = _mm_cvttps_epi32(fx);
|
||||
emm0 = _mm_add_epi32(emm0, *(v4si*)_pi32_0x7f);
|
||||
emm0 = _mm_slli_epi32(emm0, 23);
|
||||
v4sf pow2n = _mm_castsi128_ps(emm0);
|
||||
#endif
|
||||
y = _mm_mul_ps(y, pow2n);
|
||||
return y;
|
||||
}
|
||||
|
||||
_PS_CONST(minus_cephes_DP1, -0.78515625);
|
||||
_PS_CONST(minus_cephes_DP2, -2.4187564849853515625e-4);
|
||||
_PS_CONST(minus_cephes_DP3, -3.77489497744594108e-8);
|
||||
_PS_CONST(sincof_p0, -1.9515295891E-4);
|
||||
_PS_CONST(sincof_p1, 8.3321608736E-3);
|
||||
_PS_CONST(sincof_p2, -1.6666654611E-1);
|
||||
_PS_CONST(coscof_p0, 2.443315711809948E-005);
|
||||
_PS_CONST(coscof_p1, -1.388731625493765E-003);
|
||||
_PS_CONST(coscof_p2, 4.166664568298827E-002);
|
||||
_PS_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI
|
||||
|
||||
|
||||
/* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so
|
||||
it runs also on old athlons XPs and the pentium III of your grand
|
||||
mother.
|
||||
|
||||
The code is the exact rewriting of the cephes sinf function.
|
||||
Precision is excellent as long as x < 8192 (I did not bother to
|
||||
take into account the special handling they have for greater values
|
||||
-- it does not return garbage for arguments over 8192, though, but
|
||||
the extra precision is missing).
|
||||
|
||||
Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the
|
||||
surprising but correct result.
|
||||
|
||||
Performance is also surprisingly good, 1.33 times faster than the
|
||||
macos vsinf SSE2 function, and 1.5 times faster than the
|
||||
__vrs4_sinf of amd's ACML (which is only available in 64 bits). Not
|
||||
too bad for an SSE1 function (with no special tuning) !
|
||||
However the latter libraries probably have a much better handling of NaN,
|
||||
Inf, denormalized and other special arguments..
|
||||
|
||||
On my core 1 duo, the execution of this function takes approximately 95 cycles.
|
||||
|
||||
From what I have observed on the experiments with Intel AMath lib, switching to an
|
||||
SSE2 version would improve the perf by only 10%.
|
||||
|
||||
Since it is based on SSE intrinsics, it has to be compiled at -O2 to
|
||||
deliver full speed.
|
||||
*/
|
||||
v4sf sin_ps(v4sf x) { // any x
|
||||
v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y;
|
||||
|
||||
#ifdef USE_SSE2
|
||||
v4si emm0, emm2;
|
||||
#else
|
||||
v2si mm0, mm1, mm2, mm3;
|
||||
#endif
|
||||
sign_bit = x;
|
||||
/* take the absolute value */
|
||||
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
|
||||
/* extract the sign bit (upper one) */
|
||||
sign_bit = _mm_and_ps(sign_bit, *(v4sf*)_ps_sign_mask);
|
||||
|
||||
/* scale by 4/Pi */
|
||||
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
|
||||
|
||||
#ifdef USE_SSE2
|
||||
/* store the integer part of y in mm0 */
|
||||
emm2 = _mm_cvttps_epi32(y);
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
|
||||
y = _mm_cvtepi32_ps(emm2);
|
||||
|
||||
/* get the swap sign flag */
|
||||
emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4);
|
||||
emm0 = _mm_slli_epi32(emm0, 29);
|
||||
/* get the polynom selection mask
|
||||
there is one polynom for 0 <= x <= Pi/4
|
||||
and another one for Pi/4<x<=Pi/2
|
||||
|
||||
Both branches will be computed.
|
||||
*/
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
|
||||
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
|
||||
|
||||
v4sf swap_sign_bit = _mm_castsi128_ps(emm0);
|
||||
v4sf poly_mask = _mm_castsi128_ps(emm2);
|
||||
sign_bit = _mm_xor_ps(sign_bit, swap_sign_bit);
|
||||
|
||||
#else
|
||||
/* store the integer part of y in mm0:mm1 */
|
||||
xmm2 = _mm_movehl_ps(xmm2, y);
|
||||
mm2 = _mm_cvttps_pi32(y);
|
||||
mm3 = _mm_cvttps_pi32(xmm2);
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
|
||||
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
|
||||
y = _mm_cvtpi32x2_ps(mm2, mm3);
|
||||
/* get the swap sign flag */
|
||||
mm0 = _mm_and_si64(mm2, *(v2si*)_pi32_4);
|
||||
mm1 = _mm_and_si64(mm3, *(v2si*)_pi32_4);
|
||||
mm0 = _mm_slli_pi32(mm0, 29);
|
||||
mm1 = _mm_slli_pi32(mm1, 29);
|
||||
/* get the polynom selection mask */
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
|
||||
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
|
||||
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
|
||||
v4sf swap_sign_bit, poly_mask;
|
||||
COPY_MM_TO_XMM(mm0, mm1, swap_sign_bit);
|
||||
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
|
||||
sign_bit = _mm_xor_ps(sign_bit, swap_sign_bit);
|
||||
_mm_empty(); /* good-bye mmx */
|
||||
#endif
|
||||
|
||||
/* The magic pass: "Extended precision modular arithmetic"
|
||||
x = ((x - y * DP1) - y * DP2) - y * DP3; */
|
||||
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
|
||||
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
|
||||
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
|
||||
xmm1 = _mm_mul_ps(y, xmm1);
|
||||
xmm2 = _mm_mul_ps(y, xmm2);
|
||||
xmm3 = _mm_mul_ps(y, xmm3);
|
||||
x = _mm_add_ps(x, xmm1);
|
||||
x = _mm_add_ps(x, xmm2);
|
||||
x = _mm_add_ps(x, xmm3);
|
||||
|
||||
/* Evaluate the first polynom (0 <= x <= Pi/4) */
|
||||
y = *(v4sf*)_ps_coscof_p0;
|
||||
v4sf z = _mm_mul_ps(x,x);
|
||||
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_mul_ps(y, z);
|
||||
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
|
||||
y = _mm_sub_ps(y, tmp);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_1);
|
||||
|
||||
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
|
||||
|
||||
v4sf y2 = *(v4sf*)_ps_sincof_p0;
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_mul_ps(y2, x);
|
||||
y2 = _mm_add_ps(y2, x);
|
||||
|
||||
/* select the correct result from the two polynoms */
|
||||
xmm3 = poly_mask;
|
||||
y2 = _mm_and_ps(xmm3, y2); //, xmm3);
|
||||
y = _mm_andnot_ps(xmm3, y);
|
||||
y = _mm_add_ps(y,y2);
|
||||
/* update the sign */
|
||||
y = _mm_xor_ps(y, sign_bit);
|
||||
return y;
|
||||
}
|
||||
|
||||
/* almost the same as sin_ps */
|
||||
v4sf cos_ps(v4sf x) { // any x
|
||||
v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, y;
|
||||
#ifdef USE_SSE2
|
||||
v4si emm0, emm2;
|
||||
#else
|
||||
v2si mm0, mm1, mm2, mm3;
|
||||
#endif
|
||||
/* take the absolute value */
|
||||
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
|
||||
|
||||
/* scale by 4/Pi */
|
||||
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
|
||||
|
||||
#ifdef USE_SSE2
|
||||
/* store the integer part of y in mm0 */
|
||||
emm2 = _mm_cvttps_epi32(y);
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
|
||||
y = _mm_cvtepi32_ps(emm2);
|
||||
|
||||
emm2 = _mm_sub_epi32(emm2, *(v4si*)_pi32_2);
|
||||
|
||||
/* get the swap sign flag */
|
||||
emm0 = _mm_andnot_si128(emm2, *(v4si*)_pi32_4);
|
||||
emm0 = _mm_slli_epi32(emm0, 29);
|
||||
/* get the polynom selection mask */
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
|
||||
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
|
||||
|
||||
v4sf sign_bit = _mm_castsi128_ps(emm0);
|
||||
v4sf poly_mask = _mm_castsi128_ps(emm2);
|
||||
#else
|
||||
/* store the integer part of y in mm0:mm1 */
|
||||
xmm2 = _mm_movehl_ps(xmm2, y);
|
||||
mm2 = _mm_cvttps_pi32(y);
|
||||
mm3 = _mm_cvttps_pi32(xmm2);
|
||||
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
|
||||
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
|
||||
|
||||
y = _mm_cvtpi32x2_ps(mm2, mm3);
|
||||
|
||||
|
||||
mm2 = _mm_sub_pi32(mm2, *(v2si*)_pi32_2);
|
||||
mm3 = _mm_sub_pi32(mm3, *(v2si*)_pi32_2);
|
||||
|
||||
/* get the swap sign flag in mm0:mm1 and the
|
||||
polynom selection mask in mm2:mm3 */
|
||||
|
||||
mm0 = _mm_andnot_si64(mm2, *(v2si*)_pi32_4);
|
||||
mm1 = _mm_andnot_si64(mm3, *(v2si*)_pi32_4);
|
||||
mm0 = _mm_slli_pi32(mm0, 29);
|
||||
mm1 = _mm_slli_pi32(mm1, 29);
|
||||
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
|
||||
|
||||
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
|
||||
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
|
||||
|
||||
v4sf sign_bit, poly_mask;
|
||||
COPY_MM_TO_XMM(mm0, mm1, sign_bit);
|
||||
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
|
||||
_mm_empty(); /* good-bye mmx */
|
||||
#endif
|
||||
/* The magic pass: "Extended precision modular arithmetic"
|
||||
x = ((x - y * DP1) - y * DP2) - y * DP3; */
|
||||
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
|
||||
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
|
||||
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
|
||||
xmm1 = _mm_mul_ps(y, xmm1);
|
||||
xmm2 = _mm_mul_ps(y, xmm2);
|
||||
xmm3 = _mm_mul_ps(y, xmm3);
|
||||
x = _mm_add_ps(x, xmm1);
|
||||
x = _mm_add_ps(x, xmm2);
|
||||
x = _mm_add_ps(x, xmm3);
|
||||
|
||||
/* Evaluate the first polynom (0 <= x <= Pi/4) */
|
||||
y = *(v4sf*)_ps_coscof_p0;
|
||||
v4sf z = _mm_mul_ps(x,x);
|
||||
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_mul_ps(y, z);
|
||||
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
|
||||
y = _mm_sub_ps(y, tmp);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_1);
|
||||
|
||||
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
|
||||
|
||||
v4sf y2 = *(v4sf*)_ps_sincof_p0;
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_mul_ps(y2, x);
|
||||
y2 = _mm_add_ps(y2, x);
|
||||
|
||||
/* select the correct result from the two polynoms */
|
||||
xmm3 = poly_mask;
|
||||
y2 = _mm_and_ps(xmm3, y2); //, xmm3);
|
||||
y = _mm_andnot_ps(xmm3, y);
|
||||
y = _mm_add_ps(y,y2);
|
||||
/* update the sign */
|
||||
y = _mm_xor_ps(y, sign_bit);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* since sin_ps and cos_ps are almost identical, sincos_ps could replace both of them..
|
||||
it is almost as fast, and gives you a free cosine with your sine */
|
||||
void sincos_ps(v4sf x, v4sf *s, v4sf *c) {
|
||||
v4sf xmm1, xmm2, xmm3 = _mm_setzero_ps(), sign_bit_sin, y;
|
||||
#ifdef USE_SSE2
|
||||
v4si emm0, emm2, emm4;
|
||||
#else
|
||||
v2si mm0, mm1, mm2, mm3, mm4, mm5;
|
||||
#endif
|
||||
sign_bit_sin = x;
|
||||
/* take the absolute value */
|
||||
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
|
||||
/* extract the sign bit (upper one) */
|
||||
sign_bit_sin = _mm_and_ps(sign_bit_sin, *(v4sf*)_ps_sign_mask);
|
||||
|
||||
/* scale by 4/Pi */
|
||||
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
|
||||
|
||||
#ifdef USE_SSE2
|
||||
/* store the integer part of y in emm2 */
|
||||
emm2 = _mm_cvttps_epi32(y);
|
||||
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
|
||||
y = _mm_cvtepi32_ps(emm2);
|
||||
|
||||
emm4 = emm2;
|
||||
|
||||
/* get the swap sign flag for the sine */
|
||||
emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4);
|
||||
emm0 = _mm_slli_epi32(emm0, 29);
|
||||
v4sf swap_sign_bit_sin = _mm_castsi128_ps(emm0);
|
||||
|
||||
/* get the polynom selection mask for the sine*/
|
||||
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
|
||||
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
|
||||
v4sf poly_mask = _mm_castsi128_ps(emm2);
|
||||
#else
|
||||
/* store the integer part of y in mm2:mm3 */
|
||||
xmm3 = _mm_movehl_ps(xmm3, y);
|
||||
mm2 = _mm_cvttps_pi32(y);
|
||||
mm3 = _mm_cvttps_pi32(xmm3);
|
||||
|
||||
/* j=(j+1) & (~1) (see the cephes sources) */
|
||||
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
|
||||
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
|
||||
|
||||
y = _mm_cvtpi32x2_ps(mm2, mm3);
|
||||
|
||||
mm4 = mm2;
|
||||
mm5 = mm3;
|
||||
|
||||
/* get the swap sign flag for the sine */
|
||||
mm0 = _mm_and_si64(mm2, *(v2si*)_pi32_4);
|
||||
mm1 = _mm_and_si64(mm3, *(v2si*)_pi32_4);
|
||||
mm0 = _mm_slli_pi32(mm0, 29);
|
||||
mm1 = _mm_slli_pi32(mm1, 29);
|
||||
v4sf swap_sign_bit_sin;
|
||||
COPY_MM_TO_XMM(mm0, mm1, swap_sign_bit_sin);
|
||||
|
||||
/* get the polynom selection mask for the sine */
|
||||
|
||||
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
|
||||
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
|
||||
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
|
||||
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
|
||||
v4sf poly_mask;
|
||||
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
|
||||
#endif
|
||||
|
||||
/* The magic pass: "Extended precision modular arithmetic"
|
||||
x = ((x - y * DP1) - y * DP2) - y * DP3; */
|
||||
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
|
||||
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
|
||||
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
|
||||
xmm1 = _mm_mul_ps(y, xmm1);
|
||||
xmm2 = _mm_mul_ps(y, xmm2);
|
||||
xmm3 = _mm_mul_ps(y, xmm3);
|
||||
x = _mm_add_ps(x, xmm1);
|
||||
x = _mm_add_ps(x, xmm2);
|
||||
x = _mm_add_ps(x, xmm3);
|
||||
|
||||
#ifdef USE_SSE2
|
||||
emm4 = _mm_sub_epi32(emm4, *(v4si*)_pi32_2);
|
||||
emm4 = _mm_andnot_si128(emm4, *(v4si*)_pi32_4);
|
||||
emm4 = _mm_slli_epi32(emm4, 29);
|
||||
v4sf sign_bit_cos = _mm_castsi128_ps(emm4);
|
||||
#else
|
||||
/* get the sign flag for the cosine */
|
||||
mm4 = _mm_sub_pi32(mm4, *(v2si*)_pi32_2);
|
||||
mm5 = _mm_sub_pi32(mm5, *(v2si*)_pi32_2);
|
||||
mm4 = _mm_andnot_si64(mm4, *(v2si*)_pi32_4);
|
||||
mm5 = _mm_andnot_si64(mm5, *(v2si*)_pi32_4);
|
||||
mm4 = _mm_slli_pi32(mm4, 29);
|
||||
mm5 = _mm_slli_pi32(mm5, 29);
|
||||
v4sf sign_bit_cos;
|
||||
COPY_MM_TO_XMM(mm4, mm5, sign_bit_cos);
|
||||
_mm_empty(); /* good-bye mmx */
|
||||
#endif
|
||||
|
||||
sign_bit_sin = _mm_xor_ps(sign_bit_sin, swap_sign_bit_sin);
|
||||
|
||||
|
||||
/* Evaluate the first polynom (0 <= x <= Pi/4) */
|
||||
v4sf z = _mm_mul_ps(x,x);
|
||||
y = *(v4sf*)_ps_coscof_p0;
|
||||
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
|
||||
y = _mm_mul_ps(y, z);
|
||||
y = _mm_mul_ps(y, z);
|
||||
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
|
||||
y = _mm_sub_ps(y, tmp);
|
||||
y = _mm_add_ps(y, *(v4sf*)_ps_1);
|
||||
|
||||
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
|
||||
|
||||
v4sf y2 = *(v4sf*)_ps_sincof_p0;
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
|
||||
y2 = _mm_mul_ps(y2, z);
|
||||
y2 = _mm_mul_ps(y2, x);
|
||||
y2 = _mm_add_ps(y2, x);
|
||||
|
||||
/* select the correct result from the two polynoms */
|
||||
xmm3 = poly_mask;
|
||||
v4sf ysin2 = _mm_and_ps(xmm3, y2);
|
||||
v4sf ysin1 = _mm_andnot_ps(xmm3, y);
|
||||
y2 = _mm_sub_ps(y2,ysin2);
|
||||
y = _mm_sub_ps(y, ysin1);
|
||||
|
||||
xmm1 = _mm_add_ps(ysin1,ysin2);
|
||||
xmm2 = _mm_add_ps(y,y2);
|
||||
|
||||
/* update the sign */
|
||||
*s = _mm_xor_ps(xmm1, sign_bit_sin);
|
||||
*c = _mm_xor_ps(xmm2, sign_bit_cos);
|
||||
}
|
||||
|
||||
7552
Kinc/Sources/kinc/libs/stb_image.h
Normal file
7552
Kinc/Sources/kinc/libs/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
1906
Kinc/Sources/kinc/libs/stb_sprintf.h
Normal file
1906
Kinc/Sources/kinc/libs/stb_sprintf.h
Normal file
File diff suppressed because it is too large
Load Diff
5520
Kinc/Sources/kinc/libs/stb_vorbis.c
Normal file
5520
Kinc/Sources/kinc/libs/stb_vorbis.c
Normal file
File diff suppressed because it is too large
Load Diff
135
Kinc/Sources/kinc/log.h
Normal file
135
Kinc/Sources/kinc/log.h
Normal file
@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/*! \file log.h
|
||||
\brief Contains basic logging functionality.
|
||||
|
||||
Logging functionality is similar to plain printf but provides some system-specific bonuses.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Pass this to kinc_log or kinc_log_args
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When used on Android the log level is converted to the equivalent
|
||||
/// Android logging level. It is currently ignored on all other targets.
|
||||
/// </remarks>
|
||||
typedef enum { KINC_LOG_LEVEL_INFO, KINC_LOG_LEVEL_WARNING, KINC_LOG_LEVEL_ERROR } kinc_log_level_t;
|
||||
|
||||
/// <summary>
|
||||
/// Logging function similar to printf including some system-specific bonuses
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// On most systems this is equivalent to printf.
|
||||
/// On Windows it works with utf-8 strings (like printf does on any other target)
|
||||
/// and also prints to the debug console in IDEs.
|
||||
/// On Android this uses the android logging functions and also passes the logging level.
|
||||
/// </remarks>
|
||||
/// <param name="log_level">
|
||||
/// The logLevel is ignored on all targets but Android where it is converted
|
||||
/// to the equivalent Android log level
|
||||
/// </param>
|
||||
/// <param name="format">The parameter is equivalent to the first printf parameter.</param>
|
||||
/// <param name="...">The parameter is equivalent to the second printf parameter.</param>
|
||||
KINC_FUNC void kinc_log(kinc_log_level_t log_level, const char *format, ...);
|
||||
|
||||
/// <summary>
|
||||
/// Equivalent to kinc_log but uses a va_list parameter
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You will need this if you want to log parameters using va_start/va_end.
|
||||
/// </remarks>
|
||||
/// <param name="log_level">
|
||||
/// The logLevel is ignored on all targets but Android where it is converted
|
||||
/// to the equivalent Android log level
|
||||
/// </param>
|
||||
/// <param name="format">The parameter is equivalent to the first vprintf parameter.</param>
|
||||
/// <param name="args">The parameter is equivalent to the second vprintf parameter.</param>
|
||||
KINC_FUNC void kinc_log_args(kinc_log_level_t log_level, const char *format, va_list args);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_ROOT
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KORE_MICROSOFT
|
||||
#include <kinc/backend/MiniWindows.h>
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#endif
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
void kinc_log(kinc_log_level_t level, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
kinc_log_args(level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define UTF8
|
||||
|
||||
void kinc_log_args(kinc_log_level_t level, const char *format, va_list args) {
|
||||
#ifdef KORE_MICROSOFT
|
||||
#ifdef UTF8
|
||||
wchar_t buffer[4096];
|
||||
kinc_microsoft_format(format, args, buffer);
|
||||
wcscat(buffer, L"\r\n");
|
||||
OutputDebugStringW(buffer);
|
||||
#ifdef KORE_WINDOWS
|
||||
DWORD written;
|
||||
WriteConsoleW(GetStdHandle(level == KINC_LOG_LEVEL_INFO ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE), buffer, (DWORD)wcslen(buffer), &written, NULL);
|
||||
#endif
|
||||
#else
|
||||
char buffer[4096];
|
||||
vsnprintf(buffer, 4090, format, args);
|
||||
strcat(buffer, "\r\n");
|
||||
OutputDebugStringA(buffer);
|
||||
#ifdef KORE_WINDOWS
|
||||
DWORD written;
|
||||
WriteConsoleA(GetStdHandle(level == KINC_LOG_LEVEL_INFO ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE), buffer, (DWORD)strlen(buffer), &written, NULL);
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
char buffer[4096];
|
||||
vsnprintf(buffer, 4090, format, args);
|
||||
strcat(buffer, "\n");
|
||||
fprintf(level == KINC_LOG_LEVEL_INFO ? stdout : stderr, "%s", buffer);
|
||||
#endif
|
||||
|
||||
#ifdef KORE_ANDROID
|
||||
switch (level) {
|
||||
case KINC_LOG_LEVEL_INFO:
|
||||
__android_log_vprint(ANDROID_LOG_INFO, "Kinc", format, args);
|
||||
break;
|
||||
case KINC_LOG_LEVEL_WARNING:
|
||||
__android_log_vprint(ANDROID_LOG_WARN, "Kinc", format, args);
|
||||
break;
|
||||
case KINC_LOG_LEVEL_ERROR:
|
||||
__android_log_vprint(ANDROID_LOG_ERROR, "Kinc", format, args);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
70
Kinc/Sources/kinc/math/core.h
Normal file
70
Kinc/Sources/kinc/math/core.h
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file core.h
|
||||
\brief Just a few very simple additions to math.h
|
||||
the C-lib.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KINC_PI 3.141592654
|
||||
#define KINC_TAU 6.283185307
|
||||
|
||||
KINC_FUNC float kinc_cot(float x);
|
||||
KINC_FUNC float kinc_round(float value);
|
||||
KINC_FUNC float kinc_abs(float value);
|
||||
KINC_FUNC float kinc_min(float a, float b);
|
||||
KINC_FUNC float kinc_max(float a, float b);
|
||||
KINC_FUNC int kinc_mini(int a, int b);
|
||||
KINC_FUNC int kinc_maxi(int a, int b);
|
||||
KINC_FUNC float kinc_clamp(float value, float minValue, float maxValue);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_MATH
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <math.h>
|
||||
|
||||
float kinc_cot(float x) {
|
||||
return cosf(x) / sinf(x);
|
||||
}
|
||||
|
||||
float kinc_round(float value) {
|
||||
return floorf(value + 0.5f);
|
||||
}
|
||||
|
||||
float kinc_abs(float value) {
|
||||
return value < 0 ? -value : value;
|
||||
}
|
||||
|
||||
float kinc_min(float a, float b) {
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
float kinc_max(float a, float b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
int kinc_mini(int a, int b) {
|
||||
return a > b ? b : a;
|
||||
}
|
||||
|
||||
int kinc_maxi(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
float kinc_clamp(float value, float minValue, float maxValue) {
|
||||
return kinc_max(minValue, kinc_min(maxValue, value));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
5
Kinc/Sources/kinc/math/mathunit.c
Normal file
5
Kinc/Sources/kinc/math/mathunit.c
Normal file
@ -0,0 +1,5 @@
|
||||
#define KINC_IMPLEMENTATION_MATH
|
||||
|
||||
#include "core.h"
|
||||
#include "matrix.h"
|
||||
#include "random.h"
|
||||
198
Kinc/Sources/kinc/math/matrix.h
Normal file
198
Kinc/Sources/kinc/math/matrix.h
Normal file
@ -0,0 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
/*! \file matrix.h
|
||||
\brief Provides basic matrix types and a few functions which create transformation-matrices. This only provides functionality which is needed elsewhere in
|
||||
Kinc - if you need more, look up how transformation-matrices work and add some functions to your own project. Alternatively the Kore/C++-API also provides a
|
||||
more complete matrix-API.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_matrix3x3 {
|
||||
float m[3 * 3];
|
||||
} kinc_matrix3x3_t;
|
||||
|
||||
KINC_FUNC float kinc_matrix3x3_get(kinc_matrix3x3_t *matrix, int x, int y);
|
||||
KINC_FUNC void kinc_matrix3x3_set(kinc_matrix3x3_t *matrix, int x, int y, float value);
|
||||
KINC_FUNC void kinc_matrix3x3_transpose(kinc_matrix3x3_t *matrix);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_identity(void);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_rotation_x(float alpha);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_rotation_y(float alpha);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_rotation_z(float alpha);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_translation(float x, float y);
|
||||
KINC_FUNC kinc_matrix3x3_t kinc_matrix3x3_multiply(kinc_matrix3x3_t *a, kinc_matrix3x3_t *b);
|
||||
KINC_FUNC kinc_vector3_t kinc_matrix3x3_multiply_vector(kinc_matrix3x3_t *a, kinc_vector3_t b);
|
||||
|
||||
typedef struct kinc_matrix4x4 {
|
||||
float m[4 * 4];
|
||||
} kinc_matrix4x4_t;
|
||||
|
||||
KINC_FUNC float kinc_matrix4x4_get(kinc_matrix4x4_t *matrix, int x, int y);
|
||||
KINC_FUNC void kinc_matrix4x4_set(kinc_matrix4x4_t *matrix, int x, int y, float value);
|
||||
KINC_FUNC void kinc_matrix4x4_transpose(kinc_matrix4x4_t *matrix);
|
||||
KINC_FUNC kinc_matrix4x4_t kinc_matrix4x4_multiply(kinc_matrix4x4_t *a, kinc_matrix4x4_t *b);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_MATH
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_MATH
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#endif
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
#ifdef KINC_IMPLEMENTATION_MATH
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
float kinc_matrix3x3_get(kinc_matrix3x3_t *matrix, int x, int y) {
|
||||
return matrix->m[x * 3 + y];
|
||||
}
|
||||
|
||||
void kinc_matrix3x3_set(kinc_matrix3x3_t *matrix, int x, int y, float value) {
|
||||
matrix->m[x * 3 + y] = value;
|
||||
}
|
||||
|
||||
void kinc_matrix3x3_transpose(kinc_matrix3x3_t *matrix) {
|
||||
kinc_matrix3x3_t transposed;
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
kinc_matrix3x3_set(&transposed, x, y, kinc_matrix3x3_get(matrix, y, x));
|
||||
}
|
||||
}
|
||||
memcpy(matrix->m, transposed.m, sizeof(transposed.m));
|
||||
}
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_identity(void) {
|
||||
kinc_matrix3x3_t m;
|
||||
memset(m.m, 0, sizeof(m.m));
|
||||
for (unsigned x = 0; x < 3; ++x) {
|
||||
kinc_matrix3x3_set(&m, x, x, 1.0f);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_rotation_x(float alpha) {
|
||||
kinc_matrix3x3_t m = kinc_matrix3x3_identity();
|
||||
float ca = cosf(alpha);
|
||||
float sa = sinf(alpha);
|
||||
kinc_matrix3x3_set(&m, 1, 1, ca);
|
||||
kinc_matrix3x3_set(&m, 2, 1, -sa);
|
||||
kinc_matrix3x3_set(&m, 1, 2, sa);
|
||||
kinc_matrix3x3_set(&m, 2, 2, ca);
|
||||
return m;
|
||||
}
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_rotation_y(float alpha) {
|
||||
kinc_matrix3x3_t m = kinc_matrix3x3_identity();
|
||||
float ca = cosf(alpha);
|
||||
float sa = sinf(alpha);
|
||||
kinc_matrix3x3_set(&m, 0, 0, ca);
|
||||
kinc_matrix3x3_set(&m, 2, 0, sa);
|
||||
kinc_matrix3x3_set(&m, 0, 2, -sa);
|
||||
kinc_matrix3x3_set(&m, 2, 2, ca);
|
||||
return m;
|
||||
}
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_rotation_z(float alpha) {
|
||||
kinc_matrix3x3_t m = kinc_matrix3x3_identity();
|
||||
float ca = cosf(alpha);
|
||||
float sa = sinf(alpha);
|
||||
kinc_matrix3x3_set(&m, 0, 0, ca);
|
||||
kinc_matrix3x3_set(&m, 1, 0, -sa);
|
||||
kinc_matrix3x3_set(&m, 0, 1, sa);
|
||||
kinc_matrix3x3_set(&m, 1, 1, ca);
|
||||
return m;
|
||||
}
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_translation(float x, float y) {
|
||||
kinc_matrix3x3_t m = kinc_matrix3x3_identity();
|
||||
kinc_matrix3x3_set(&m, 2, 0, x);
|
||||
kinc_matrix3x3_set(&m, 2, 1, y);
|
||||
return m;
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wconditional-uninitialized"
|
||||
#endif
|
||||
|
||||
kinc_matrix3x3_t kinc_matrix3x3_multiply(kinc_matrix3x3_t *a, kinc_matrix3x3_t *b) {
|
||||
kinc_matrix3x3_t result;
|
||||
for (unsigned x = 0; x < 3; ++x) {
|
||||
for (unsigned y = 0; y < 3; ++y) {
|
||||
float t = kinc_matrix3x3_get(a, 0, y) * kinc_matrix3x3_get(b, x, 0);
|
||||
for (unsigned i = 1; i < 3; ++i) {
|
||||
t += kinc_matrix3x3_get(a, i, y) * kinc_matrix3x3_get(b, x, i);
|
||||
}
|
||||
kinc_matrix3x3_set(&result, x, y, t);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static float vector3_get(kinc_vector3_t vec, int index) {
|
||||
float *values = (float *)&vec;
|
||||
return values[index];
|
||||
}
|
||||
|
||||
static void vector3_set(kinc_vector3_t *vec, int index, float value) {
|
||||
float *values = (float *)vec;
|
||||
values[index] = value;
|
||||
}
|
||||
|
||||
kinc_vector3_t kinc_matrix3x3_multiply_vector(kinc_matrix3x3_t *a, kinc_vector3_t b) {
|
||||
kinc_vector3_t product;
|
||||
for (unsigned y = 0; y < 3; ++y) {
|
||||
float t = 0;
|
||||
for (unsigned x = 0; x < 3; ++x) {
|
||||
t += kinc_matrix3x3_get(a, x, y) * vector3_get(b, x);
|
||||
}
|
||||
vector3_set(&product, y, t);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
float kinc_matrix4x4_get(kinc_matrix4x4_t *matrix, int x, int y) {
|
||||
return matrix->m[x * 4 + y];
|
||||
}
|
||||
|
||||
void kinc_matrix4x4_set(kinc_matrix4x4_t *matrix, int x, int y, float value) {
|
||||
matrix->m[x * 4 + y] = value;
|
||||
}
|
||||
|
||||
void kinc_matrix4x4_transpose(kinc_matrix4x4_t *matrix) {
|
||||
kinc_matrix4x4_t transposed;
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
kinc_matrix4x4_set(&transposed, x, y, kinc_matrix4x4_get(matrix, y, x));
|
||||
}
|
||||
}
|
||||
memcpy(matrix->m, transposed.m, sizeof(transposed.m));
|
||||
}
|
||||
|
||||
kinc_matrix4x4_t kinc_matrix4x4_multiply(kinc_matrix4x4_t *a, kinc_matrix4x4_t *b) {
|
||||
kinc_matrix4x4_t result;
|
||||
for (unsigned x = 0; x < 4; ++x)
|
||||
for (unsigned y = 0; y < 4; ++y) {
|
||||
float t = kinc_matrix4x4_get(a, 0, y) * kinc_matrix4x4_get(b, x, 0);
|
||||
for (unsigned i = 1; i < 4; ++i) {
|
||||
t += kinc_matrix4x4_get(a, i, y) * kinc_matrix4x4_get(b, x, i);
|
||||
}
|
||||
kinc_matrix4x4_set(&result, x, y, t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
22
Kinc/Sources/kinc/math/quaternion.h
Normal file
22
Kinc/Sources/kinc/math/quaternion.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/*! \file quaternion.h
|
||||
\brief Provides a basic quaternion type.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_quaternion {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} kinc_quaternion_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
98
Kinc/Sources/kinc/math/random.h
Normal file
98
Kinc/Sources/kinc/math/random.h
Normal file
@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file random.h
|
||||
\brief Generates values which are kind of random.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the randomizer with a seed. This is optional but helpful.
|
||||
/// </summary>
|
||||
/// <param name="seed">A value which should ideally be pretty random</param>
|
||||
KINC_FUNC void kinc_random_init(int64_t seed);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random value.
|
||||
/// </summary>
|
||||
/// <returns>A random value</returns>
|
||||
KINC_FUNC int64_t kinc_random_get(void);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value between 0 and max (both inclusive).
|
||||
/// </summary>
|
||||
/// <returns>A random value</returns>
|
||||
KINC_FUNC int64_t kinc_random_get_max(int64_t max);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value between min and max (both inclusive).
|
||||
/// </summary>
|
||||
/// <returns>A random value</returns>
|
||||
KINC_FUNC int64_t kinc_random_get_in(int64_t min, int64_t max);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_MATH
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// xoshiro256** 1.0
|
||||
|
||||
static inline uint64_t rotl(const uint64_t x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
static uint64_t s[4] = {1, 2, 3, 4};
|
||||
|
||||
uint64_t next(void) {
|
||||
const uint64_t result = rotl(s[1] * 5, 7) * 9;
|
||||
|
||||
const uint64_t t = s[1] << 17;
|
||||
|
||||
s[2] ^= s[0];
|
||||
s[3] ^= s[1];
|
||||
s[1] ^= s[2];
|
||||
s[0] ^= s[3];
|
||||
|
||||
s[2] ^= t;
|
||||
|
||||
s[3] = rotl(s[3], 45);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void kinc_random_init(int64_t seed) {
|
||||
s[0] = (uint64_t)seed;
|
||||
s[1] = 2;
|
||||
s[2] = 3;
|
||||
s[3] = 4;
|
||||
s[1] = next();
|
||||
s[2] = next();
|
||||
s[3] = next();
|
||||
}
|
||||
|
||||
int64_t kinc_random_get(void) {
|
||||
return (int64_t)next();
|
||||
}
|
||||
|
||||
int64_t kinc_random_get_max(int64_t max) {
|
||||
return kinc_random_get() % (max + 1);
|
||||
}
|
||||
|
||||
int64_t kinc_random_get_in(int64_t min, int64_t max) {
|
||||
int64_t value = kinc_random_get();
|
||||
return (value < -LLONG_MAX ? LLONG_MAX : llabs(value)) % (max + 1 - min) + min;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
33
Kinc/Sources/kinc/math/vector.h
Normal file
33
Kinc/Sources/kinc/math/vector.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/*! \file vector.h
|
||||
\brief Provides basic vector types.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kinc_vector2 {
|
||||
float x;
|
||||
float y;
|
||||
} kinc_vector2_t;
|
||||
|
||||
typedef struct kinc_vector3 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} kinc_vector3_t;
|
||||
|
||||
typedef struct kinc_vector4 {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} kinc_vector4_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
49
Kinc/Sources/kinc/network/http.h
Normal file
49
Kinc/Sources/kinc/network/http.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*! \file http.h
|
||||
\brief Provides a simple http-API.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KINC_HTTP_GET 0
|
||||
#define KINC_HTTP_POST 1
|
||||
#define KINC_HTTP_PUT 2
|
||||
#define KINC_HTTP_DELETE 3
|
||||
|
||||
typedef void (*kinc_http_callback_t)(int error, int response, const char *body, void *callbackdata);
|
||||
|
||||
/// <summary>
|
||||
/// Fires off an http request.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_http_request(const char *url, const char *path, const char *data, int port, bool secure, int method, const char *header,
|
||||
kinc_http_callback_t callback, void *callbackdata);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_NETWORK
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#if !defined KORE_MACOS && !defined KORE_IOS && !defined KORE_WINDOWS
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
void kinc_http_request(const char *url, const char *path, const char *data, int port, bool secure, int method, const char *header,
|
||||
kinc_http_callback_t callback, void *callbackdata) {
|
||||
assert(false); // not implemented for the current system, please send a pull-request
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
4
Kinc/Sources/kinc/network/networkunit.c
Normal file
4
Kinc/Sources/kinc/network/networkunit.c
Normal file
@ -0,0 +1,4 @@
|
||||
#define KINC_IMPLEMENTATION_NETWORK
|
||||
|
||||
#include "http.h"
|
||||
#include "socket.h"
|
||||
665
Kinc/Sources/kinc/network/socket.h
Normal file
665
Kinc/Sources/kinc/network/socket.h
Normal file
@ -0,0 +1,665 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/global.h>
|
||||
|
||||
/*! \file socket.h
|
||||
\brief Provides low-level network-communication via UDP or TCP-sockets.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum kinc_socket_protocol { KINC_SOCKET_PROTOCOL_UDP, KINC_SOCKET_PROTOCOL_TCP } kinc_socket_protocol_t;
|
||||
|
||||
typedef enum kinc_socket_family { KINC_SOCKET_FAMILY_IP4, KINC_SOCKET_FAMILY_IP6 } kinc_socket_family_t;
|
||||
|
||||
#ifdef KORE_MICROSOFT
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
|
||||
#else
|
||||
#if !defined _W64
|
||||
#define _W64
|
||||
#endif
|
||||
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
|
||||
#endif
|
||||
typedef UINT_PTR SOCKET;
|
||||
#endif
|
||||
|
||||
typedef struct kinc_socket {
|
||||
#ifdef KORE_MICROSOFT
|
||||
SOCKET handle;
|
||||
#else
|
||||
int handle;
|
||||
#endif
|
||||
uint32_t host;
|
||||
uint32_t port;
|
||||
kinc_socket_protocol_t protocol;
|
||||
kinc_socket_family_t family;
|
||||
bool connected;
|
||||
} kinc_socket_t;
|
||||
|
||||
typedef struct kinc_socket_options {
|
||||
bool non_blocking;
|
||||
bool broadcast;
|
||||
bool tcp_no_delay;
|
||||
} kinc_socket_options_t;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a socket-options-object to the default options
|
||||
/// </summary>
|
||||
/// <param name="options">The new default options</param>
|
||||
KINC_FUNC void kinc_socket_options_set_defaults(kinc_socket_options_t *options);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a socket-object. To set the host and port use kinc_socket_set.
|
||||
/// Host will be localhost
|
||||
/// Port will be 8080
|
||||
/// Family will be IPv4
|
||||
/// Protocol will be TCP
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket to initialize</param>
|
||||
KINC_FUNC void kinc_socket_init(kinc_socket_t *socket);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sockets properties.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket-object to use</param>
|
||||
/// <param name="host">The host to use as IP or URL</param>
|
||||
/// <param name="port">The port to use</param>
|
||||
/// <param name="family">The IP-family to use</param>
|
||||
/// <param name="protocol">The protocol to use</param>
|
||||
/// <returns>Whether the socket was set correctly</returns>
|
||||
KINC_FUNC bool kinc_socket_set(kinc_socket_t *socket, const char *host, int port, kinc_socket_family_t family, kinc_socket_protocol_t protocol);
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a socket-object.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket to destroy</param>
|
||||
KINC_FUNC void kinc_socket_destroy(kinc_socket_t *socket);
|
||||
|
||||
/// <summary>
|
||||
/// Opens a socket-connection.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket-object to use</param>
|
||||
/// <param name="protocol">The protocol to use</param>
|
||||
/// <param name="port">The port to use</param>
|
||||
/// <param name="options">The options to use</param>
|
||||
/// <returns>Whether the socket-connection could be opened</returns>
|
||||
KINC_FUNC bool kinc_socket_open(kinc_socket_t *socket, kinc_socket_options_t *options);
|
||||
|
||||
/// <summary>
|
||||
/// For use with non-blocking sockets to try to see if we are connected.
|
||||
/// </summary>
|
||||
/// <param name="socket">The socket-object to use</param>
|
||||
/// <param name="waittime">The amount of time in seconds the select function will timeout.</param>
|
||||
/// <param name="read">Check if the socket is ready to be read from.</param>
|
||||
/// <param name="write">Check if the socket is ready to be written to.</param>
|
||||
/// <returns>Whether the socket-connection can read or write or checks both.</returns>
|
||||
KINC_FUNC bool kinc_socket_select(kinc_socket_t *socket, uint32_t waittime, bool read, bool write);
|
||||
|
||||
/*Typically these are server actions.*/
|
||||
KINC_FUNC bool kinc_socket_bind(kinc_socket_t *socket);
|
||||
KINC_FUNC bool kinc_socket_listen(kinc_socket_t *socket, int backlog);
|
||||
KINC_FUNC bool kinc_socket_accept(kinc_socket_t *socket, kinc_socket_t *new_socket, unsigned *remote_address, unsigned *remote_port);
|
||||
|
||||
/*Typically this is a client action.*/
|
||||
KINC_FUNC bool kinc_socket_connect(kinc_socket_t *socket);
|
||||
|
||||
KINC_FUNC int kinc_socket_send(kinc_socket_t *socket, const uint8_t *data, int size);
|
||||
KINC_FUNC int kinc_socket_send_address(kinc_socket_t *socket, unsigned address, int port, const uint8_t *data, int size);
|
||||
KINC_FUNC int kinc_socket_send_url(kinc_socket_t *socket, const char *url, int port, const uint8_t *data, int size);
|
||||
KINC_FUNC int kinc_socket_receive(kinc_socket_t *socket, uint8_t *data, int maxSize, unsigned *from_address, unsigned *from_port);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a DNS-entry to an IP and returns its integer representation.
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
KINC_FUNC unsigned kinc_url_to_int(const char *url, int port);
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION_NETWORK
|
||||
#define KINC_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#ifdef KINC_IMPLEMENTATION
|
||||
|
||||
#undef KINC_IMPLEMENTATION
|
||||
#include <kinc/libs/stb_sprintf.h>
|
||||
#include <kinc/log.h>
|
||||
#define KINC_IMPLEMENTATION
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
|
||||
// Windows 7
|
||||
#define WINVER 0x0601
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#define NOATOM
|
||||
#define NOCLIPBOARD
|
||||
#define NOCOLOR
|
||||
#define NOCOMM
|
||||
#define NOCTLMGR
|
||||
#define NODEFERWINDOWPOS
|
||||
#define NODRAWTEXT
|
||||
#define NOGDI
|
||||
#define NOGDICAPMASKS
|
||||
#define NOHELP
|
||||
#define NOICONS
|
||||
#define NOKANJI
|
||||
#define NOKEYSTATES
|
||||
#define NOMB
|
||||
#define NOMCX
|
||||
#define NOMEMMGR
|
||||
#define NOMENUS
|
||||
#define NOMETAFILE
|
||||
#define NOMINMAX
|
||||
#define NOMSG
|
||||
#define NONLS
|
||||
#define NOOPENFILE
|
||||
#define NOPROFILER
|
||||
#define NORASTEROPS
|
||||
#define NOSCROLL
|
||||
#define NOSERVICE
|
||||
#define NOSHOWWINDOW
|
||||
#define NOSOUND
|
||||
#define NOSYSCOMMANDS
|
||||
#define NOSYSMETRICS
|
||||
#define NOTEXTMETRIC
|
||||
#define NOUSER
|
||||
#define NOVIRTUALKEYCODES
|
||||
#define NOWH
|
||||
#define NOWINMESSAGES
|
||||
#define NOWINOFFSETS
|
||||
#define NOWINSTYLES
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <Ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#elif defined(KORE_POSIX) || defined(KORE_EMSCRIPTEN)
|
||||
#include <arpa/inet.h> // for inet_addr()
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(KORE_EMSCRIPTEN)
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/posix_socket.h>
|
||||
#include <emscripten/threading.h>
|
||||
#include <emscripten/websocket.h>
|
||||
|
||||
static EMSCRIPTEN_WEBSOCKET_T bridgeSocket = 0;
|
||||
#elif defined(KORE_POSIX)
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
static int counter = 0;
|
||||
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
// Important: Must be cleaned with freeaddrinfo(address) later if the result is 0 in order to prevent memory leaks
|
||||
static int resolveAddress(const char *url, int port, struct addrinfo **result) {
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_protocol = IPPROTO_UDP;
|
||||
|
||||
char serv[6];
|
||||
sprintf(serv, "%u", port);
|
||||
|
||||
return getaddrinfo(url, serv, &hints, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
KINC_FUNC bool kinc_socket_bind(kinc_socket_t *sock) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
struct sockaddr_in address;
|
||||
address.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
|
||||
address.sin_addr.s_addr = sock->host;
|
||||
address.sin_port = sock->port;
|
||||
if (bind(sock->handle, (const struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not bind socket: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
KINC_FUNC void kinc_socket_options_set_defaults(kinc_socket_options_t *options) {
|
||||
options->non_blocking = true;
|
||||
options->broadcast = false;
|
||||
options->tcp_no_delay = false;
|
||||
}
|
||||
|
||||
void kinc_socket_init(kinc_socket_t *sock) {
|
||||
sock->handle = 0;
|
||||
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
sock->host = INADDR_ANY;
|
||||
sock->port = htons((unsigned short)8080);
|
||||
sock->protocol = KINC_SOCKET_PROTOCOL_TCP;
|
||||
sock->family = KINC_SOCKET_FAMILY_IP4;
|
||||
#endif
|
||||
sock->connected = false;
|
||||
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
if (counter == 0) {
|
||||
WSADATA WsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &WsaData);
|
||||
}
|
||||
#if defined(KORE_EMSCRIPTEN)
|
||||
if (!bridgeSocket) {
|
||||
bridgeSocket = emscripten_init_websocket_to_posix_socket_bridge("ws://localhost:8080");
|
||||
// Synchronously wait until connection has been established.
|
||||
uint16_t readyState = 0;
|
||||
do {
|
||||
emscripten_websocket_get_ready_state(bridgeSocket, &readyState);
|
||||
emscripten_thread_sleep(100);
|
||||
} while (readyState == 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
++counter;
|
||||
}
|
||||
|
||||
bool kinc_socket_open(kinc_socket_t *sock, struct kinc_socket_options *options) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
switch (sock->protocol) {
|
||||
case KINC_SOCKET_PROTOCOL_UDP:
|
||||
sock->handle = socket(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case KINC_SOCKET_PROTOCOL_TCP:
|
||||
sock->handle = socket(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
default:
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Unsupported socket protocol.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sock->handle <= 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not create socket.");
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
int errorCode = WSAGetLastError();
|
||||
switch (errorCode) {
|
||||
case (WSANOTINITIALISED):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "A successful WSAStartup call must occur before using this function.");
|
||||
break;
|
||||
case (WSAENETDOWN):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The network subsystem or the associated service provider has failed.");
|
||||
break;
|
||||
case (WSAEAFNOSUPPORT):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR,
|
||||
"The specified address family is not supported.For example, an application tried to create a socket for the AF_IRDA address "
|
||||
"family but an infrared adapter and device driver is not installed on the local computer.");
|
||||
break;
|
||||
case (WSAEINPROGRESS):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR,
|
||||
"A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.");
|
||||
break;
|
||||
case (WSAEMFILE):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "No more socket descriptors are available.");
|
||||
break;
|
||||
case (WSAEINVAL):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR,
|
||||
"An invalid argument was supplied.This error is returned if the af parameter is set to AF_UNSPEC and the type and protocol "
|
||||
"parameter are unspecified.");
|
||||
break;
|
||||
case (WSAENOBUFS):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "No buffer space is available.The socket cannot be created.");
|
||||
break;
|
||||
case (WSAEPROTONOSUPPORT):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The specified protocol is not supported.");
|
||||
break;
|
||||
case (WSAEPROTOTYPE):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The specified protocol is the wrong type for this socket.");
|
||||
break;
|
||||
case (WSAEPROVIDERFAILEDINIT):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR,
|
||||
"The service provider failed to initialize.This error is returned if a layered service provider(LSP) or namespace provider was "
|
||||
"improperly installed or the provider fails to operate correctly.");
|
||||
break;
|
||||
case (WSAESOCKTNOSUPPORT):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The specified socket type is not supported in this address family.");
|
||||
break;
|
||||
case (WSAEINVALIDPROVIDER):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The service provider returned a version other than 2.2.");
|
||||
break;
|
||||
case (WSAEINVALIDPROCTABLE):
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "The service provider returned an invalid or incomplete procedure table to the WSPStartup.");
|
||||
break;
|
||||
default:
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Unknown error.");
|
||||
}
|
||||
#elif defined(KORE_POSIX) && !defined(KORE_EMSCRIPTEN)
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "%s", strerror(errno));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (options) {
|
||||
if (options->non_blocking) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
DWORD value = 1;
|
||||
if (ioctlsocket(sock->handle, FIONBIO, &value) != 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set non-blocking mode.");
|
||||
return false;
|
||||
}
|
||||
#elif defined(KORE_POSIX)
|
||||
int value = 1;
|
||||
if (fcntl(sock->handle, F_SETFL, O_NONBLOCK, value) == -1) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set non-blocking mode.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (options->broadcast) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
int value = 1;
|
||||
if (setsockopt(sock->handle, SOL_SOCKET, SO_BROADCAST, (const char *)&value, sizeof(value)) < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set broadcast mode.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (options->tcp_no_delay) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
int value = 1;
|
||||
if (setsockopt(sock->handle, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(value)) != 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not set no-delay mode.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void kinc_socket_destroy(kinc_socket_t *sock) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
closesocket(sock->handle);
|
||||
#elif defined(KORE_POSIX)
|
||||
close(sock->handle);
|
||||
#endif
|
||||
|
||||
memset(sock, 0, sizeof(kinc_socket_t));
|
||||
|
||||
--counter;
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
if (counter == 0) {
|
||||
WSACleanup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool kinc_socket_select(kinc_socket_t *sock, uint32_t waittime, bool read, bool write) {
|
||||
#if !defined(KORE_EMSCRIPTEN) && (defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX))
|
||||
fd_set r_fds, w_fds;
|
||||
struct timeval timeout;
|
||||
|
||||
FD_ZERO(&r_fds);
|
||||
FD_ZERO(&w_fds);
|
||||
|
||||
FD_SET(sock->handle, &r_fds);
|
||||
FD_SET(sock->handle, &w_fds);
|
||||
|
||||
timeout.tv_sec = waittime;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
if (select(0, &r_fds, &w_fds, NULL, &timeout) < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "kinc_socket_select didn't work: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (read && write) {
|
||||
return FD_ISSET(sock->handle, &w_fds) && FD_ISSET(sock->handle, &r_fds);
|
||||
}
|
||||
else if (read) {
|
||||
return FD_ISSET(sock->handle, &r_fds);
|
||||
}
|
||||
else if (write) {
|
||||
return FD_ISSET(sock->handle, &w_fds);
|
||||
}
|
||||
else {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Calling kinc_socket_select with both read and write set to false is useless.");
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool kinc_socket_set(kinc_socket_t *sock, const char *host, int port, kinc_socket_family_t family, kinc_socket_protocol_t protocol) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
|
||||
sock->family = family;
|
||||
sock->protocol = protocol;
|
||||
sock->port = htons((unsigned short)port);
|
||||
|
||||
if (host == NULL)
|
||||
return true;
|
||||
|
||||
if (isdigit(host[0]) || (family == KINC_SOCKET_FAMILY_IP6 && host[4] == ':')) { // Is IPv4 or IPv6 string
|
||||
struct in_addr addr;
|
||||
|
||||
if (inet_pton(sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6, host, &addr) == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Invalid %s address: %s\n", sock->family == KINC_SOCKET_FAMILY_IP4 ? "IPv4" : "IPv6", host);
|
||||
return false;
|
||||
}
|
||||
sock->host = addr.s_addr;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
struct addrinfo *address = NULL;
|
||||
int res = resolveAddress(host, port, &address);
|
||||
if (res != 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
|
||||
return false;
|
||||
}
|
||||
#if defined(KORE_POSIX)
|
||||
sock->host = ((struct sockaddr_in *)address->ai_addr)->sin_addr.s_addr;
|
||||
#else
|
||||
sock->host = ((struct sockaddr_in *)address->ai_addr)->sin_addr.S_un.S_addr;
|
||||
#endif
|
||||
freeaddrinfo(address);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool kinc_socket_listen(kinc_socket_t *socket, int backlog) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
int res = listen(socket->handle, backlog);
|
||||
return (res == 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool kinc_socket_accept(kinc_socket_t *sock, kinc_socket_t *newSocket, unsigned *remoteAddress, unsigned *remotePort) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrLength = sizeof(addr);
|
||||
newSocket->handle = accept(sock->handle, (struct sockaddr *)&addr, &addrLength);
|
||||
if (newSocket->handle <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
newSocket->connected = sock->connected = true;
|
||||
newSocket->host = addr.sin_addr.s_addr;
|
||||
newSocket->port = addr.sin_port;
|
||||
newSocket->family = sock->family;
|
||||
newSocket->protocol = sock->protocol;
|
||||
*remoteAddress = ntohl(addr.sin_addr.s_addr);
|
||||
*remotePort = ntohs(addr.sin_port);
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool kinc_socket_connect(kinc_socket_t *sock) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
|
||||
addr.sin_addr.s_addr = sock->host;
|
||||
addr.sin_port = sock->port;
|
||||
|
||||
int res = connect(sock->handle, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||
return sock->connected = (res == 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_socket_send(kinc_socket_t *sock, const uint8_t *data, int size) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
if (sock->protocol == KINC_SOCKET_PROTOCOL_UDP) {
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = sock->family == KINC_SOCKET_FAMILY_IP4 ? AF_INET : AF_INET6;
|
||||
addr.sin_addr.s_addr = sock->host;
|
||||
addr.sin_port = sock->port;
|
||||
|
||||
size_t sent = sendto(sock->handle, (const char *)data, size, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||
if (sent != size) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
|
||||
return -1;
|
||||
}
|
||||
return (int)sent;
|
||||
}
|
||||
else {
|
||||
if (!sock->connected) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Call kinc_sockect_connect/bind before send/recv can be called for TCP sockets.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t sent = send(sock->handle, (const char *)data, size, 0);
|
||||
if (sent != size) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
|
||||
}
|
||||
return (int)sent;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_socket_send_address(kinc_socket_t *sock, unsigned address, int port, const uint8_t *data, int size) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
size_t sent = sendto(sock->handle, (const char *)data, size, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||
if (sent != size) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
|
||||
}
|
||||
return (int)sent;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_socket_send_url(kinc_socket_t *sock, const char *url, int port, const uint8_t *data, int size) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
struct addrinfo *address = NULL;
|
||||
int res = resolveAddress(url, port, &address);
|
||||
if (res != 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t sent = sendto(sock->handle, (const char *)data, size, 0, address->ai_addr, sizeof(struct sockaddr_in));
|
||||
if (sent != size) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not send packet.");
|
||||
}
|
||||
freeaddrinfo(address);
|
||||
return (int)sent;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int kinc_socket_receive(kinc_socket_t *sock, uint8_t *data, int maxSize, unsigned *fromAddress, unsigned *fromPort) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
typedef int socklen_t;
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_POSIX)
|
||||
|
||||
if (sock->protocol == KINC_SOCKET_PROTOCOL_UDP) {
|
||||
struct sockaddr_in from;
|
||||
socklen_t fromLength = sizeof(from);
|
||||
ssize_t bytes = recvfrom(sock->handle, (char *)data, maxSize, 0, (struct sockaddr *)&from, &fromLength);
|
||||
if (bytes <= 0) {
|
||||
return (int)bytes;
|
||||
}
|
||||
*fromAddress = ntohl(from.sin_addr.s_addr);
|
||||
*fromPort = ntohs(from.sin_port);
|
||||
return (int)bytes;
|
||||
}
|
||||
else {
|
||||
|
||||
if (!sock->connected) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Call kinc_sockect_connect/bind before send/recv can be called for TCP sockets.");
|
||||
return -1;
|
||||
}
|
||||
ssize_t bytes = recv(sock->handle, (char *)data, maxSize, 0);
|
||||
*fromAddress = ntohl(sock->host);
|
||||
*fromPort = ntohs(sock->port);
|
||||
return (int)bytes;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned kinc_url_to_int(const char *url, int port) {
|
||||
#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP)
|
||||
struct addrinfo *address = NULL;
|
||||
int res = resolveAddress(url, port, &address);
|
||||
if (res != 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not resolve address.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned fromAddress = ntohl(((struct sockaddr_in *)address->ai_addr)->sin_addr.S_un.S_addr);
|
||||
freeaddrinfo(address);
|
||||
|
||||
return fromAddress;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user