Imported Upstream version 0.13.2+dsfg1
This commit is contained in:
commit
fb3990e9e5
2036 changed files with 287360 additions and 0 deletions
38
libobs/graphics/axisang.c
Normal file
38
libobs/graphics/axisang.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "axisang.h"
|
||||
#include "quat.h"
|
||||
|
||||
void axisang_from_quat(struct axisang *dst, const struct quat *q)
|
||||
{
|
||||
float len, leni;
|
||||
|
||||
len = q->x*q->x + q->y*q->y + q->z*q->z;
|
||||
if (!close_float(len, 0.0f, EPSILON)) {
|
||||
leni = 1.0f/sqrtf(len);
|
||||
dst->x = q->x * leni;
|
||||
dst->y = q->y * leni;
|
||||
dst->z = q->z * leni;
|
||||
dst->w = acosf(q->w)*2.0f;
|
||||
} else {
|
||||
dst->x = 0.0f;
|
||||
dst->y = 0.0f;
|
||||
dst->z = 0.0f;
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
}
|
||||
64
libobs/graphics/axisang.h
Normal file
64
libobs/graphics/axisang.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct quat;
|
||||
|
||||
struct axisang {
|
||||
union {
|
||||
struct {float x, y, z, w;};
|
||||
float ptr[4];
|
||||
};
|
||||
};
|
||||
|
||||
static inline void axisang_zero(struct axisang *dst)
|
||||
{
|
||||
dst->x = 0.0f;
|
||||
dst->y = 0.0f;
|
||||
dst->z = 0.0f;
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void axisang_copy(struct axisang *dst, struct axisang *aa)
|
||||
{
|
||||
dst->x = aa->x;
|
||||
dst->y = aa->y;
|
||||
dst->z = aa->z;
|
||||
dst->w = aa->w;
|
||||
}
|
||||
|
||||
static inline void axisang_set(struct axisang *dst, float x, float y, float z,
|
||||
float w)
|
||||
{
|
||||
dst->x = x;
|
||||
dst->y = y;
|
||||
dst->z = z;
|
||||
dst->w = w;
|
||||
}
|
||||
|
||||
EXPORT void axisang_from_quat(struct axisang *dst, const struct quat *q);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
3
libobs/graphics/basemath.hpp
Normal file
3
libobs/graphics/basemath.hpp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
/* TODO: C++ math wrappers */
|
||||
321
libobs/graphics/bounds.c
Normal file
321
libobs/graphics/bounds.c
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "bounds.h"
|
||||
#include "matrix3.h"
|
||||
#include "matrix4.h"
|
||||
#include "plane.h"
|
||||
|
||||
void bounds_move(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
vec3_add(&dst->min, &b->min, v);
|
||||
vec3_add(&dst->max, &b->max, v);
|
||||
}
|
||||
|
||||
void bounds_scale(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
vec3_mul(&dst->min, &b->min, v);
|
||||
vec3_mul(&dst->max, &b->max, v);
|
||||
}
|
||||
|
||||
void bounds_merge(struct bounds *dst, const struct bounds *b1,
|
||||
const struct bounds *b2)
|
||||
{
|
||||
vec3_min(&dst->min, &b1->min, &b2->min);
|
||||
vec3_max(&dst->max, &b1->max, &b2->max);
|
||||
}
|
||||
|
||||
void bounds_merge_point(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
vec3_min(&dst->min, &b->min, v);
|
||||
vec3_max(&dst->max, &b->max, v);
|
||||
}
|
||||
|
||||
void bounds_get_point(struct vec3 *dst, const struct bounds *b,
|
||||
unsigned int i)
|
||||
{
|
||||
if (i > 8)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* 0 = min.x,min.y,min.z
|
||||
* 1 = min.x,min.y,MAX.z
|
||||
* 2 = min.x,MAX.y,min.z
|
||||
* 3 = min.x,MAX.y,MAX.z
|
||||
* 4 = MAX.x,min.y,min.z
|
||||
* 5 = MAX.x,min.y,MAX.z
|
||||
|
||||
* 6 = MAX.x,MAX.y,min.z
|
||||
* 7 = MAX.x,MAX.y,MAX.z
|
||||
*/
|
||||
|
||||
if(i > 3) {dst->x = b->max.x; i -= 4;}
|
||||
else {dst->x = b->min.x;}
|
||||
|
||||
if(i > 1) {dst->y = b->max.y; i -= 2;}
|
||||
else {dst->y = b->min.y;}
|
||||
|
||||
dst->z = (i == 1) ? b->max.z : b->min.z;
|
||||
}
|
||||
|
||||
void bounds_get_center(struct vec3 *dst, const struct bounds *b)
|
||||
{
|
||||
vec3_sub(dst, &b->max, &b->min);
|
||||
vec3_mulf(dst, dst, 0.5f);
|
||||
vec3_add(dst, dst, &b->min);
|
||||
}
|
||||
|
||||
void bounds_transform(struct bounds *dst, const struct bounds *b,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct bounds temp;
|
||||
bool b_init = false;
|
||||
int i;
|
||||
|
||||
memset(&temp, 0, sizeof(temp));
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
struct vec3 p;
|
||||
bounds_get_point(&p, b, i);
|
||||
vec3_transform(&p, &p, m);
|
||||
|
||||
if (!b_init) {
|
||||
vec3_copy(&temp.min, &p);
|
||||
vec3_copy(&temp.max, &p);
|
||||
b_init = true;
|
||||
} else {
|
||||
if (p.x < temp.min.x)
|
||||
temp.min.x = p.x;
|
||||
else if (p.x > temp.max.x)
|
||||
temp.max.x = p.x;
|
||||
|
||||
if (p.y < temp.min.y)
|
||||
temp.min.y = p.y;
|
||||
else if (p.y > temp.max.y)
|
||||
temp.max.y = p.y;
|
||||
|
||||
if (p.z < temp.min.z)
|
||||
temp.min.z = p.z;
|
||||
else if (p.z > temp.max.z)
|
||||
temp.max.z = p.z;
|
||||
}
|
||||
}
|
||||
|
||||
bounds_copy(dst, &temp);
|
||||
}
|
||||
|
||||
void bounds_transform3x4(struct bounds *dst, const struct bounds *b,
|
||||
const struct matrix3 *m)
|
||||
{
|
||||
struct bounds temp;
|
||||
bool b_init = false;
|
||||
int i;
|
||||
|
||||
memset(&temp, 0, sizeof(temp));
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
struct vec3 p;
|
||||
bounds_get_point(&p, b, i);
|
||||
vec3_transform3x4(&p, &p, m);
|
||||
|
||||
if (!b_init) {
|
||||
vec3_copy(&temp.min, &p);
|
||||
vec3_copy(&temp.max, &p);
|
||||
b_init = true;
|
||||
} else {
|
||||
if (p.x < temp.min.x)
|
||||
temp.min.x = p.x;
|
||||
else if (p.x > temp.max.x)
|
||||
temp.max.x = p.x;
|
||||
|
||||
if (p.y < temp.min.y)
|
||||
temp.min.y = p.y;
|
||||
else if (p.y > temp.max.y)
|
||||
temp.max.y = p.y;
|
||||
|
||||
if (p.z < temp.min.z)
|
||||
temp.min.z = p.z;
|
||||
else if (p.z > temp.max.z)
|
||||
temp.max.z = p.z;
|
||||
}
|
||||
}
|
||||
|
||||
bounds_copy(dst, &temp);
|
||||
}
|
||||
|
||||
bool bounds_intersection_ray(const struct bounds *b, const struct vec3 *orig,
|
||||
const struct vec3 *dir, float *t)
|
||||
{
|
||||
float t_max = M_INFINITE;
|
||||
float t_min = -M_INFINITE;
|
||||
struct vec3 center, max_offset, box_offset;
|
||||
int i;
|
||||
|
||||
bounds_get_center(¢er, b);
|
||||
vec3_sub(&max_offset, &b->max, ¢er);
|
||||
vec3_sub(&box_offset, ¢er, orig);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
float e = box_offset.ptr[i];
|
||||
float f = dir->ptr[i];
|
||||
|
||||
if (fabsf(f) > 0.0f) {
|
||||
float fi = 1.0f/f;
|
||||
float t1 = (e+max_offset.ptr[i])*fi;
|
||||
float t2 = (e-max_offset.ptr[i])*fi;
|
||||
if (t1 > t2) {
|
||||
if (t2 > t_min) t_min = t2;
|
||||
if (t1 < t_max) t_max = t1;
|
||||
} else {
|
||||
if (t1 > t_min) t_min = t1;
|
||||
if (t2 < t_max) t_max = t2;
|
||||
}
|
||||
if (t_min > t_max)
|
||||
return false;
|
||||
if (t_max < 0.0f)
|
||||
return false;
|
||||
} else if ((-e - max_offset.ptr[i]) > 0.0f ||
|
||||
(-e + max_offset.ptr[i]) < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*t = (t_min > 0.0f) ? t_min : t_max;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bounds_intersection_line(const struct bounds *b, const struct vec3 *p1,
|
||||
const struct vec3 *p2, float *t)
|
||||
{
|
||||
struct vec3 dir;
|
||||
float length;
|
||||
|
||||
vec3_sub(&dir, p2, p1);
|
||||
length = vec3_len(&dir);
|
||||
if (length <= TINY_EPSILON)
|
||||
return false;
|
||||
|
||||
vec3_mulf(&dir, &dir, 1.0f/length);
|
||||
|
||||
if (!bounds_intersection_ray(b, p1, &dir, t))
|
||||
return false;
|
||||
|
||||
*t /= length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bounds_plane_test(const struct bounds *b, const struct plane *p)
|
||||
{
|
||||
struct vec3 vmin, vmax;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (p->dir.ptr[i] >= 0.0f) {
|
||||
vmin.ptr[i] = b->min.ptr[i];
|
||||
vmax.ptr[i] = b->max.ptr[i];
|
||||
} else {
|
||||
vmin.ptr[i] = b->max.ptr[i];
|
||||
vmax.ptr[i] = b->min.ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (vec3_plane_dist(&vmin, p) > 0.0f)
|
||||
return BOUNDS_OUTSIDE;
|
||||
|
||||
if (vec3_plane_dist(&vmax, p) >= 0.0f)
|
||||
return BOUNDS_PARTIAL;
|
||||
|
||||
return BOUNDS_INSIDE;
|
||||
}
|
||||
|
||||
bool bounds_under_plane(const struct bounds *b, const struct plane *p)
|
||||
{
|
||||
struct vec3 vmin;
|
||||
|
||||
vmin.x = (p->dir.x < 0.0f) ? b->max.x : b->min.x;
|
||||
vmin.y = (p->dir.y < 0.0f) ? b->max.y : b->min.y;
|
||||
vmin.z = (p->dir.z < 0.0f) ? b->max.z : b->min.z;
|
||||
|
||||
return (vec3_dot(&vmin, &p->dir) <= p->dist);
|
||||
}
|
||||
|
||||
bool bounds_intersects(const struct bounds *b, const struct bounds *test,
|
||||
float epsilon)
|
||||
{
|
||||
return ((b->min.x - test->max.x) <= epsilon) &&
|
||||
((test->min.x - b->max.x) <= epsilon) &&
|
||||
((b->min.y - test->max.y) <= epsilon) &&
|
||||
((test->min.y - b->max.y) <= epsilon) &&
|
||||
((b->min.z - test->max.z) <= epsilon) &&
|
||||
((test->min.z - b->max.z) <= epsilon);
|
||||
}
|
||||
|
||||
bool bounds_intersects_obb(const struct bounds *b, const struct bounds *test,
|
||||
const struct matrix4 *m, float epsilon)
|
||||
{
|
||||
struct bounds b_tr, test_tr;
|
||||
struct matrix4 m_inv;
|
||||
|
||||
matrix4_inv(&m_inv, m);
|
||||
|
||||
bounds_transform(&b_tr, b, m);
|
||||
bounds_transform(&test_tr, test, &m_inv);
|
||||
|
||||
return bounds_intersects(b, &test_tr, epsilon) &&
|
||||
bounds_intersects(&b_tr, test, epsilon);
|
||||
}
|
||||
|
||||
bool bounds_intersects_obb3x4(const struct bounds *b, const struct bounds *test,
|
||||
const struct matrix3 *m, float epsilon)
|
||||
{
|
||||
struct bounds b_tr, test_tr;
|
||||
struct matrix3 m_inv;
|
||||
|
||||
matrix3_transpose(&m_inv, m);
|
||||
|
||||
bounds_transform3x4(&b_tr, b, m);
|
||||
bounds_transform3x4(&test_tr, test, &m_inv);
|
||||
|
||||
return bounds_intersects(b, &test_tr, epsilon) &&
|
||||
bounds_intersects(&b_tr, test, epsilon);
|
||||
}
|
||||
|
||||
static inline float vec3or_offset_len(const struct bounds *b,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
struct vec3 temp1, temp2;
|
||||
vec3_sub(&temp1, &b->max, &b->min);
|
||||
vec3_abs(&temp2, v);
|
||||
return vec3_dot(&temp1, &temp2);
|
||||
}
|
||||
|
||||
float bounds_min_dist(const struct bounds *b, const struct plane *p)
|
||||
{
|
||||
struct vec3 center;
|
||||
float vec_len = vec3or_offset_len(b, &p->dir) * 0.5f;
|
||||
float center_dist;
|
||||
|
||||
bounds_get_center(¢er, b);
|
||||
center_dist = vec3_plane_dist(¢er, p);
|
||||
|
||||
return p->dist + center_dist - vec_len;
|
||||
}
|
||||
137
libobs/graphics/bounds.h
Normal file
137
libobs/graphics/bounds.h
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math-defs.h"
|
||||
#include "vec3.h"
|
||||
|
||||
/*
|
||||
* Axis Aligned Bounding Box
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BOUNDS_MAX_X 1
|
||||
#define BOUNDS_MAX_Y 2
|
||||
#define BOUNDS_MAX_Z 4
|
||||
|
||||
#define BOUNDS_OUTSIDE 1
|
||||
#define BOUNDS_INSIDE 2
|
||||
#define BOUNDS_PARTIAL 3
|
||||
|
||||
struct bounds {
|
||||
struct vec3 min, max;
|
||||
};
|
||||
|
||||
static inline void bounds_zero(struct bounds *dst)
|
||||
{
|
||||
vec3_zero(&dst->min);
|
||||
vec3_zero(&dst->max);
|
||||
}
|
||||
|
||||
static inline void bounds_copy(struct bounds *dst, const struct bounds *b)
|
||||
{
|
||||
vec3_copy(&dst->min, &b->min);
|
||||
vec3_copy(&dst->max, &b->max);
|
||||
}
|
||||
|
||||
EXPORT void bounds_move(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v);
|
||||
|
||||
EXPORT void bounds_scale(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v);
|
||||
|
||||
EXPORT void bounds_merge(struct bounds *dst, const struct bounds *b1,
|
||||
const struct bounds *b2);
|
||||
EXPORT void bounds_merge_point(struct bounds *dst, const struct bounds *b,
|
||||
const struct vec3 *v);
|
||||
|
||||
EXPORT void bounds_get_point(struct vec3 *dst, const struct bounds *b,
|
||||
unsigned int i);
|
||||
EXPORT void bounds_get_center(struct vec3 *dst, const struct bounds *b);
|
||||
|
||||
/**
|
||||
* Note: transforms as OBB, then converts back to AABB, which can result in
|
||||
* the actual size becoming larger than it originally was.
|
||||
*/
|
||||
EXPORT void bounds_transform(struct bounds *dst, const struct bounds *b,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void bounds_transform3x4(struct bounds *dst, const struct bounds *b,
|
||||
const struct matrix3 *m);
|
||||
|
||||
EXPORT bool bounds_intersection_ray(const struct bounds *b,
|
||||
const struct vec3 *orig, const struct vec3 *dir, float *t);
|
||||
EXPORT bool bounds_intersection_line(const struct bounds *b,
|
||||
const struct vec3 *p1, const struct vec3 *p2, float *t);
|
||||
|
||||
EXPORT bool bounds_plane_test(const struct bounds *b, const struct plane *p);
|
||||
EXPORT bool bounds_under_plane(const struct bounds *b,
|
||||
const struct plane *p);
|
||||
|
||||
static inline bool bounds_inside(const struct bounds *b,
|
||||
const struct bounds *test)
|
||||
{
|
||||
return test->min.x >= b->min.x &&
|
||||
test->min.y >= b->min.y &&
|
||||
test->min.z >= b->min.z &&
|
||||
test->max.x <= b->max.x &&
|
||||
test->max.y <= b->max.y &&
|
||||
test->max.z <= b->max.z;
|
||||
}
|
||||
|
||||
static inline bool bounds_vec3_inside(const struct bounds *b,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
return v->x >= (b->min.x-EPSILON) &&
|
||||
v->x <= (b->max.x+EPSILON) &&
|
||||
v->y >= (b->min.y-EPSILON) &&
|
||||
v->y <= (b->max.y+EPSILON) &&
|
||||
v->z >= (b->min.z-EPSILON) &&
|
||||
v->z <= (b->max.z+EPSILON);
|
||||
}
|
||||
|
||||
EXPORT bool bounds_intersects(const struct bounds *b,
|
||||
const struct bounds *test, float epsilon);
|
||||
EXPORT bool bounds_intersects_obb(const struct bounds *b,
|
||||
const struct bounds *test, const struct matrix4 *m,
|
||||
float epsilon);
|
||||
EXPORT bool bounds_intersects_obb3x4(const struct bounds *b,
|
||||
const struct bounds *test, const struct matrix3 *m,
|
||||
float epsilon);
|
||||
|
||||
static inline bool bounds_intersects_ray(const struct bounds *b,
|
||||
const struct vec3 *orig, const struct vec3 *dir)
|
||||
{
|
||||
float t;
|
||||
return bounds_intersection_ray(b, orig, dir, &t);
|
||||
}
|
||||
|
||||
static inline bool bounds_intersects_line(const struct bounds *b,
|
||||
const struct vec3 *p1, const struct vec3 *p2)
|
||||
{
|
||||
float t;
|
||||
return bounds_intersection_line(b, p1, p2, &t);
|
||||
}
|
||||
|
||||
EXPORT float bounds_min_dist(const struct bounds *b, const struct plane *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
148
libobs/graphics/device-exports.h
Normal file
148
libobs/graphics/device-exports.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/c99defs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EXPORT const char *device_get_name(void);
|
||||
EXPORT int device_get_type(void);
|
||||
EXPORT bool device_enum_adapters(
|
||||
bool (*callback)(void *param, const char *name, uint32_t id),
|
||||
void *param);
|
||||
EXPORT const char *device_preprocessor_name(void);
|
||||
EXPORT int device_create(gs_device_t **device, uint32_t adapter);
|
||||
EXPORT void device_destroy(gs_device_t *device);
|
||||
EXPORT void device_enter_context(gs_device_t *device);
|
||||
EXPORT void device_leave_context(gs_device_t *device);
|
||||
EXPORT gs_swapchain_t *device_swapchain_create(gs_device_t *device,
|
||||
const struct gs_init_data *data);
|
||||
EXPORT void device_resize(gs_device_t *device, uint32_t x, uint32_t y);
|
||||
EXPORT void device_get_size(const gs_device_t *device, uint32_t *x, uint32_t *y);
|
||||
EXPORT uint32_t device_get_width(const gs_device_t *device);
|
||||
EXPORT uint32_t device_get_height(const gs_device_t *device);
|
||||
EXPORT gs_texture_t *device_texture_create(gs_device_t *device, uint32_t width,
|
||||
uint32_t height, enum gs_color_format color_format,
|
||||
uint32_t levels, const uint8_t **data, uint32_t flags);
|
||||
EXPORT gs_texture_t *device_cubetexture_create(gs_device_t *device,
|
||||
uint32_t size, enum gs_color_format color_format,
|
||||
uint32_t levels, const uint8_t **data, uint32_t flags);
|
||||
EXPORT gs_texture_t *device_voltexture_create(gs_device_t *device,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
enum gs_color_format color_format, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags);
|
||||
EXPORT gs_zstencil_t *device_zstencil_create(gs_device_t *device,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_zstencil_format format);
|
||||
EXPORT gs_stagesurf_t *device_stagesurface_create(gs_device_t *device,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_color_format color_format);
|
||||
EXPORT gs_samplerstate_t *device_samplerstate_create(gs_device_t *device,
|
||||
const struct gs_sampler_info *info);
|
||||
EXPORT gs_shader_t *device_vertexshader_create(gs_device_t *device,
|
||||
const char *shader, const char *file,
|
||||
char **error_string);
|
||||
EXPORT gs_shader_t *device_pixelshader_create(gs_device_t *device,
|
||||
const char *shader, const char *file,
|
||||
char **error_string);
|
||||
EXPORT gs_vertbuffer_t *device_vertexbuffer_create(gs_device_t *device,
|
||||
struct gs_vb_data *data, uint32_t flags);
|
||||
EXPORT gs_indexbuffer_t *device_indexbuffer_create(gs_device_t *device,
|
||||
enum gs_index_type type, void *indices, size_t num,
|
||||
uint32_t flags);
|
||||
EXPORT enum gs_texture_type device_get_texture_type(
|
||||
const gs_texture_t *texture);
|
||||
EXPORT void device_load_vertexbuffer(gs_device_t *device,
|
||||
gs_vertbuffer_t *vertbuffer);
|
||||
EXPORT void device_load_indexbuffer(gs_device_t *device,
|
||||
gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT void device_load_texture(gs_device_t *device, gs_texture_t *tex,
|
||||
int unit);
|
||||
EXPORT void device_load_samplerstate(gs_device_t *device,
|
||||
gs_samplerstate_t *samplerstate, int unit);
|
||||
EXPORT void device_load_vertexshader(gs_device_t *device,
|
||||
gs_shader_t *vertshader);
|
||||
EXPORT void device_load_pixelshader(gs_device_t *device,
|
||||
gs_shader_t *pixelshader);
|
||||
EXPORT void device_load_default_samplerstate(gs_device_t *device, bool b_3d,
|
||||
int unit);
|
||||
EXPORT gs_shader_t *device_get_vertex_shader(const gs_device_t *device);
|
||||
EXPORT gs_shader_t *device_get_pixel_shader(const gs_device_t *device);
|
||||
EXPORT gs_texture_t *device_get_render_target(const gs_device_t *device);
|
||||
EXPORT gs_zstencil_t *device_get_zstencil_target(const gs_device_t *device);
|
||||
EXPORT void device_set_render_target(gs_device_t *device, gs_texture_t *tex,
|
||||
gs_zstencil_t *zstencil);
|
||||
EXPORT void device_set_cube_render_target(gs_device_t *device,
|
||||
gs_texture_t *cubetex,
|
||||
int side, gs_zstencil_t *zstencil);
|
||||
EXPORT void device_copy_texture(gs_device_t *device, gs_texture_t *dst,
|
||||
gs_texture_t *src);
|
||||
EXPORT void device_copy_texture_region(gs_device_t *device,
|
||||
gs_texture_t *dst, uint32_t dst_x, uint32_t dst_y,
|
||||
gs_texture_t *src, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
EXPORT void device_stage_texture(gs_device_t *device, gs_stagesurf_t *dst,
|
||||
gs_texture_t *src);
|
||||
EXPORT void device_begin_scene(gs_device_t *device);
|
||||
EXPORT void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
|
||||
uint32_t start_vert, uint32_t num_verts);
|
||||
EXPORT void device_end_scene(gs_device_t *device);
|
||||
EXPORT void device_load_swapchain(gs_device_t *device,
|
||||
gs_swapchain_t *swapchain);
|
||||
EXPORT void device_clear(gs_device_t *device, uint32_t clear_flags,
|
||||
const struct vec4 *color, float depth, uint8_t stencil);
|
||||
EXPORT void device_present(gs_device_t *device);
|
||||
EXPORT void device_flush(gs_device_t *device);
|
||||
EXPORT void device_set_cull_mode(gs_device_t *device, enum gs_cull_mode mode);
|
||||
EXPORT enum gs_cull_mode device_get_cull_mode(const gs_device_t *device);
|
||||
EXPORT void device_enable_blending(gs_device_t *device, bool enable);
|
||||
EXPORT void device_enable_depth_test(gs_device_t *device, bool enable);
|
||||
EXPORT void device_enable_stencil_test(gs_device_t *device, bool enable);
|
||||
EXPORT void device_enable_stencil_write(gs_device_t *device, bool enable);
|
||||
EXPORT void device_enable_color(gs_device_t *device, bool red, bool green,
|
||||
bool blue, bool alpha);
|
||||
EXPORT void device_blend_function(gs_device_t *device, enum gs_blend_type src,
|
||||
enum gs_blend_type dest);
|
||||
EXPORT void device_blend_function_separate(gs_device_t *device,
|
||||
enum gs_blend_type src_c, enum gs_blend_type dest_c,
|
||||
enum gs_blend_type src_a, enum gs_blend_type dest_a);
|
||||
EXPORT void device_depth_function(gs_device_t *device, enum gs_depth_test test);
|
||||
EXPORT void device_stencil_function(gs_device_t *device,
|
||||
enum gs_stencil_side side, enum gs_depth_test test);
|
||||
EXPORT void device_stencil_op(gs_device_t *device, enum gs_stencil_side side,
|
||||
enum gs_stencil_op_type fail, enum gs_stencil_op_type zfail,
|
||||
enum gs_stencil_op_type zpass);
|
||||
EXPORT void device_set_viewport(gs_device_t *device, int x, int y, int width,
|
||||
int height);
|
||||
EXPORT void device_get_viewport(const gs_device_t *device,
|
||||
struct gs_rect *rect);
|
||||
EXPORT void device_set_scissor_rect(gs_device_t *device,
|
||||
const struct gs_rect *rect);
|
||||
EXPORT void device_ortho(gs_device_t *device, float left, float right,
|
||||
float top, float bottom, float znear, float zfar);
|
||||
EXPORT void device_frustum(gs_device_t *device, float left, float right,
|
||||
float top, float bottom, float znear, float zfar);
|
||||
EXPORT void device_projection_push(gs_device_t *device);
|
||||
EXPORT void device_projection_pop(gs_device_t *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
1512
libobs/graphics/effect-parser.c
Normal file
1512
libobs/graphics/effect-parser.c
Normal file
File diff suppressed because it is too large
Load diff
283
libobs/graphics/effect-parser.h
Normal file
283
libobs/graphics/effect-parser.h
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/darray.h"
|
||||
#include "../util/cf-parser.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct dstr;
|
||||
|
||||
/*
|
||||
* The effect parser takes an effect file and converts it into individual
|
||||
* shaders for each technique's pass. It automatically writes all dependent
|
||||
* structures/functions/parameters to the shader and builds shader text for
|
||||
* each shader component of each pass.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser var data */
|
||||
|
||||
struct ep_var {
|
||||
char *type, *name, *mapping;
|
||||
bool uniform;
|
||||
};
|
||||
|
||||
static inline void ep_var_init(struct ep_var *epv)
|
||||
{
|
||||
memset(epv, 0, sizeof(struct ep_var));
|
||||
}
|
||||
|
||||
static inline void ep_var_free(struct ep_var *epv)
|
||||
{
|
||||
bfree(epv->type);
|
||||
bfree(epv->name);
|
||||
bfree(epv->mapping);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser param data */
|
||||
|
||||
struct ep_param {
|
||||
char *type, *name;
|
||||
DARRAY(uint8_t) default_val;
|
||||
DARRAY(char*) properties;
|
||||
struct gs_effect_param *param;
|
||||
bool is_const, is_property, is_uniform, is_texture, written;
|
||||
int writeorder, array_count;
|
||||
};
|
||||
|
||||
extern void ep_param_writevar(struct dstr *dst, struct darray *use_params);
|
||||
|
||||
static inline void ep_param_init(struct ep_param *epp,
|
||||
char *type, char *name,
|
||||
bool is_property, bool is_const, bool is_uniform)
|
||||
{
|
||||
epp->type = type;
|
||||
epp->name = name;
|
||||
epp->is_property = is_property;
|
||||
epp->is_const = is_const;
|
||||
epp->is_uniform = is_uniform;
|
||||
epp->is_texture = (astrcmp_n(epp->type, "texture", 7) == 0);
|
||||
epp->written = false;
|
||||
epp->writeorder = false;
|
||||
epp->array_count = 0;
|
||||
da_init(epp->default_val);
|
||||
da_init(epp->properties);
|
||||
}
|
||||
|
||||
static inline void ep_param_free(struct ep_param *epp)
|
||||
{
|
||||
bfree(epp->type);
|
||||
bfree(epp->name);
|
||||
da_free(epp->default_val);
|
||||
da_free(epp->properties);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser struct data */
|
||||
|
||||
struct ep_struct {
|
||||
char *name;
|
||||
DARRAY(struct ep_var) vars; /* struct ep_var */
|
||||
bool written;
|
||||
};
|
||||
|
||||
static inline bool ep_struct_mapped(struct ep_struct *eps)
|
||||
{
|
||||
if (eps->vars.num > 0)
|
||||
return eps->vars.array[0].mapping != NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ep_struct_init(struct ep_struct *eps)
|
||||
{
|
||||
memset(eps, 0, sizeof(struct ep_struct));
|
||||
}
|
||||
|
||||
static inline void ep_struct_free(struct ep_struct *eps)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
bfree(eps->name);
|
||||
for (i = 0; i < eps->vars.num; i++)
|
||||
ep_var_free(eps->vars.array+i);
|
||||
da_free(eps->vars);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser sampler data */
|
||||
|
||||
struct ep_sampler {
|
||||
char *name;
|
||||
DARRAY(char*) states;
|
||||
DARRAY(char*) values;
|
||||
|
||||
bool written;
|
||||
};
|
||||
|
||||
static inline void ep_sampler_init(struct ep_sampler *eps)
|
||||
{
|
||||
memset(eps, 0, sizeof(struct ep_sampler));
|
||||
}
|
||||
|
||||
static inline void ep_sampler_free(struct ep_sampler *eps)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < eps->states.num; i++)
|
||||
bfree(eps->states.array[i]);
|
||||
for (i = 0; i < eps->values.num; i++)
|
||||
bfree(eps->values.array[i]);
|
||||
|
||||
bfree(eps->name);
|
||||
da_free(eps->states);
|
||||
da_free(eps->values);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser pass data */
|
||||
|
||||
struct ep_pass {
|
||||
char *name;
|
||||
DARRAY(struct cf_token) vertex_program;
|
||||
DARRAY(struct cf_token) fragment_program;
|
||||
struct gs_effect_pass *pass;
|
||||
};
|
||||
|
||||
static inline void ep_pass_init(struct ep_pass *epp)
|
||||
{
|
||||
memset(epp, 0, sizeof(struct ep_pass));
|
||||
}
|
||||
|
||||
static inline void ep_pass_free(struct ep_pass *epp)
|
||||
{
|
||||
bfree(epp->name);
|
||||
da_free(epp->vertex_program);
|
||||
da_free(epp->fragment_program);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser technique data */
|
||||
|
||||
struct ep_technique {
|
||||
char *name;
|
||||
DARRAY(struct ep_pass) passes; /* struct ep_pass */
|
||||
};
|
||||
|
||||
static inline void ep_technique_init(struct ep_technique *ept)
|
||||
{
|
||||
memset(ept, 0, sizeof(struct ep_technique));
|
||||
}
|
||||
|
||||
static inline void ep_technique_free(struct ep_technique *ept)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ept->passes.num; i++)
|
||||
ep_pass_free(ept->passes.array+i);
|
||||
|
||||
bfree(ept->name);
|
||||
da_free(ept->passes);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* effect parser function data */
|
||||
|
||||
struct ep_func {
|
||||
char *name, *ret_type, *mapping;
|
||||
struct dstr contents;
|
||||
DARRAY(struct ep_var) param_vars;
|
||||
DARRAY(const char*) func_deps;
|
||||
DARRAY(const char*) struct_deps;
|
||||
DARRAY(const char*) param_deps;
|
||||
DARRAY(const char*) sampler_deps;
|
||||
bool written;
|
||||
};
|
||||
|
||||
static inline void ep_func_init(struct ep_func *epf, char *ret_type,
|
||||
char *name)
|
||||
{
|
||||
memset(epf, 0, sizeof(struct ep_func));
|
||||
epf->name = name;
|
||||
epf->ret_type = ret_type;
|
||||
}
|
||||
|
||||
static inline void ep_func_free(struct ep_func *epf)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < epf->param_vars.num; i++)
|
||||
ep_var_free(epf->param_vars.array+i);
|
||||
|
||||
bfree(epf->name);
|
||||
bfree(epf->ret_type);
|
||||
bfree(epf->mapping);
|
||||
dstr_free(&epf->contents);
|
||||
da_free(epf->param_vars);
|
||||
da_free(epf->func_deps);
|
||||
da_free(epf->struct_deps);
|
||||
da_free(epf->param_deps);
|
||||
da_free(epf->sampler_deps);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct effect_parser {
|
||||
gs_effect_t *effect;
|
||||
|
||||
DARRAY(struct ep_param) params;
|
||||
DARRAY(struct ep_struct) structs;
|
||||
DARRAY(struct ep_func) funcs;
|
||||
DARRAY(struct ep_sampler) samplers;
|
||||
DARRAY(struct ep_technique) techniques;
|
||||
|
||||
/* internal vars */
|
||||
DARRAY(struct cf_lexer) files;
|
||||
DARRAY(struct cf_token) tokens;
|
||||
struct gs_effect_pass *cur_pass;
|
||||
|
||||
struct cf_parser cfp;
|
||||
};
|
||||
|
||||
static inline void ep_init(struct effect_parser *ep)
|
||||
{
|
||||
da_init(ep->params);
|
||||
da_init(ep->structs);
|
||||
da_init(ep->funcs);
|
||||
da_init(ep->samplers);
|
||||
da_init(ep->techniques);
|
||||
da_init(ep->files);
|
||||
da_init(ep->tokens);
|
||||
|
||||
ep->cur_pass = NULL;
|
||||
cf_parser_init(&ep->cfp);
|
||||
}
|
||||
|
||||
extern void ep_free(struct effect_parser *ep);
|
||||
|
||||
extern bool ep_parse(struct effect_parser *ep, gs_effect_t *effect,
|
||||
const char *effect_string, const char *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
380
libobs/graphics/effect.c
Normal file
380
libobs/graphics/effect.c
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "effect.h"
|
||||
#include "graphics-internal.h"
|
||||
#include "vec2.h"
|
||||
#include "vec3.h"
|
||||
#include "vec4.h"
|
||||
|
||||
void gs_effect_actually_destroy(gs_effect_t *effect)
|
||||
{
|
||||
effect_free(effect);
|
||||
bfree(effect);
|
||||
}
|
||||
|
||||
void gs_effect_destroy(gs_effect_t *effect)
|
||||
{
|
||||
if (effect) {
|
||||
if (!effect->cached)
|
||||
gs_effect_actually_destroy(effect);
|
||||
}
|
||||
}
|
||||
|
||||
gs_technique_t *gs_effect_get_technique(const gs_effect_t *effect,
|
||||
const char *name)
|
||||
{
|
||||
if (!effect) return NULL;
|
||||
|
||||
for (size_t i = 0; i < effect->techniques.num; i++) {
|
||||
struct gs_effect_technique *tech = effect->techniques.array+i;
|
||||
if (strcmp(tech->name, name) == 0)
|
||||
return tech;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gs_technique_t *gs_effect_get_current_technique(const gs_effect_t *effect)
|
||||
{
|
||||
if (!effect) return NULL;
|
||||
|
||||
return effect->cur_technique;
|
||||
}
|
||||
|
||||
bool gs_effect_loop(gs_effect_t *effect, const char *name)
|
||||
{
|
||||
if (!effect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!effect->looping) {
|
||||
gs_technique_t *tech;
|
||||
|
||||
if (!!gs_get_effect()) {
|
||||
blog(LOG_WARNING, "gs_effect_loop: An effect is "
|
||||
"already active");
|
||||
return false;
|
||||
}
|
||||
|
||||
tech = gs_effect_get_technique(effect, name);
|
||||
if (!tech) {
|
||||
blog(LOG_WARNING, "gs_effect_loop: Technique '%s' "
|
||||
"not found.", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
gs_technique_begin(tech);
|
||||
|
||||
effect->looping = true;
|
||||
} else {
|
||||
gs_technique_end_pass(effect->cur_technique);
|
||||
}
|
||||
|
||||
if (!gs_technique_begin_pass(effect->cur_technique,
|
||||
effect->loop_pass++)) {
|
||||
gs_technique_end(effect->cur_technique);
|
||||
effect->looping = false;
|
||||
effect->loop_pass = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t gs_technique_begin(gs_technique_t *tech)
|
||||
{
|
||||
if (!tech) return 0;
|
||||
|
||||
tech->effect->cur_technique = tech;
|
||||
tech->effect->graphics->cur_effect = tech->effect;
|
||||
|
||||
return tech->passes.num;
|
||||
}
|
||||
|
||||
void gs_technique_end(gs_technique_t *tech)
|
||||
{
|
||||
if (!tech) return;
|
||||
|
||||
struct gs_effect *effect = tech->effect;
|
||||
struct gs_effect_param *params = effect->params.array;
|
||||
size_t i;
|
||||
|
||||
gs_load_vertexshader(NULL);
|
||||
gs_load_pixelshader(NULL);
|
||||
|
||||
tech->effect->cur_technique = NULL;
|
||||
tech->effect->graphics->cur_effect = NULL;
|
||||
|
||||
for (i = 0; i < effect->params.num; i++) {
|
||||
struct gs_effect_param *param = params+i;
|
||||
|
||||
da_free(param->cur_val);
|
||||
param->changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void reset_params(struct darray *shaderparams)
|
||||
{
|
||||
struct pass_shaderparam *params = shaderparams->array;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < shaderparams->num; i++)
|
||||
params[i].eparam->changed = false;
|
||||
}
|
||||
|
||||
static void upload_shader_params(struct darray *pass_params, bool changed_only)
|
||||
{
|
||||
struct pass_shaderparam *params = pass_params->array;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < pass_params->num; i++) {
|
||||
struct pass_shaderparam *param = params+i;
|
||||
struct gs_effect_param *eparam = param->eparam;
|
||||
gs_sparam_t *sparam = param->sparam;
|
||||
|
||||
if (changed_only && !eparam->changed)
|
||||
continue;
|
||||
|
||||
if (!eparam->cur_val.num) {
|
||||
if (eparam->default_val.num)
|
||||
da_copy(eparam->cur_val, eparam->default_val);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
gs_shader_set_val(sparam, eparam->cur_val.array,
|
||||
eparam->cur_val.num);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void upload_parameters(struct gs_effect *effect,
|
||||
bool changed_only)
|
||||
{
|
||||
struct darray *vshader_params, *pshader_params;
|
||||
|
||||
if (!effect->cur_pass)
|
||||
return;
|
||||
|
||||
vshader_params = &effect->cur_pass->vertshader_params.da;
|
||||
pshader_params = &effect->cur_pass->pixelshader_params.da;
|
||||
|
||||
upload_shader_params(vshader_params, changed_only);
|
||||
upload_shader_params(pshader_params, changed_only);
|
||||
reset_params(vshader_params);
|
||||
reset_params(pshader_params);
|
||||
}
|
||||
|
||||
void gs_effect_update_params(gs_effect_t *effect)
|
||||
{
|
||||
if (effect)
|
||||
upload_parameters(effect, true);
|
||||
}
|
||||
|
||||
bool gs_technique_begin_pass(gs_technique_t *tech, size_t idx)
|
||||
{
|
||||
struct gs_effect_pass *passes;
|
||||
struct gs_effect_pass *cur_pass;
|
||||
|
||||
if (!tech || idx >= tech->passes.num)
|
||||
return false;
|
||||
|
||||
passes = tech->passes.array;
|
||||
cur_pass = passes+idx;
|
||||
|
||||
tech->effect->cur_pass = cur_pass;
|
||||
gs_load_vertexshader(cur_pass->vertshader);
|
||||
gs_load_pixelshader(cur_pass->pixelshader);
|
||||
upload_parameters(tech->effect, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gs_technique_begin_pass_by_name(gs_technique_t *tech,
|
||||
const char *name)
|
||||
{
|
||||
if (!tech)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < tech->passes.num; i++) {
|
||||
struct gs_effect_pass *pass = tech->passes.array+i;
|
||||
if (strcmp(pass->name, name) == 0) {
|
||||
gs_technique_begin_pass(tech, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void clear_tex_params(struct darray *in_params)
|
||||
{
|
||||
struct pass_shaderparam *params = in_params->array;
|
||||
|
||||
for (size_t i = 0; i < in_params->num; i++) {
|
||||
struct pass_shaderparam *param = params+i;
|
||||
struct gs_shader_param_info info;
|
||||
|
||||
gs_shader_get_param_info(param->sparam, &info);
|
||||
if (info.type == GS_SHADER_PARAM_TEXTURE)
|
||||
gs_shader_set_texture(param->sparam, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_technique_end_pass(gs_technique_t *tech)
|
||||
{
|
||||
if (!tech) return;
|
||||
|
||||
struct gs_effect_pass *pass = tech->effect->cur_pass;
|
||||
if (!pass)
|
||||
return;
|
||||
|
||||
clear_tex_params(&pass->vertshader_params.da);
|
||||
clear_tex_params(&pass->pixelshader_params.da);
|
||||
tech->effect->cur_pass = NULL;
|
||||
}
|
||||
|
||||
size_t gs_effect_get_num_params(const gs_effect_t *effect)
|
||||
{
|
||||
return effect ? effect->params.num : 0;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_effect_get_param_by_idx(const gs_effect_t *effect, size_t param)
|
||||
{
|
||||
if (!effect) return NULL;
|
||||
|
||||
struct gs_effect_param *params = effect->params.array;
|
||||
if (param >= effect->params.num)
|
||||
return NULL;
|
||||
|
||||
return params+param;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect,
|
||||
const char *name)
|
||||
{
|
||||
if (!effect) return NULL;
|
||||
|
||||
struct gs_effect_param *params = effect->params.array;
|
||||
|
||||
for (size_t i = 0; i < effect->params.num; i++) {
|
||||
struct gs_effect_param *param = params+i;
|
||||
|
||||
if (strcmp(param->name, name) == 0)
|
||||
return param;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_effect_get_viewproj_matrix(const gs_effect_t *effect)
|
||||
{
|
||||
return effect ? effect->view_proj : NULL;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_effect_get_world_matrix(const gs_effect_t *effect)
|
||||
{
|
||||
return effect ? effect->world : NULL;
|
||||
}
|
||||
|
||||
void gs_effect_get_param_info(const gs_eparam_t *param,
|
||||
struct gs_effect_param_info *info)
|
||||
{
|
||||
if (!param)
|
||||
return;
|
||||
|
||||
info->name = param->name;
|
||||
info->type = param->type;
|
||||
}
|
||||
|
||||
static inline void effect_setval_inline(gs_eparam_t *param,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
bool size_changed;
|
||||
|
||||
if (!param) {
|
||||
blog(LOG_ERROR, "effect_setval_inline: invalid param");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
blog(LOG_ERROR, "effect_setval_inline: invalid data");
|
||||
return;
|
||||
}
|
||||
|
||||
size_changed = param->cur_val.num != size;
|
||||
|
||||
if (size_changed)
|
||||
da_resize(param->cur_val, size);
|
||||
|
||||
if (size_changed || memcmp(param->cur_val.array, data, size) != 0) {
|
||||
memcpy(param->cur_val.array, data, size);
|
||||
param->changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void gs_effect_set_bool(gs_eparam_t *param, bool val)
|
||||
{
|
||||
int b_val = (int)val;
|
||||
effect_setval_inline(param, &b_val, sizeof(int));
|
||||
}
|
||||
|
||||
void gs_effect_set_float(gs_eparam_t *param, float val)
|
||||
{
|
||||
effect_setval_inline(param, &val, sizeof(float));
|
||||
}
|
||||
|
||||
void gs_effect_set_int(gs_eparam_t *param, int val)
|
||||
{
|
||||
effect_setval_inline(param, &val, sizeof(int));
|
||||
}
|
||||
|
||||
void gs_effect_set_matrix4(gs_eparam_t *param, const struct matrix4 *val)
|
||||
{
|
||||
effect_setval_inline(param, val, sizeof(struct matrix4));
|
||||
}
|
||||
|
||||
void gs_effect_set_vec2(gs_eparam_t *param, const struct vec2 *val)
|
||||
{
|
||||
effect_setval_inline(param, val, sizeof(struct vec2));
|
||||
}
|
||||
|
||||
void gs_effect_set_vec3(gs_eparam_t *param, const struct vec3 *val)
|
||||
{
|
||||
effect_setval_inline(param, val, sizeof(float) * 3);
|
||||
}
|
||||
|
||||
void gs_effect_set_vec4(gs_eparam_t *param, const struct vec4 *val)
|
||||
{
|
||||
effect_setval_inline(param, val, sizeof(struct vec4));
|
||||
}
|
||||
|
||||
void gs_effect_set_texture(gs_eparam_t *param, gs_texture_t *val)
|
||||
{
|
||||
effect_setval_inline(param, &val, sizeof(gs_texture_t*));
|
||||
}
|
||||
|
||||
void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size)
|
||||
{
|
||||
effect_setval_inline(param, val, size);
|
||||
}
|
||||
|
||||
void gs_effect_set_default(gs_eparam_t *param)
|
||||
{
|
||||
effect_setval_inline(param, param->default_val.array,
|
||||
param->default_val.num);
|
||||
}
|
||||
187
libobs/graphics/effect.h
Normal file
187
libobs/graphics/effect.h
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect-parser.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Effects introduce a means of bundling together shader text into one
|
||||
* file with shared functions and parameters. This is done because often
|
||||
* shaders must be duplicated when you need to alter minor aspects of the code
|
||||
* that cannot be done via constants. Effects allow developers to easily
|
||||
* switch shaders and set constants that can be used between shaders.
|
||||
*
|
||||
* Effects are built via the effect parser, and shaders are automatically
|
||||
* generated for each technique's pass.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
enum effect_section {
|
||||
EFFECT_PARAM,
|
||||
EFFECT_TECHNIQUE,
|
||||
EFFECT_SAMPLER,
|
||||
EFFECT_PASS
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct gs_effect_param {
|
||||
char *name;
|
||||
enum effect_section section;
|
||||
|
||||
enum gs_shader_param_type type;
|
||||
|
||||
bool changed;
|
||||
DARRAY(uint8_t) cur_val;
|
||||
DARRAY(uint8_t) default_val;
|
||||
|
||||
gs_effect_t *effect;
|
||||
|
||||
/*char *full_name;
|
||||
float scroller_min, scroller_max, scroller_inc, scroller_mul;*/
|
||||
};
|
||||
|
||||
static inline void effect_param_init(struct gs_effect_param *param)
|
||||
{
|
||||
memset(param, 0, sizeof(struct gs_effect_param));
|
||||
}
|
||||
|
||||
static inline void effect_param_free(struct gs_effect_param *param)
|
||||
{
|
||||
bfree(param->name);
|
||||
//bfree(param->full_name);
|
||||
da_free(param->cur_val);
|
||||
da_free(param->default_val);
|
||||
}
|
||||
|
||||
EXPORT void effect_param_parse_property(gs_eparam_t *param,
|
||||
const char *property);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct pass_shaderparam {
|
||||
struct gs_effect_param *eparam;
|
||||
gs_sparam_t *sparam;
|
||||
};
|
||||
|
||||
struct gs_effect_pass {
|
||||
char *name;
|
||||
enum effect_section section;
|
||||
|
||||
gs_shader_t *vertshader;
|
||||
gs_shader_t *pixelshader;
|
||||
DARRAY(struct pass_shaderparam) vertshader_params;
|
||||
DARRAY(struct pass_shaderparam) pixelshader_params;
|
||||
};
|
||||
|
||||
static inline void effect_pass_init(struct gs_effect_pass *pass)
|
||||
{
|
||||
memset(pass, 0, sizeof(struct gs_effect_pass));
|
||||
}
|
||||
|
||||
static inline void effect_pass_free(struct gs_effect_pass *pass)
|
||||
{
|
||||
bfree(pass->name);
|
||||
da_free(pass->vertshader_params);
|
||||
da_free(pass->pixelshader_params);
|
||||
gs_shader_destroy(pass->vertshader);
|
||||
gs_shader_destroy(pass->pixelshader);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct gs_effect_technique {
|
||||
char *name;
|
||||
enum effect_section section;
|
||||
struct gs_effect *effect;
|
||||
|
||||
DARRAY(struct gs_effect_pass) passes;
|
||||
};
|
||||
|
||||
static inline void effect_technique_init(struct gs_effect_technique *t)
|
||||
{
|
||||
memset(t, 0, sizeof(struct gs_effect_technique));
|
||||
}
|
||||
|
||||
static inline void effect_technique_free(struct gs_effect_technique *t)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < t->passes.num; i++)
|
||||
effect_pass_free(t->passes.array+i);
|
||||
da_free(t->passes);
|
||||
bfree(t->name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct gs_effect {
|
||||
bool processing;
|
||||
bool cached;
|
||||
char *effect_path, *effect_dir;
|
||||
|
||||
DARRAY(struct gs_effect_param) params;
|
||||
DARRAY(struct gs_effect_technique) techniques;
|
||||
|
||||
struct gs_effect_technique *cur_technique;
|
||||
struct gs_effect_pass *cur_pass;
|
||||
|
||||
gs_eparam_t *view_proj, *world, *scale;
|
||||
graphics_t *graphics;
|
||||
|
||||
struct gs_effect *next;
|
||||
|
||||
size_t loop_pass;
|
||||
bool looping;
|
||||
};
|
||||
|
||||
static inline void effect_init(gs_effect_t *effect)
|
||||
{
|
||||
memset(effect, 0, sizeof(struct gs_effect));
|
||||
}
|
||||
|
||||
static inline void effect_free(gs_effect_t *effect)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < effect->params.num; i++)
|
||||
effect_param_free(effect->params.array+i);
|
||||
for (i = 0; i < effect->techniques.num; i++)
|
||||
effect_technique_free(effect->techniques.array+i);
|
||||
|
||||
da_free(effect->params);
|
||||
da_free(effect->techniques);
|
||||
|
||||
bfree(effect->effect_path);
|
||||
bfree(effect->effect_dir);
|
||||
effect->effect_path = NULL;
|
||||
effect->effect_dir = NULL;
|
||||
}
|
||||
|
||||
EXPORT void effect_upload_params(gs_effect_t *effect, bool changed_only);
|
||||
EXPORT void effect_upload_shader_params(gs_effect_t *effect,
|
||||
gs_shader_t *shader, struct darray *pass_params,
|
||||
bool changed_only);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
227
libobs/graphics/graphics-ffmpeg.c
Normal file
227
libobs/graphics/graphics-ffmpeg.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#include "graphics.h"
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#include "../obs-ffmpeg-compat.h"
|
||||
|
||||
struct ffmpeg_image {
|
||||
const char *file;
|
||||
AVFormatContext *fmt_ctx;
|
||||
AVCodecContext *decoder_ctx;
|
||||
AVCodec *decoder;
|
||||
AVStream *stream;
|
||||
int stream_idx;
|
||||
|
||||
int cx, cy;
|
||||
enum AVPixelFormat format;
|
||||
};
|
||||
|
||||
static bool ffmpeg_image_open_decoder_context(struct ffmpeg_image *info)
|
||||
{
|
||||
int ret = av_find_best_stream(info->fmt_ctx, AVMEDIA_TYPE_VIDEO,
|
||||
-1, 1, NULL, 0);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Couldn't find video stream in file '%s': %s",
|
||||
info->file, av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
info->stream_idx = ret;
|
||||
info->stream = info->fmt_ctx->streams[ret];
|
||||
info->decoder_ctx = info->stream->codec;
|
||||
info->decoder = avcodec_find_decoder(info->decoder_ctx->codec_id);
|
||||
|
||||
if (!info->decoder) {
|
||||
blog(LOG_WARNING, "Failed to find decoder for file '%s'",
|
||||
info->file);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = avcodec_open2(info->decoder_ctx, info->decoder, NULL);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Failed to open video codec for file '%s': "
|
||||
"%s", info->file, av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ffmpeg_image_free(struct ffmpeg_image *info)
|
||||
{
|
||||
avcodec_close(info->decoder_ctx);
|
||||
avformat_close_input(&info->fmt_ctx);
|
||||
}
|
||||
|
||||
static bool ffmpeg_image_init(struct ffmpeg_image *info, const char *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!file || !*file)
|
||||
return false;
|
||||
|
||||
memset(info, 0, sizeof(struct ffmpeg_image));
|
||||
info->file = file;
|
||||
info->stream_idx = -1;
|
||||
|
||||
ret = avformat_open_input(&info->fmt_ctx, file, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Failed to open file '%s': %s",
|
||||
info->file, av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = avformat_find_stream_info(info->fmt_ctx, NULL);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Could not find stream info for file '%s':"
|
||||
" %s", info->file, av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!ffmpeg_image_open_decoder_context(info))
|
||||
goto fail;
|
||||
|
||||
info->cx = info->decoder_ctx->width;
|
||||
info->cy = info->decoder_ctx->height;
|
||||
info->format = info->decoder_ctx->pix_fmt;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
ffmpeg_image_free(info);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ffmpeg_image_reformat_frame(struct ffmpeg_image *info,
|
||||
AVFrame *frame, uint8_t *out, int linesize)
|
||||
{
|
||||
struct SwsContext *sws_ctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (info->format == AV_PIX_FMT_RGBA ||
|
||||
info->format == AV_PIX_FMT_BGRA ||
|
||||
info->format == AV_PIX_FMT_BGR0) {
|
||||
|
||||
if (linesize != frame->linesize[0]) {
|
||||
int min_line = linesize < frame->linesize[0] ?
|
||||
linesize : frame->linesize[0];
|
||||
|
||||
for (int y = 0; y < info->cy; y++)
|
||||
memcpy(out + y * linesize,
|
||||
frame->data[0] + y * frame->linesize[0],
|
||||
min_line);
|
||||
} else {
|
||||
memcpy(out, frame->data[0], linesize * info->cy);
|
||||
}
|
||||
|
||||
} else {
|
||||
sws_ctx = sws_getContext(info->cx, info->cy, info->format,
|
||||
info->cx, info->cy, AV_PIX_FMT_BGRA,
|
||||
SWS_POINT, NULL, NULL, NULL);
|
||||
if (!sws_ctx) {
|
||||
blog(LOG_WARNING, "Failed to create scale context "
|
||||
"for '%s'", info->file);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = sws_scale(sws_ctx, (const uint8_t *const*)frame->data,
|
||||
frame->linesize, 0, info->cy, &out, &linesize);
|
||||
sws_freeContext(sws_ctx);
|
||||
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "sws_scale failed for '%s': %s",
|
||||
info->file, av_err2str(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
info->format = AV_PIX_FMT_BGRA;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ffmpeg_image_decode(struct ffmpeg_image *info, uint8_t *out,
|
||||
int linesize)
|
||||
{
|
||||
AVPacket packet = {0};
|
||||
bool success = false;
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
int got_frame = 0;
|
||||
int ret;
|
||||
|
||||
if (!frame) {
|
||||
blog(LOG_WARNING, "Failed to create frame data for '%s'",
|
||||
info->file);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = av_read_frame(info->fmt_ctx, &packet);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Failed to read image frame from '%s': %s",
|
||||
info->file, av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (!got_frame) {
|
||||
ret = avcodec_decode_video2(info->decoder_ctx, frame,
|
||||
&got_frame, &packet);
|
||||
if (ret < 0) {
|
||||
blog(LOG_WARNING, "Failed to decode frame for '%s': %s",
|
||||
info->file, av_err2str(ret));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
success = ffmpeg_image_reformat_frame(info, frame, out, linesize);
|
||||
|
||||
fail:
|
||||
av_free_packet(&packet);
|
||||
av_frame_free(&frame);
|
||||
return success;
|
||||
}
|
||||
|
||||
void gs_init_image_deps(void)
|
||||
{
|
||||
av_register_all();
|
||||
}
|
||||
|
||||
void gs_free_image_deps(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline enum gs_color_format convert_format(enum AVPixelFormat format)
|
||||
{
|
||||
switch ((int)format) {
|
||||
case AV_PIX_FMT_RGBA: return GS_RGBA;
|
||||
case AV_PIX_FMT_BGRA: return GS_BGRA;
|
||||
case AV_PIX_FMT_BGR0: return GS_BGRX;
|
||||
}
|
||||
|
||||
return GS_BGRX;
|
||||
}
|
||||
|
||||
uint8_t *gs_create_texture_file_data(const char *file,
|
||||
enum gs_color_format *format,
|
||||
uint32_t *cx_out, uint32_t *cy_out)
|
||||
{
|
||||
struct ffmpeg_image image;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
if (ffmpeg_image_init(&image, file)) {
|
||||
data = bmalloc(image.cx * image.cy * 4);
|
||||
|
||||
if (ffmpeg_image_decode(&image, data, image.cx * 4)) {
|
||||
*format = convert_format(image.format);
|
||||
*cx_out = (uint32_t)image.cx;
|
||||
*cy_out = (uint32_t)image.cy;
|
||||
} else {
|
||||
bfree(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
ffmpeg_image_free(&image);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
192
libobs/graphics/graphics-imports.c
Normal file
192
libobs/graphics/graphics-imports.c
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "../util/base.h"
|
||||
#include "../util/dstr.h"
|
||||
#include "../util/platform.h"
|
||||
#include "graphics-internal.h"
|
||||
|
||||
#define GRAPHICS_IMPORT(func) \
|
||||
do { \
|
||||
exports->func = os_dlsym(module, #func); \
|
||||
if (!exports->func) { \
|
||||
success = false; \
|
||||
blog(LOG_ERROR, "Could not load function '%s' from " \
|
||||
"module '%s'", #func, module_name); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define GRAPHICS_IMPORT_OPTIONAL(func) \
|
||||
do { \
|
||||
exports->func = os_dlsym(module, #func); \
|
||||
} while (false)
|
||||
|
||||
bool load_graphics_imports(struct gs_exports *exports, void *module,
|
||||
const char *module_name)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
GRAPHICS_IMPORT(device_get_name);
|
||||
GRAPHICS_IMPORT(device_get_type);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_enum_adapters);
|
||||
GRAPHICS_IMPORT(device_preprocessor_name);
|
||||
GRAPHICS_IMPORT(device_create);
|
||||
GRAPHICS_IMPORT(device_destroy);
|
||||
GRAPHICS_IMPORT(device_enter_context);
|
||||
GRAPHICS_IMPORT(device_leave_context);
|
||||
GRAPHICS_IMPORT(device_swapchain_create);
|
||||
GRAPHICS_IMPORT(device_resize);
|
||||
GRAPHICS_IMPORT(device_get_size);
|
||||
GRAPHICS_IMPORT(device_get_width);
|
||||
GRAPHICS_IMPORT(device_get_height);
|
||||
GRAPHICS_IMPORT(device_texture_create);
|
||||
GRAPHICS_IMPORT(device_cubetexture_create);
|
||||
GRAPHICS_IMPORT(device_voltexture_create);
|
||||
GRAPHICS_IMPORT(device_zstencil_create);
|
||||
GRAPHICS_IMPORT(device_stagesurface_create);
|
||||
GRAPHICS_IMPORT(device_samplerstate_create);
|
||||
GRAPHICS_IMPORT(device_vertexshader_create);
|
||||
GRAPHICS_IMPORT(device_pixelshader_create);
|
||||
GRAPHICS_IMPORT(device_vertexbuffer_create);
|
||||
GRAPHICS_IMPORT(device_indexbuffer_create);
|
||||
GRAPHICS_IMPORT(device_get_texture_type);
|
||||
GRAPHICS_IMPORT(device_load_vertexbuffer);
|
||||
GRAPHICS_IMPORT(device_load_indexbuffer);
|
||||
GRAPHICS_IMPORT(device_load_texture);
|
||||
GRAPHICS_IMPORT(device_load_samplerstate);
|
||||
GRAPHICS_IMPORT(device_load_vertexshader);
|
||||
GRAPHICS_IMPORT(device_load_pixelshader);
|
||||
GRAPHICS_IMPORT(device_load_default_samplerstate);
|
||||
GRAPHICS_IMPORT(device_get_vertex_shader);
|
||||
GRAPHICS_IMPORT(device_get_pixel_shader);
|
||||
GRAPHICS_IMPORT(device_get_render_target);
|
||||
GRAPHICS_IMPORT(device_get_zstencil_target);
|
||||
GRAPHICS_IMPORT(device_set_render_target);
|
||||
GRAPHICS_IMPORT(device_set_cube_render_target);
|
||||
GRAPHICS_IMPORT(device_copy_texture_region);
|
||||
GRAPHICS_IMPORT(device_copy_texture);
|
||||
GRAPHICS_IMPORT(device_stage_texture);
|
||||
GRAPHICS_IMPORT(device_begin_scene);
|
||||
GRAPHICS_IMPORT(device_draw);
|
||||
GRAPHICS_IMPORT(device_load_swapchain);
|
||||
GRAPHICS_IMPORT(device_end_scene);
|
||||
GRAPHICS_IMPORT(device_clear);
|
||||
GRAPHICS_IMPORT(device_present);
|
||||
GRAPHICS_IMPORT(device_flush);
|
||||
GRAPHICS_IMPORT(device_set_cull_mode);
|
||||
GRAPHICS_IMPORT(device_get_cull_mode);
|
||||
GRAPHICS_IMPORT(device_enable_blending);
|
||||
GRAPHICS_IMPORT(device_enable_depth_test);
|
||||
GRAPHICS_IMPORT(device_enable_stencil_test);
|
||||
GRAPHICS_IMPORT(device_enable_stencil_write);
|
||||
GRAPHICS_IMPORT(device_enable_color);
|
||||
GRAPHICS_IMPORT(device_blend_function);
|
||||
GRAPHICS_IMPORT(device_blend_function_separate);
|
||||
GRAPHICS_IMPORT(device_depth_function);
|
||||
GRAPHICS_IMPORT(device_stencil_function);
|
||||
GRAPHICS_IMPORT(device_stencil_op);
|
||||
GRAPHICS_IMPORT(device_set_viewport);
|
||||
GRAPHICS_IMPORT(device_get_viewport);
|
||||
GRAPHICS_IMPORT(device_set_scissor_rect);
|
||||
GRAPHICS_IMPORT(device_ortho);
|
||||
GRAPHICS_IMPORT(device_frustum);
|
||||
GRAPHICS_IMPORT(device_projection_push);
|
||||
GRAPHICS_IMPORT(device_projection_pop);
|
||||
|
||||
GRAPHICS_IMPORT(gs_swapchain_destroy);
|
||||
|
||||
GRAPHICS_IMPORT(gs_texture_destroy);
|
||||
GRAPHICS_IMPORT(gs_texture_get_width);
|
||||
GRAPHICS_IMPORT(gs_texture_get_height);
|
||||
GRAPHICS_IMPORT(gs_texture_get_color_format);
|
||||
GRAPHICS_IMPORT(gs_texture_map);
|
||||
GRAPHICS_IMPORT(gs_texture_unmap);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_is_rect);
|
||||
GRAPHICS_IMPORT(gs_texture_get_obj);
|
||||
|
||||
GRAPHICS_IMPORT(gs_cubetexture_destroy);
|
||||
GRAPHICS_IMPORT(gs_cubetexture_get_size);
|
||||
GRAPHICS_IMPORT(gs_cubetexture_get_color_format);
|
||||
|
||||
GRAPHICS_IMPORT(gs_voltexture_destroy);
|
||||
GRAPHICS_IMPORT(gs_voltexture_get_width);
|
||||
GRAPHICS_IMPORT(gs_voltexture_get_height);
|
||||
GRAPHICS_IMPORT(gs_voltexture_get_depth);
|
||||
GRAPHICS_IMPORT(gs_voltexture_get_color_format);
|
||||
|
||||
GRAPHICS_IMPORT(gs_stagesurface_destroy);
|
||||
GRAPHICS_IMPORT(gs_stagesurface_get_width);
|
||||
GRAPHICS_IMPORT(gs_stagesurface_get_height);
|
||||
GRAPHICS_IMPORT(gs_stagesurface_get_color_format);
|
||||
GRAPHICS_IMPORT(gs_stagesurface_map);
|
||||
GRAPHICS_IMPORT(gs_stagesurface_unmap);
|
||||
|
||||
GRAPHICS_IMPORT(gs_zstencil_destroy);
|
||||
|
||||
GRAPHICS_IMPORT(gs_samplerstate_destroy);
|
||||
|
||||
GRAPHICS_IMPORT(gs_vertexbuffer_destroy);
|
||||
GRAPHICS_IMPORT(gs_vertexbuffer_flush);
|
||||
GRAPHICS_IMPORT(gs_vertexbuffer_get_data);
|
||||
|
||||
GRAPHICS_IMPORT(gs_indexbuffer_destroy);
|
||||
GRAPHICS_IMPORT(gs_indexbuffer_flush);
|
||||
GRAPHICS_IMPORT(gs_indexbuffer_get_data);
|
||||
GRAPHICS_IMPORT(gs_indexbuffer_get_num_indices);
|
||||
GRAPHICS_IMPORT(gs_indexbuffer_get_type);
|
||||
|
||||
GRAPHICS_IMPORT(gs_shader_destroy);
|
||||
GRAPHICS_IMPORT(gs_shader_get_num_params);
|
||||
GRAPHICS_IMPORT(gs_shader_get_param_by_idx);
|
||||
GRAPHICS_IMPORT(gs_shader_get_param_by_name);
|
||||
GRAPHICS_IMPORT(gs_shader_get_viewproj_matrix);
|
||||
GRAPHICS_IMPORT(gs_shader_get_world_matrix);
|
||||
GRAPHICS_IMPORT(gs_shader_get_param_info);
|
||||
GRAPHICS_IMPORT(gs_shader_set_bool);
|
||||
GRAPHICS_IMPORT(gs_shader_set_float);
|
||||
GRAPHICS_IMPORT(gs_shader_set_int);
|
||||
GRAPHICS_IMPORT(gs_shader_set_matrix3);
|
||||
GRAPHICS_IMPORT(gs_shader_set_matrix4);
|
||||
GRAPHICS_IMPORT(gs_shader_set_vec2);
|
||||
GRAPHICS_IMPORT(gs_shader_set_vec3);
|
||||
GRAPHICS_IMPORT(gs_shader_set_vec4);
|
||||
GRAPHICS_IMPORT(gs_shader_set_texture);
|
||||
GRAPHICS_IMPORT(gs_shader_set_val);
|
||||
GRAPHICS_IMPORT(gs_shader_set_default);
|
||||
|
||||
/* OSX/Cocoa specific functions */
|
||||
#ifdef __APPLE__
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_create_from_iosurface);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_rebind_iosurface);
|
||||
|
||||
/* win32 specific functions */
|
||||
#elif _WIN32
|
||||
GRAPHICS_IMPORT(device_gdi_texture_available);
|
||||
GRAPHICS_IMPORT(device_shared_texture_available);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_get_duplicator_monitor_info);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_duplicator_create);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_destroy);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_update_frame);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_duplicator_get_texture);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_create_gdi);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_get_dc);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_release_dc);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_open_shared);
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
300
libobs/graphics/graphics-internal.h
Normal file
300
libobs/graphics/graphics-internal.h
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/threading.h"
|
||||
#include "../util/darray.h"
|
||||
#include "graphics.h"
|
||||
#include "matrix3.h"
|
||||
#include "matrix4.h"
|
||||
|
||||
struct gs_exports {
|
||||
const char *(*device_get_name)(void);
|
||||
int (*device_get_type)(void);
|
||||
bool (*device_enum_adapters)(
|
||||
bool (*callback)(void*, const char*, uint32_t),
|
||||
void*);
|
||||
const char *(*device_preprocessor_name)(void);
|
||||
int (*device_create)(gs_device_t **device, uint32_t adapter);
|
||||
void (*device_destroy)(gs_device_t *device);
|
||||
void (*device_enter_context)(gs_device_t *device);
|
||||
void (*device_leave_context)(gs_device_t *device);
|
||||
gs_swapchain_t *(*device_swapchain_create)(gs_device_t *device,
|
||||
const struct gs_init_data *data);
|
||||
void (*device_resize)(gs_device_t *device, uint32_t x, uint32_t y);
|
||||
void (*device_get_size)(const gs_device_t *device,
|
||||
uint32_t *x, uint32_t *y);
|
||||
uint32_t (*device_get_width)(const gs_device_t *device);
|
||||
uint32_t (*device_get_height)(const gs_device_t *device);
|
||||
gs_texture_t *(*device_texture_create)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_color_format color_format, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags);
|
||||
gs_texture_t *(*device_cubetexture_create)(gs_device_t *device,
|
||||
uint32_t size, enum gs_color_format color_format,
|
||||
uint32_t levels, const uint8_t **data, uint32_t flags);
|
||||
gs_texture_t *(*device_voltexture_create)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
enum gs_color_format color_format, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags);
|
||||
gs_zstencil_t *(*device_zstencil_create)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_zstencil_format format);
|
||||
gs_stagesurf_t *(*device_stagesurface_create)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_color_format color_format);
|
||||
gs_samplerstate_t *(*device_samplerstate_create)(gs_device_t *device,
|
||||
const struct gs_sampler_info *info);
|
||||
gs_shader_t *(*device_vertexshader_create)(gs_device_t *device,
|
||||
const char *shader, const char *file,
|
||||
char **error_string);
|
||||
gs_shader_t *(*device_pixelshader_create)(gs_device_t *device,
|
||||
const char *shader, const char *file,
|
||||
char **error_string);
|
||||
gs_vertbuffer_t *(*device_vertexbuffer_create)(gs_device_t *device,
|
||||
struct gs_vb_data *data, uint32_t flags);
|
||||
gs_indexbuffer_t *(*device_indexbuffer_create)(gs_device_t *device,
|
||||
enum gs_index_type type, void *indices, size_t num,
|
||||
uint32_t flags);
|
||||
enum gs_texture_type (*device_get_texture_type)(
|
||||
const gs_texture_t *texture);
|
||||
void (*device_load_vertexbuffer)(gs_device_t *device,
|
||||
gs_vertbuffer_t *vertbuffer);
|
||||
void (*device_load_indexbuffer)(gs_device_t *device,
|
||||
gs_indexbuffer_t *indexbuffer);
|
||||
void (*device_load_texture)(gs_device_t *device, gs_texture_t *tex,
|
||||
int unit);
|
||||
void (*device_load_samplerstate)(gs_device_t *device,
|
||||
gs_samplerstate_t *samplerstate, int unit);
|
||||
void (*device_load_vertexshader)(gs_device_t *device,
|
||||
gs_shader_t *vertshader);
|
||||
void (*device_load_pixelshader)(gs_device_t *device,
|
||||
gs_shader_t *pixelshader);
|
||||
void (*device_load_default_samplerstate)(gs_device_t *device,
|
||||
bool b_3d, int unit);
|
||||
gs_shader_t *(*device_get_vertex_shader)(const gs_device_t *device);
|
||||
gs_shader_t *(*device_get_pixel_shader)(const gs_device_t *device);
|
||||
gs_texture_t *(*device_get_render_target)(const gs_device_t *device);
|
||||
gs_zstencil_t *(*device_get_zstencil_target)(const gs_device_t *device);
|
||||
void (*device_set_render_target)(gs_device_t *device, gs_texture_t *tex,
|
||||
gs_zstencil_t *zstencil);
|
||||
void (*device_set_cube_render_target)(gs_device_t *device,
|
||||
gs_texture_t *cubetex, int side, gs_zstencil_t *zstencil);
|
||||
void (*device_copy_texture)(gs_device_t *device, gs_texture_t *dst,
|
||||
gs_texture_t *src);
|
||||
void (*device_copy_texture_region)(gs_device_t *device,
|
||||
gs_texture_t *dst, uint32_t dst_x, uint32_t dst_y,
|
||||
gs_texture_t *src, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
void (*device_stage_texture)(gs_device_t *device, gs_stagesurf_t *dst,
|
||||
gs_texture_t *src);
|
||||
void (*device_begin_scene)(gs_device_t *device);
|
||||
void (*device_draw)(gs_device_t *device, enum gs_draw_mode draw_mode,
|
||||
uint32_t start_vert, uint32_t num_verts);
|
||||
void (*device_end_scene)(gs_device_t *device);
|
||||
void (*device_load_swapchain)(gs_device_t *device,
|
||||
gs_swapchain_t *swaphchain);
|
||||
void (*device_clear)(gs_device_t *device, uint32_t clear_flags,
|
||||
const struct vec4 *color, float depth, uint8_t stencil);
|
||||
void (*device_present)(gs_device_t *device);
|
||||
void (*device_flush)(gs_device_t *device);
|
||||
void (*device_set_cull_mode)(gs_device_t *device,
|
||||
enum gs_cull_mode mode);
|
||||
enum gs_cull_mode (*device_get_cull_mode)(const gs_device_t *device);
|
||||
void (*device_enable_blending)(gs_device_t *device, bool enable);
|
||||
void (*device_enable_depth_test)(gs_device_t *device, bool enable);
|
||||
void (*device_enable_stencil_test)(gs_device_t *device, bool enable);
|
||||
void (*device_enable_stencil_write)(gs_device_t *device, bool enable);
|
||||
void (*device_enable_color)(gs_device_t *device, bool red, bool green,
|
||||
bool blue, bool alpha);
|
||||
void (*device_blend_function)(gs_device_t *device,
|
||||
enum gs_blend_type src, enum gs_blend_type dest);
|
||||
void (*device_blend_function_separate)(gs_device_t *device,
|
||||
enum gs_blend_type src_c, enum gs_blend_type dest_c,
|
||||
enum gs_blend_type src_a, enum gs_blend_type dest_a);
|
||||
void (*device_depth_function)(gs_device_t *device,
|
||||
enum gs_depth_test test);
|
||||
void (*device_stencil_function)(gs_device_t *device,
|
||||
enum gs_stencil_side side, enum gs_depth_test test);
|
||||
void (*device_stencil_op)(gs_device_t *device,
|
||||
enum gs_stencil_side side,
|
||||
enum gs_stencil_op_type fail,
|
||||
enum gs_stencil_op_type zfail,
|
||||
enum gs_stencil_op_type zpass);
|
||||
void (*device_set_viewport)(gs_device_t *device, int x, int y,
|
||||
int width, int height);
|
||||
void (*device_get_viewport)(const gs_device_t *device,
|
||||
struct gs_rect *rect);
|
||||
void (*device_set_scissor_rect)(gs_device_t *device,
|
||||
const struct gs_rect *rect);
|
||||
void (*device_ortho)(gs_device_t *device, float left, float right,
|
||||
float top, float bottom, float znear, float zfar);
|
||||
void (*device_frustum)(gs_device_t *device, float left, float right,
|
||||
float top, float bottom, float znear, float zfar);
|
||||
void (*device_projection_push)(gs_device_t *device);
|
||||
void (*device_projection_pop)(gs_device_t *device);
|
||||
|
||||
void (*gs_swapchain_destroy)(gs_swapchain_t *swapchain);
|
||||
|
||||
void (*gs_texture_destroy)(gs_texture_t *tex);
|
||||
uint32_t (*gs_texture_get_width)(const gs_texture_t *tex);
|
||||
uint32_t (*gs_texture_get_height)(const gs_texture_t *tex);
|
||||
enum gs_color_format (*gs_texture_get_color_format)(
|
||||
const gs_texture_t *tex);
|
||||
bool (*gs_texture_map)(gs_texture_t *tex, uint8_t **ptr,
|
||||
uint32_t *linesize);
|
||||
void (*gs_texture_unmap)(gs_texture_t *tex);
|
||||
bool (*gs_texture_is_rect)(const gs_texture_t *tex);
|
||||
void *(*gs_texture_get_obj)(const gs_texture_t *tex);
|
||||
|
||||
void (*gs_cubetexture_destroy)(gs_texture_t *cubetex);
|
||||
uint32_t (*gs_cubetexture_get_size)(const gs_texture_t *cubetex);
|
||||
enum gs_color_format (*gs_cubetexture_get_color_format)(
|
||||
const gs_texture_t *cubetex);
|
||||
|
||||
void (*gs_voltexture_destroy)(gs_texture_t *voltex);
|
||||
uint32_t (*gs_voltexture_get_width)(const gs_texture_t *voltex);
|
||||
uint32_t (*gs_voltexture_get_height)(const gs_texture_t *voltex);
|
||||
uint32_t (*gs_voltexture_get_depth)(const gs_texture_t *voltex);
|
||||
enum gs_color_format (*gs_voltexture_get_color_format)(
|
||||
const gs_texture_t *voltex);
|
||||
|
||||
void (*gs_stagesurface_destroy)(gs_stagesurf_t *stagesurf);
|
||||
uint32_t (*gs_stagesurface_get_width)(const gs_stagesurf_t *stagesurf);
|
||||
uint32_t (*gs_stagesurface_get_height)(const gs_stagesurf_t *stagesurf);
|
||||
enum gs_color_format (*gs_stagesurface_get_color_format)(
|
||||
const gs_stagesurf_t *stagesurf);
|
||||
bool (*gs_stagesurface_map)(gs_stagesurf_t *stagesurf,
|
||||
uint8_t **data, uint32_t *linesize);
|
||||
void (*gs_stagesurface_unmap)(gs_stagesurf_t *stagesurf);
|
||||
|
||||
void (*gs_zstencil_destroy)(gs_zstencil_t *zstencil);
|
||||
|
||||
void (*gs_samplerstate_destroy)(gs_samplerstate_t *samplerstate);
|
||||
|
||||
void (*gs_vertexbuffer_destroy)(gs_vertbuffer_t *vertbuffer);
|
||||
void (*gs_vertexbuffer_flush)(gs_vertbuffer_t *vertbuffer);
|
||||
struct gs_vb_data *(*gs_vertexbuffer_get_data)(
|
||||
const gs_vertbuffer_t *vertbuffer);
|
||||
|
||||
void (*gs_indexbuffer_destroy)(gs_indexbuffer_t *indexbuffer);
|
||||
void (*gs_indexbuffer_flush)(gs_indexbuffer_t *indexbuffer);
|
||||
void *(*gs_indexbuffer_get_data)(const gs_indexbuffer_t *indexbuffer);
|
||||
size_t (*gs_indexbuffer_get_num_indices)(
|
||||
const gs_indexbuffer_t *indexbuffer);
|
||||
enum gs_index_type (*gs_indexbuffer_get_type)(
|
||||
const gs_indexbuffer_t *indexbuffer);
|
||||
|
||||
void (*gs_shader_destroy)(gs_shader_t *shader);
|
||||
int (*gs_shader_get_num_params)(const gs_shader_t *shader);
|
||||
gs_sparam_t *(*gs_shader_get_param_by_idx)(gs_shader_t *shader,
|
||||
uint32_t param);
|
||||
gs_sparam_t *(*gs_shader_get_param_by_name)(gs_shader_t *shader,
|
||||
const char *name);
|
||||
gs_sparam_t *(*gs_shader_get_viewproj_matrix)(
|
||||
const gs_shader_t *shader);
|
||||
gs_sparam_t *(*gs_shader_get_world_matrix)(const gs_shader_t *shader);
|
||||
void (*gs_shader_get_param_info)(const gs_sparam_t *param,
|
||||
struct gs_shader_param_info *info);
|
||||
void (*gs_shader_set_bool)(gs_sparam_t *param, bool val);
|
||||
void (*gs_shader_set_float)(gs_sparam_t *param, float val);
|
||||
void (*gs_shader_set_int)(gs_sparam_t *param, int val);
|
||||
void (*gs_shader_set_matrix3)(gs_sparam_t *param,
|
||||
const struct matrix3 *val);
|
||||
void (*gs_shader_set_matrix4)(gs_sparam_t *param,
|
||||
const struct matrix4 *val);
|
||||
void (*gs_shader_set_vec2)(gs_sparam_t *param, const struct vec2 *val);
|
||||
void (*gs_shader_set_vec3)(gs_sparam_t *param, const struct vec3 *val);
|
||||
void (*gs_shader_set_vec4)(gs_sparam_t *param, const struct vec4 *val);
|
||||
void (*gs_shader_set_texture)(gs_sparam_t *param, gs_texture_t *val);
|
||||
void (*gs_shader_set_val)(gs_sparam_t *param, const void *val,
|
||||
size_t size);
|
||||
void (*gs_shader_set_default)(gs_sparam_t *param);
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* OSX/Cocoa specific functions */
|
||||
gs_texture_t *(*device_texture_create_from_iosurface)(gs_device_t *dev,
|
||||
void *iosurf);
|
||||
bool (*gs_texture_rebind_iosurface)(gs_texture_t *texture,
|
||||
void *iosurf);
|
||||
|
||||
#elif _WIN32
|
||||
bool (*device_gdi_texture_available)(void);
|
||||
bool (*device_shared_texture_available)(void);
|
||||
|
||||
bool (*device_get_duplicator_monitor_info)(gs_device_t *device,
|
||||
int monitor_idx, struct gs_monitor_info *monitor_info);
|
||||
|
||||
gs_duplicator_t *(*device_duplicator_create)(gs_device_t *device,
|
||||
int monitor_idx);
|
||||
void (*gs_duplicator_destroy)(gs_duplicator_t *duplicator);
|
||||
|
||||
bool (*gs_duplicator_update_frame)(gs_duplicator_t *duplicator);
|
||||
gs_texture_t *(*gs_duplicator_get_texture)(gs_duplicator_t *duplicator);
|
||||
|
||||
gs_texture_t *(*device_texture_create_gdi)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
void *(*gs_texture_get_dc)(gs_texture_t *gdi_tex);
|
||||
void (*gs_texture_release_dc)(gs_texture_t *gdi_tex);
|
||||
|
||||
gs_texture_t *(*device_texture_open_shared)(gs_device_t *device,
|
||||
uint32_t handle);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct blend_state {
|
||||
bool enabled;
|
||||
enum gs_blend_type src_c;
|
||||
enum gs_blend_type dest_c;
|
||||
enum gs_blend_type src_a;
|
||||
enum gs_blend_type dest_a;
|
||||
};
|
||||
|
||||
struct graphics_subsystem {
|
||||
void *module;
|
||||
gs_device_t *device;
|
||||
struct gs_exports exports;
|
||||
|
||||
DARRAY(struct gs_rect) viewport_stack;
|
||||
|
||||
DARRAY(struct matrix4) matrix_stack;
|
||||
size_t cur_matrix;
|
||||
|
||||
struct matrix4 projection;
|
||||
struct gs_effect *cur_effect;
|
||||
|
||||
gs_vertbuffer_t *sprite_buffer;
|
||||
|
||||
bool using_immediate;
|
||||
struct gs_vb_data *vbd;
|
||||
gs_vertbuffer_t *immediate_vertbuffer;
|
||||
DARRAY(struct vec3) verts;
|
||||
DARRAY(struct vec3) norms;
|
||||
DARRAY(uint32_t) colors;
|
||||
DARRAY(struct vec2) texverts[16];
|
||||
|
||||
pthread_mutex_t effect_mutex;
|
||||
struct gs_effect *first_effect;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
volatile long ref;
|
||||
|
||||
struct blend_state cur_blend_state;
|
||||
DARRAY(struct blend_state) blend_state_stack;
|
||||
};
|
||||
63
libobs/graphics/graphics-magick.c
Normal file
63
libobs/graphics/graphics-magick.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#include "graphics.h"
|
||||
|
||||
#define MAGICKCORE_QUANTUM_DEPTH 16
|
||||
#define MAGICKCORE_HDRI_ENABLE 0
|
||||
#include <magick/MagickCore.h>
|
||||
|
||||
void gs_init_image_deps()
|
||||
{
|
||||
MagickCoreGenesis(NULL, MagickTrue);
|
||||
}
|
||||
|
||||
void gs_free_image_deps()
|
||||
{
|
||||
MagickCoreTerminus();
|
||||
}
|
||||
|
||||
uint8_t *gs_create_texture_file_data(const char *file,
|
||||
enum gs_color_format *format,
|
||||
uint32_t *cx_out, uint32_t *cy_out)
|
||||
{
|
||||
uint8_t *data = NULL;
|
||||
ImageInfo *info;
|
||||
ExceptionInfo *exception;
|
||||
Image *image;
|
||||
|
||||
if (!file || !*file)
|
||||
return NULL;
|
||||
|
||||
info = CloneImageInfo(NULL);
|
||||
exception = AcquireExceptionInfo();
|
||||
|
||||
strcpy(info->filename, file);
|
||||
image = ReadImage(info, exception);
|
||||
if (image) {
|
||||
size_t cx = image->magick_columns;
|
||||
size_t cy = image->magick_rows;
|
||||
data = bmalloc(cx * cy * 4);
|
||||
|
||||
ExportImagePixels(image, 0, 0, cx, cy, "BGRA", CharPixel,
|
||||
data, exception);
|
||||
if (exception->severity != UndefinedException) {
|
||||
blog(LOG_WARNING, "magickcore warning/error getting "
|
||||
"pixels from file '%s': %s", file,
|
||||
exception->reason);
|
||||
bfree(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
*format = GS_BGRA;
|
||||
*cx_out = (uint32_t)cx;
|
||||
*cy_out = (uint32_t)cy;
|
||||
DestroyImage(image);
|
||||
|
||||
} else if (exception->severity != UndefinedException) {
|
||||
blog(LOG_WARNING, "magickcore warning/error reading file "
|
||||
"'%s': %s", file, exception->reason);
|
||||
}
|
||||
|
||||
DestroyImageInfo(info);
|
||||
DestroyExceptionInfo(exception);
|
||||
|
||||
return data;
|
||||
}
|
||||
2566
libobs/graphics/graphics.c
Normal file
2566
libobs/graphics/graphics.c
Normal file
File diff suppressed because it is too large
Load diff
808
libobs/graphics/graphics.h
Normal file
808
libobs/graphics/graphics.h
Normal file
|
|
@ -0,0 +1,808 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/bmem.h"
|
||||
#include "input.h"
|
||||
#ifdef __APPLE__
|
||||
#include <objc/objc-runtime.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is an API-independent graphics subsystem wrapper.
|
||||
*
|
||||
* This allows the use of OpenGL and different Direct3D versions through
|
||||
* one shared interface.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GS_MAX_TEXTURES 8
|
||||
|
||||
struct vec2;
|
||||
struct vec3;
|
||||
struct vec4;
|
||||
struct quat;
|
||||
struct axisang;
|
||||
struct plane;
|
||||
struct matrix3;
|
||||
struct matrix4;
|
||||
|
||||
enum gs_draw_mode {
|
||||
GS_POINTS,
|
||||
GS_LINES,
|
||||
GS_LINESTRIP,
|
||||
GS_TRIS,
|
||||
GS_TRISTRIP
|
||||
};
|
||||
|
||||
enum gs_color_format {
|
||||
GS_UNKNOWN,
|
||||
GS_A8,
|
||||
GS_R8,
|
||||
GS_RGBA,
|
||||
GS_BGRX,
|
||||
GS_BGRA,
|
||||
GS_R10G10B10A2,
|
||||
GS_RGBA16,
|
||||
GS_R16,
|
||||
GS_RGBA16F,
|
||||
GS_RGBA32F,
|
||||
GS_RG16F,
|
||||
GS_RG32F,
|
||||
GS_R16F,
|
||||
GS_R32F,
|
||||
GS_DXT1,
|
||||
GS_DXT3,
|
||||
GS_DXT5
|
||||
};
|
||||
|
||||
enum gs_zstencil_format {
|
||||
GS_ZS_NONE,
|
||||
GS_Z16,
|
||||
GS_Z24_S8,
|
||||
GS_Z32F,
|
||||
GS_Z32F_S8X24
|
||||
};
|
||||
|
||||
enum gs_index_type {
|
||||
GS_UNSIGNED_SHORT,
|
||||
GS_UNSIGNED_LONG
|
||||
};
|
||||
|
||||
enum gs_cull_mode {
|
||||
GS_BACK,
|
||||
GS_FRONT,
|
||||
GS_NEITHER
|
||||
};
|
||||
|
||||
enum gs_blend_type {
|
||||
GS_BLEND_ZERO,
|
||||
GS_BLEND_ONE,
|
||||
GS_BLEND_SRCCOLOR,
|
||||
GS_BLEND_INVSRCCOLOR,
|
||||
GS_BLEND_SRCALPHA,
|
||||
GS_BLEND_INVSRCALPHA,
|
||||
GS_BLEND_DSTCOLOR,
|
||||
GS_BLEND_INVDSTCOLOR,
|
||||
GS_BLEND_DSTALPHA,
|
||||
GS_BLEND_INVDSTALPHA,
|
||||
GS_BLEND_SRCALPHASAT
|
||||
};
|
||||
|
||||
enum gs_depth_test {
|
||||
GS_NEVER,
|
||||
GS_LESS,
|
||||
GS_LEQUAL,
|
||||
GS_EQUAL,
|
||||
GS_GEQUAL,
|
||||
GS_GREATER,
|
||||
GS_NOTEQUAL,
|
||||
GS_ALWAYS
|
||||
};
|
||||
|
||||
enum gs_stencil_side {
|
||||
GS_STENCIL_FRONT=1,
|
||||
GS_STENCIL_BACK,
|
||||
GS_STENCIL_BOTH
|
||||
};
|
||||
|
||||
enum gs_stencil_op_type {
|
||||
GS_KEEP,
|
||||
GS_ZERO,
|
||||
GS_REPLACE,
|
||||
GS_INCR,
|
||||
GS_DECR,
|
||||
GS_INVERT
|
||||
};
|
||||
|
||||
enum gs_cube_sides {
|
||||
GS_POSITIVE_X,
|
||||
GS_NEGATIVE_X,
|
||||
GS_POSITIVE_Y,
|
||||
GS_NEGATIVE_Y,
|
||||
GS_POSITIVE_Z,
|
||||
GS_NEGATIVE_Z
|
||||
};
|
||||
|
||||
enum gs_sample_filter {
|
||||
GS_FILTER_POINT,
|
||||
GS_FILTER_LINEAR,
|
||||
GS_FILTER_ANISOTROPIC,
|
||||
GS_FILTER_MIN_MAG_POINT_MIP_LINEAR,
|
||||
GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
|
||||
GS_FILTER_MIN_POINT_MAG_MIP_LINEAR,
|
||||
GS_FILTER_MIN_LINEAR_MAG_MIP_POINT,
|
||||
GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
|
||||
GS_FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
||||
};
|
||||
|
||||
enum gs_address_mode {
|
||||
GS_ADDRESS_CLAMP,
|
||||
GS_ADDRESS_WRAP,
|
||||
GS_ADDRESS_MIRROR,
|
||||
GS_ADDRESS_BORDER,
|
||||
GS_ADDRESS_MIRRORONCE
|
||||
};
|
||||
|
||||
enum gs_texture_type {
|
||||
GS_TEXTURE_2D,
|
||||
GS_TEXTURE_3D,
|
||||
GS_TEXTURE_CUBE
|
||||
};
|
||||
|
||||
struct gs_monitor_info {
|
||||
int rotation_degrees;
|
||||
long x;
|
||||
long y;
|
||||
long cx;
|
||||
long cy;
|
||||
};
|
||||
|
||||
struct gs_tvertarray {
|
||||
size_t width;
|
||||
void *array;
|
||||
};
|
||||
|
||||
struct gs_vb_data {
|
||||
size_t num;
|
||||
struct vec3 *points;
|
||||
struct vec3 *normals;
|
||||
struct vec3 *tangents;
|
||||
uint32_t *colors;
|
||||
|
||||
size_t num_tex;
|
||||
struct gs_tvertarray *tvarray;
|
||||
};
|
||||
|
||||
static inline struct gs_vb_data *gs_vbdata_create(void)
|
||||
{
|
||||
return (struct gs_vb_data*)bzalloc(sizeof(struct gs_vb_data));
|
||||
}
|
||||
|
||||
static inline void gs_vbdata_destroy(struct gs_vb_data *data)
|
||||
{
|
||||
uint32_t i;
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
bfree(data->points);
|
||||
bfree(data->normals);
|
||||
bfree(data->tangents);
|
||||
bfree(data->colors);
|
||||
for (i = 0; i < data->num_tex; i++)
|
||||
bfree(data->tvarray[i].array);
|
||||
bfree(data->tvarray);
|
||||
bfree(data);
|
||||
}
|
||||
|
||||
struct gs_sampler_info {
|
||||
enum gs_sample_filter filter;
|
||||
enum gs_address_mode address_u;
|
||||
enum gs_address_mode address_v;
|
||||
enum gs_address_mode address_w;
|
||||
int max_anisotropy;
|
||||
uint32_t border_color;
|
||||
};
|
||||
|
||||
struct gs_display_mode {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t bits;
|
||||
uint32_t freq;
|
||||
};
|
||||
|
||||
struct gs_rect {
|
||||
int x;
|
||||
int y;
|
||||
int cx;
|
||||
int cy;
|
||||
};
|
||||
|
||||
/* wrapped opaque data types */
|
||||
|
||||
struct gs_texture;
|
||||
struct gs_stage_surface;
|
||||
struct gs_zstencil_buffer;
|
||||
struct gs_vertex_buffer;
|
||||
struct gs_index_buffer;
|
||||
struct gs_sampler_state;
|
||||
struct gs_shader;
|
||||
struct gs_swap_chain;
|
||||
struct gs_texrender;
|
||||
struct gs_shader_param;
|
||||
struct gs_effect;
|
||||
struct gs_effect_technique;
|
||||
struct gs_effect_pass;
|
||||
struct gs_effect_param;
|
||||
struct gs_device;
|
||||
struct graphics_subsystem;
|
||||
|
||||
typedef struct gs_texture gs_texture_t;
|
||||
typedef struct gs_stage_surface gs_stagesurf_t;
|
||||
typedef struct gs_zstencil_buffer gs_zstencil_t;
|
||||
typedef struct gs_vertex_buffer gs_vertbuffer_t;
|
||||
typedef struct gs_index_buffer gs_indexbuffer_t;
|
||||
typedef struct gs_sampler_state gs_samplerstate_t;
|
||||
typedef struct gs_swap_chain gs_swapchain_t;
|
||||
typedef struct gs_texture_render gs_texrender_t;
|
||||
typedef struct gs_shader gs_shader_t;
|
||||
typedef struct gs_shader_param gs_sparam_t;
|
||||
typedef struct gs_effect gs_effect_t;
|
||||
typedef struct gs_effect_technique gs_technique_t;
|
||||
typedef struct gs_effect_param gs_eparam_t;
|
||||
typedef struct gs_device gs_device_t;
|
||||
typedef struct graphics_subsystem graphics_t;
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* shader functions
|
||||
* --------------------------------------------------- */
|
||||
|
||||
enum gs_shader_param_type {
|
||||
GS_SHADER_PARAM_UNKNOWN,
|
||||
GS_SHADER_PARAM_BOOL,
|
||||
GS_SHADER_PARAM_FLOAT,
|
||||
GS_SHADER_PARAM_INT,
|
||||
GS_SHADER_PARAM_STRING,
|
||||
GS_SHADER_PARAM_VEC2,
|
||||
GS_SHADER_PARAM_VEC3,
|
||||
GS_SHADER_PARAM_VEC4,
|
||||
GS_SHADER_PARAM_MATRIX4X4,
|
||||
GS_SHADER_PARAM_TEXTURE,
|
||||
};
|
||||
|
||||
struct gs_shader_param_info {
|
||||
enum gs_shader_param_type type;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
enum gs_shader_type {
|
||||
GS_SHADER_VERTEX,
|
||||
GS_SHADER_PIXEL,
|
||||
};
|
||||
|
||||
EXPORT void gs_shader_destroy(gs_shader_t *shader);
|
||||
|
||||
EXPORT int gs_shader_get_num_params(const gs_shader_t *shader);
|
||||
EXPORT gs_sparam_t *gs_shader_get_param_by_idx(gs_shader_t *shader,
|
||||
uint32_t param);
|
||||
EXPORT gs_sparam_t *gs_shader_get_param_by_name(gs_shader_t *shader,
|
||||
const char *name);
|
||||
|
||||
EXPORT gs_sparam_t *gs_shader_get_viewproj_matrix(const gs_shader_t *shader);
|
||||
EXPORT gs_sparam_t *gs_shader_get_world_matrix(const gs_shader_t *shader);
|
||||
|
||||
EXPORT void gs_shader_get_param_info(const gs_sparam_t *param,
|
||||
struct gs_shader_param_info *info);
|
||||
EXPORT void gs_shader_set_bool(gs_sparam_t *param, bool val);
|
||||
EXPORT void gs_shader_set_float(gs_sparam_t *param, float val);
|
||||
EXPORT void gs_shader_set_int(gs_sparam_t *param, int val);
|
||||
EXPORT void gs_shader_set_matrix3(gs_sparam_t *param, const struct matrix3 *val);
|
||||
EXPORT void gs_shader_set_matrix4(gs_sparam_t *param, const struct matrix4 *val);
|
||||
EXPORT void gs_shader_set_vec2(gs_sparam_t *param, const struct vec2 *val);
|
||||
EXPORT void gs_shader_set_vec3(gs_sparam_t *param, const struct vec3 *val);
|
||||
EXPORT void gs_shader_set_vec4(gs_sparam_t *param, const struct vec4 *val);
|
||||
EXPORT void gs_shader_set_texture(gs_sparam_t *param, gs_texture_t *val);
|
||||
EXPORT void gs_shader_set_val(gs_sparam_t *param, const void *val, size_t size);
|
||||
EXPORT void gs_shader_set_default(gs_sparam_t *param);
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* effect functions
|
||||
* --------------------------------------------------- */
|
||||
|
||||
/*enum gs_effect_property_type {
|
||||
GS_EFFECT_NONE,
|
||||
GS_EFFECT_BOOL,
|
||||
GS_EFFECT_FLOAT,
|
||||
GS_EFFECT_COLOR,
|
||||
GS_EFFECT_TEXTURE
|
||||
};*/
|
||||
|
||||
struct gs_effect_param_info {
|
||||
const char *name;
|
||||
enum gs_shader_param_type type;
|
||||
|
||||
/* const char *full_name;
|
||||
enum gs_effect_property_type prop_type;
|
||||
|
||||
float min, max, inc, mul; */
|
||||
};
|
||||
|
||||
EXPORT void gs_effect_destroy(gs_effect_t *effect);
|
||||
|
||||
EXPORT gs_technique_t *gs_effect_get_technique(const gs_effect_t *effect,
|
||||
const char *name);
|
||||
|
||||
EXPORT gs_technique_t *gs_effect_get_current_technique(
|
||||
const gs_effect_t *effect);
|
||||
|
||||
EXPORT size_t gs_technique_begin(gs_technique_t *technique);
|
||||
EXPORT void gs_technique_end(gs_technique_t *technique);
|
||||
EXPORT bool gs_technique_begin_pass(gs_technique_t *technique, size_t pass);
|
||||
EXPORT bool gs_technique_begin_pass_by_name(gs_technique_t *technique,
|
||||
const char *name);
|
||||
EXPORT void gs_technique_end_pass(gs_technique_t *technique);
|
||||
|
||||
EXPORT size_t gs_effect_get_num_params(const gs_effect_t *effect);
|
||||
EXPORT gs_eparam_t *gs_effect_get_param_by_idx(const gs_effect_t *effect,
|
||||
size_t param);
|
||||
EXPORT gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect,
|
||||
const char *name);
|
||||
|
||||
/** Helper function to simplify effect usage. Use with a while loop that
|
||||
* contains drawing functions. Automatically handles techniques, passes, and
|
||||
* unloading. */
|
||||
EXPORT bool gs_effect_loop(gs_effect_t *effect, const char *name);
|
||||
|
||||
/** used internally */
|
||||
EXPORT void gs_effect_update_params(gs_effect_t *effect);
|
||||
|
||||
EXPORT gs_eparam_t *gs_effect_get_viewproj_matrix(const gs_effect_t *effect);
|
||||
EXPORT gs_eparam_t *gs_effect_get_world_matrix(const gs_effect_t *effect);
|
||||
|
||||
EXPORT void gs_effect_get_param_info(const gs_eparam_t *param,
|
||||
struct gs_effect_param_info *info);
|
||||
EXPORT void gs_effect_set_bool(gs_eparam_t *param, bool val);
|
||||
EXPORT void gs_effect_set_float(gs_eparam_t *param, float val);
|
||||
EXPORT void gs_effect_set_int(gs_eparam_t *param, int val);
|
||||
EXPORT void gs_effect_set_matrix4(gs_eparam_t *param,
|
||||
const struct matrix4 *val);
|
||||
EXPORT void gs_effect_set_vec2(gs_eparam_t *param, const struct vec2 *val);
|
||||
EXPORT void gs_effect_set_vec3(gs_eparam_t *param, const struct vec3 *val);
|
||||
EXPORT void gs_effect_set_vec4(gs_eparam_t *param, const struct vec4 *val);
|
||||
EXPORT void gs_effect_set_texture(gs_eparam_t *param, gs_texture_t *val);
|
||||
EXPORT void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size);
|
||||
EXPORT void gs_effect_set_default(gs_eparam_t *param);
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* texture render helper functions
|
||||
* --------------------------------------------------- */
|
||||
|
||||
EXPORT gs_texrender_t *gs_texrender_create(enum gs_color_format format,
|
||||
enum gs_zstencil_format zsformat);
|
||||
EXPORT void gs_texrender_destroy(gs_texrender_t *texrender);
|
||||
EXPORT bool gs_texrender_begin(gs_texrender_t *texrender, uint32_t cx,
|
||||
uint32_t cy);
|
||||
EXPORT void gs_texrender_end(gs_texrender_t *texrender);
|
||||
EXPORT void gs_texrender_reset(gs_texrender_t *texrender);
|
||||
EXPORT gs_texture_t *gs_texrender_get_texture(const gs_texrender_t *texrender);
|
||||
|
||||
/* ---------------------------------------------------
|
||||
* graphics subsystem
|
||||
* --------------------------------------------------- */
|
||||
|
||||
#define GS_BUILD_MIPMAPS (1<<0)
|
||||
#define GS_DYNAMIC (1<<1)
|
||||
#define GS_RENDER_TARGET (1<<2)
|
||||
#define GS_GL_DUMMYTEX (1<<3) /**<< texture with no allocated texture data */
|
||||
|
||||
/* ---------------- */
|
||||
/* global functions */
|
||||
|
||||
#define GS_SUCCESS 0
|
||||
#define GS_ERROR_FAIL -1
|
||||
#define GS_ERROR_MODULE_NOT_FOUND -2
|
||||
#define GS_ERROR_NOT_SUPPORTED -3
|
||||
|
||||
struct gs_window {
|
||||
#if defined(_WIN32)
|
||||
void *hwnd;
|
||||
#elif defined(__APPLE__)
|
||||
__unsafe_unretained id view;
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
/* I'm not sure how portable defining id to uint32_t is. */
|
||||
uint32_t id;
|
||||
void* display;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct gs_init_data {
|
||||
struct gs_window window;
|
||||
uint32_t cx, cy;
|
||||
uint32_t num_backbuffers;
|
||||
enum gs_color_format format;
|
||||
enum gs_zstencil_format zsformat;
|
||||
uint32_t adapter;
|
||||
};
|
||||
|
||||
#define GS_DEVICE_OPENGL 1
|
||||
#define GS_DEVICE_DIRECT3D_11 2
|
||||
|
||||
EXPORT const char *gs_get_device_name(void);
|
||||
EXPORT int gs_get_device_type(void);
|
||||
EXPORT void gs_enum_adapters(
|
||||
bool (*callback)(void *param, const char *name, uint32_t id),
|
||||
void *param);
|
||||
|
||||
EXPORT int gs_create(graphics_t **graphics, const char *module,
|
||||
uint32_t adapter);
|
||||
EXPORT void gs_destroy(graphics_t *graphics);
|
||||
|
||||
EXPORT void gs_enter_context(graphics_t *graphics);
|
||||
EXPORT void gs_leave_context(void);
|
||||
EXPORT graphics_t *gs_get_context(void);
|
||||
|
||||
EXPORT void gs_matrix_push(void);
|
||||
EXPORT void gs_matrix_pop(void);
|
||||
EXPORT void gs_matrix_identity(void);
|
||||
EXPORT void gs_matrix_transpose(void);
|
||||
EXPORT void gs_matrix_set(const struct matrix4 *matrix);
|
||||
EXPORT void gs_matrix_get(struct matrix4 *dst);
|
||||
EXPORT void gs_matrix_mul(const struct matrix4 *matrix);
|
||||
EXPORT void gs_matrix_rotquat(const struct quat *rot);
|
||||
EXPORT void gs_matrix_rotaa(const struct axisang *rot);
|
||||
EXPORT void gs_matrix_translate(const struct vec3 *pos);
|
||||
EXPORT void gs_matrix_scale(const struct vec3 *scale);
|
||||
EXPORT void gs_matrix_rotaa4f(float x, float y, float z, float angle);
|
||||
EXPORT void gs_matrix_translate3f(float x, float y, float z);
|
||||
EXPORT void gs_matrix_scale3f(float x, float y, float z);
|
||||
|
||||
EXPORT void gs_render_start(bool b_new);
|
||||
EXPORT void gs_render_stop(enum gs_draw_mode mode);
|
||||
EXPORT gs_vertbuffer_t *gs_render_save(void);
|
||||
EXPORT void gs_vertex2f(float x, float y);
|
||||
EXPORT void gs_vertex3f(float x, float y, float z);
|
||||
EXPORT void gs_normal3f(float x, float y, float z);
|
||||
EXPORT void gs_color(uint32_t color);
|
||||
EXPORT void gs_texcoord(float x, float y, int unit);
|
||||
EXPORT void gs_vertex2v(const struct vec2 *v);
|
||||
EXPORT void gs_vertex3v(const struct vec3 *v);
|
||||
EXPORT void gs_normal3v(const struct vec3 *v);
|
||||
EXPORT void gs_color4v(const struct vec4 *v);
|
||||
EXPORT void gs_texcoord2v(const struct vec2 *v, int unit);
|
||||
|
||||
EXPORT input_t *gs_get_input(void);
|
||||
EXPORT gs_effect_t *gs_get_effect(void);
|
||||
|
||||
EXPORT gs_effect_t *gs_effect_create_from_file(const char *file,
|
||||
char **error_string);
|
||||
EXPORT gs_effect_t *gs_effect_create(const char *effect_string,
|
||||
const char *filename, char **error_string);
|
||||
|
||||
EXPORT gs_shader_t *gs_vertexshader_create_from_file(const char *file,
|
||||
char **error_string);
|
||||
EXPORT gs_shader_t *gs_pixelshader_create_from_file(const char *file,
|
||||
char **error_string);
|
||||
|
||||
EXPORT gs_texture_t *gs_texture_create_from_file(const char *file);
|
||||
EXPORT uint8_t *gs_create_texture_file_data(const char *file,
|
||||
enum gs_color_format *format, uint32_t *cx, uint32_t *cy);
|
||||
|
||||
#define GS_FLIP_U (1<<0)
|
||||
#define GS_FLIP_V (1<<1)
|
||||
|
||||
/**
|
||||
* Draws a 2D sprite
|
||||
*
|
||||
* If width or height is 0, the width or height of the texture will be used.
|
||||
* The flip value specifies whether the texture shoudl be flipped on the U or V
|
||||
* axis with GS_FLIP_U and GS_FLIP_V.
|
||||
*/
|
||||
EXPORT void gs_draw_sprite(gs_texture_t *tex, uint32_t flip, uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
EXPORT void gs_draw_cube_backdrop(gs_texture_t *cubetex, const struct quat *rot,
|
||||
float left, float right, float top, float bottom, float znear);
|
||||
|
||||
/** sets the viewport to current swap chain size */
|
||||
EXPORT void gs_reset_viewport(void);
|
||||
|
||||
/** sets default screen-sized orthographich mode */
|
||||
EXPORT void gs_set_2d_mode(void);
|
||||
/** sets default screen-sized perspective mode */
|
||||
EXPORT void gs_set_3d_mode(double fovy, double znear, double zvar);
|
||||
|
||||
EXPORT void gs_viewport_push(void);
|
||||
EXPORT void gs_viewport_pop(void);
|
||||
|
||||
EXPORT void gs_texture_set_image(gs_texture_t *tex, const uint8_t *data,
|
||||
uint32_t linesize, bool invert);
|
||||
EXPORT void gs_cubetexture_set_image(gs_texture_t *cubetex, uint32_t side,
|
||||
const void *data, uint32_t linesize, bool invert);
|
||||
|
||||
EXPORT void gs_perspective(float fovy, float aspect, float znear, float zfar);
|
||||
|
||||
EXPORT void gs_blend_state_push(void);
|
||||
EXPORT void gs_blend_state_pop(void);
|
||||
EXPORT void gs_reset_blend_state(void);
|
||||
|
||||
/* -------------------------- */
|
||||
/* library-specific functions */
|
||||
|
||||
EXPORT gs_swapchain_t *gs_swapchain_create(const struct gs_init_data *data);
|
||||
|
||||
EXPORT void gs_resize(uint32_t x, uint32_t y);
|
||||
EXPORT void gs_get_size(uint32_t *x, uint32_t *y);
|
||||
EXPORT uint32_t gs_get_width(void);
|
||||
EXPORT uint32_t gs_get_height(void);
|
||||
|
||||
EXPORT gs_texture_t *gs_texture_create(uint32_t width, uint32_t height,
|
||||
enum gs_color_format color_format, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags);
|
||||
EXPORT gs_texture_t *gs_cubetexture_create(uint32_t size,
|
||||
enum gs_color_format color_format, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags);
|
||||
EXPORT gs_texture_t *gs_voltexture_create(uint32_t width, uint32_t height,
|
||||
uint32_t depth, enum gs_color_format color_format,
|
||||
uint32_t levels, const uint8_t **data, uint32_t flags);
|
||||
|
||||
EXPORT gs_zstencil_t *gs_zstencil_create(uint32_t width, uint32_t height,
|
||||
enum gs_zstencil_format format);
|
||||
|
||||
EXPORT gs_stagesurf_t *gs_stagesurface_create(uint32_t width, uint32_t height,
|
||||
enum gs_color_format color_format);
|
||||
|
||||
EXPORT gs_samplerstate_t *gs_samplerstate_create(
|
||||
const struct gs_sampler_info *info);
|
||||
|
||||
EXPORT gs_shader_t *gs_vertexshader_create(const char *shader,
|
||||
const char *file, char **error_string);
|
||||
EXPORT gs_shader_t *gs_pixelshader_create(const char *shader,
|
||||
const char *file, char **error_string);
|
||||
|
||||
EXPORT gs_vertbuffer_t *gs_vertexbuffer_create(struct gs_vb_data *data,
|
||||
uint32_t flags);
|
||||
EXPORT gs_indexbuffer_t *gs_indexbuffer_create(enum gs_index_type type,
|
||||
void *indices, size_t num, uint32_t flags);
|
||||
|
||||
EXPORT enum gs_texture_type gs_get_texture_type(const gs_texture_t *texture);
|
||||
|
||||
EXPORT void gs_load_vertexbuffer(gs_vertbuffer_t *vertbuffer);
|
||||
EXPORT void gs_load_indexbuffer(gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT void gs_load_texture(gs_texture_t *tex, int unit);
|
||||
EXPORT void gs_load_samplerstate(gs_samplerstate_t *samplerstate, int unit);
|
||||
EXPORT void gs_load_vertexshader(gs_shader_t *vertshader);
|
||||
EXPORT void gs_load_pixelshader(gs_shader_t *pixelshader);
|
||||
|
||||
EXPORT void gs_load_default_samplerstate(bool b_3d, int unit);
|
||||
|
||||
EXPORT gs_shader_t *gs_get_vertex_shader(void);
|
||||
EXPORT gs_shader_t *gs_get_pixel_shader(void);
|
||||
|
||||
EXPORT gs_texture_t *gs_get_render_target(void);
|
||||
EXPORT gs_zstencil_t *gs_get_zstencil_target(void);
|
||||
|
||||
EXPORT void gs_set_render_target(gs_texture_t *tex, gs_zstencil_t *zstencil);
|
||||
EXPORT void gs_set_cube_render_target(gs_texture_t *cubetex, int side,
|
||||
gs_zstencil_t *zstencil);
|
||||
|
||||
EXPORT void gs_copy_texture(gs_texture_t *dst, gs_texture_t *src);
|
||||
EXPORT void gs_copy_texture_region(
|
||||
gs_texture_t *dst, uint32_t dst_x, uint32_t dst_y,
|
||||
gs_texture_t *src, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
EXPORT void gs_stage_texture(gs_stagesurf_t *dst, gs_texture_t *src);
|
||||
|
||||
EXPORT void gs_begin_scene(void);
|
||||
EXPORT void gs_draw(enum gs_draw_mode draw_mode, uint32_t start_vert,
|
||||
uint32_t num_verts);
|
||||
EXPORT void gs_end_scene(void);
|
||||
|
||||
#define GS_CLEAR_COLOR (1<<0)
|
||||
#define GS_CLEAR_DEPTH (1<<1)
|
||||
#define GS_CLEAR_STENCIL (1<<2)
|
||||
|
||||
EXPORT void gs_load_swapchain(gs_swapchain_t *swapchain);
|
||||
EXPORT void gs_clear(uint32_t clear_flags, const struct vec4 *color,
|
||||
float depth, uint8_t stencil);
|
||||
EXPORT void gs_present(void);
|
||||
EXPORT void gs_flush(void);
|
||||
|
||||
EXPORT void gs_set_cull_mode(enum gs_cull_mode mode);
|
||||
EXPORT enum gs_cull_mode gs_get_cull_mode(void);
|
||||
|
||||
EXPORT void gs_enable_blending(bool enable);
|
||||
EXPORT void gs_enable_depth_test(bool enable);
|
||||
EXPORT void gs_enable_stencil_test(bool enable);
|
||||
EXPORT void gs_enable_stencil_write(bool enable);
|
||||
EXPORT void gs_enable_color(bool red, bool green, bool blue, bool alpha);
|
||||
|
||||
EXPORT void gs_blend_function(enum gs_blend_type src, enum gs_blend_type dest);
|
||||
EXPORT void gs_blend_function_separate(
|
||||
enum gs_blend_type src_c, enum gs_blend_type dest_c,
|
||||
enum gs_blend_type src_a, enum gs_blend_type dest_a);
|
||||
EXPORT void gs_depth_function(enum gs_depth_test test);
|
||||
|
||||
EXPORT void gs_stencil_function(enum gs_stencil_side side,
|
||||
enum gs_depth_test test);
|
||||
EXPORT void gs_stencil_op(enum gs_stencil_side side,
|
||||
enum gs_stencil_op_type fail,
|
||||
enum gs_stencil_op_type zfail,
|
||||
enum gs_stencil_op_type zpass);
|
||||
|
||||
EXPORT void gs_set_viewport(int x, int y, int width, int height);
|
||||
EXPORT void gs_get_viewport(struct gs_rect *rect);
|
||||
EXPORT void gs_set_scissor_rect(const struct gs_rect *rect);
|
||||
|
||||
EXPORT void gs_ortho(float left, float right, float top, float bottom,
|
||||
float znear, float zfar);
|
||||
EXPORT void gs_frustum(float left, float right, float top, float bottom,
|
||||
float znear, float zfar);
|
||||
|
||||
EXPORT void gs_projection_push(void);
|
||||
EXPORT void gs_projection_pop(void);
|
||||
|
||||
EXPORT void gs_swapchain_destroy(gs_swapchain_t *swapchain);
|
||||
|
||||
EXPORT void gs_texture_destroy(gs_texture_t *tex);
|
||||
EXPORT uint32_t gs_texture_get_width(const gs_texture_t *tex);
|
||||
EXPORT uint32_t gs_texture_get_height(const gs_texture_t *tex);
|
||||
EXPORT enum gs_color_format gs_texture_get_color_format(
|
||||
const gs_texture_t *tex);
|
||||
EXPORT bool gs_texture_map(gs_texture_t *tex, uint8_t **ptr,
|
||||
uint32_t *linesize);
|
||||
EXPORT void gs_texture_unmap(gs_texture_t *tex);
|
||||
/** special-case function (GL only) - specifies whether the texture is a
|
||||
* GL_TEXTURE_RECTANGLE type, which doesn't use normalized texture
|
||||
* coordinates, doesn't support mipmapping, and requires address clamping */
|
||||
EXPORT bool gs_texture_is_rect(const gs_texture_t *tex);
|
||||
/**
|
||||
* Gets a pointer to the context-specific object associated with the texture.
|
||||
* For example, for GL, this is a GLuint*. For D3D11, ID3D11Texture2D*.
|
||||
*/
|
||||
EXPORT void *gs_texture_get_obj(gs_texture_t *tex);
|
||||
|
||||
EXPORT void gs_cubetexture_destroy(gs_texture_t *cubetex);
|
||||
EXPORT uint32_t gs_cubetexture_get_size(const gs_texture_t *cubetex);
|
||||
EXPORT enum gs_color_format gs_cubetexture_get_color_format(
|
||||
const gs_texture_t *cubetex);
|
||||
|
||||
EXPORT void gs_voltexture_destroy(gs_texture_t *voltex);
|
||||
EXPORT uint32_t gs_voltexture_get_width(const gs_texture_t *voltex);
|
||||
EXPORT uint32_t gs_voltexture_get_height(const gs_texture_t *voltex);
|
||||
EXPORT uint32_t gs_voltexture_get_depth(const gs_texture_t *voltex);
|
||||
EXPORT enum gs_color_format gs_voltexture_get_color_format(
|
||||
const gs_texture_t *voltex);
|
||||
|
||||
EXPORT void gs_stagesurface_destroy(gs_stagesurf_t *stagesurf);
|
||||
EXPORT uint32_t gs_stagesurface_get_width(const gs_stagesurf_t *stagesurf);
|
||||
EXPORT uint32_t gs_stagesurface_get_height(const gs_stagesurf_t *stagesurf);
|
||||
EXPORT enum gs_color_format gs_stagesurface_get_color_format(
|
||||
const gs_stagesurf_t *stagesurf);
|
||||
EXPORT bool gs_stagesurface_map(gs_stagesurf_t *stagesurf, uint8_t **data,
|
||||
uint32_t *linesize);
|
||||
EXPORT void gs_stagesurface_unmap(gs_stagesurf_t *stagesurf);
|
||||
|
||||
EXPORT void gs_zstencil_destroy(gs_zstencil_t *zstencil);
|
||||
|
||||
EXPORT void gs_samplerstate_destroy(gs_samplerstate_t *samplerstate);
|
||||
|
||||
EXPORT void gs_vertexbuffer_destroy(gs_vertbuffer_t *vertbuffer);
|
||||
EXPORT void gs_vertexbuffer_flush(gs_vertbuffer_t *vertbuffer);
|
||||
EXPORT struct gs_vb_data *gs_vertexbuffer_get_data(
|
||||
const gs_vertbuffer_t *vertbuffer);
|
||||
|
||||
EXPORT void gs_indexbuffer_destroy(gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT void gs_indexbuffer_flush(gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT void *gs_indexbuffer_get_data(const gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT size_t gs_indexbuffer_get_num_indices(
|
||||
const gs_indexbuffer_t *indexbuffer);
|
||||
EXPORT enum gs_index_type gs_indexbuffer_get_type(
|
||||
const gs_indexbuffer_t *indexbuffer);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/** platform specific function for creating (GL_TEXTURE_RECTANGLE) textures
|
||||
* from shared surface resources */
|
||||
EXPORT gs_texture_t *gs_texture_create_from_iosurface(void *iosurf);
|
||||
EXPORT bool gs_texture_rebind_iosurface(gs_texture_t *texture,
|
||||
void *iosurf);
|
||||
|
||||
#elif _WIN32
|
||||
|
||||
EXPORT bool gs_gdi_texture_available(void);
|
||||
EXPORT bool gs_shared_texture_available(void);
|
||||
|
||||
struct gs_duplicator;
|
||||
typedef struct gs_duplicator gs_duplicator_t;
|
||||
|
||||
/**
|
||||
* Gets information about the monitor at the specific index, returns false
|
||||
* when there is no monitor at the specified index
|
||||
*/
|
||||
EXPORT bool gs_get_duplicator_monitor_info(int monitor_idx,
|
||||
struct gs_monitor_info *monitor_info);
|
||||
|
||||
/** creates a windows 8+ output duplicator (monitor capture) */
|
||||
EXPORT gs_duplicator_t *gs_duplicator_create(int monitor_idx);
|
||||
EXPORT void gs_duplicator_destroy(gs_duplicator_t *duplicator);
|
||||
|
||||
EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *duplicator);
|
||||
EXPORT gs_texture_t *gs_duplicator_get_texture(gs_duplicator_t *duplicator);
|
||||
|
||||
/** creates a windows GDI-lockable texture */
|
||||
EXPORT gs_texture_t *gs_texture_create_gdi(uint32_t width, uint32_t height);
|
||||
|
||||
EXPORT void *gs_texture_get_dc(gs_texture_t *gdi_tex);
|
||||
EXPORT void gs_texture_release_dc(gs_texture_t *gdi_tex);
|
||||
|
||||
/** creates a windows shared texture from a texture handle */
|
||||
EXPORT gs_texture_t *gs_texture_open_shared(uint32_t handle);
|
||||
#endif
|
||||
|
||||
/* inline functions used by modules */
|
||||
|
||||
static inline uint32_t gs_get_format_bpp(enum gs_color_format format)
|
||||
{
|
||||
switch (format) {
|
||||
case GS_A8: return 8;
|
||||
case GS_R8: return 8;
|
||||
case GS_RGBA: return 32;
|
||||
case GS_BGRX: return 32;
|
||||
case GS_BGRA: return 32;
|
||||
case GS_R10G10B10A2: return 32;
|
||||
case GS_RGBA16: return 64;
|
||||
case GS_R16: return 16;
|
||||
case GS_RGBA16F: return 64;
|
||||
case GS_RGBA32F: return 128;
|
||||
case GS_RG16F: return 32;
|
||||
case GS_RG32F: return 64;
|
||||
case GS_R16F: return 16;
|
||||
case GS_R32F: return 32;
|
||||
case GS_DXT1: return 4;
|
||||
case GS_DXT3: return 8;
|
||||
case GS_DXT5: return 8;
|
||||
case GS_UNKNOWN: return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool gs_is_compressed_format(enum gs_color_format format)
|
||||
{
|
||||
return (format == GS_DXT1 || format == GS_DXT3 || format == GS_DXT5);
|
||||
}
|
||||
|
||||
static inline uint32_t gs_get_total_levels(uint32_t width, uint32_t height)
|
||||
{
|
||||
uint32_t size = width > height ? width : height;
|
||||
uint32_t num_levels = 0;
|
||||
|
||||
while (size > 1) {
|
||||
size /= 2;
|
||||
num_levels++;
|
||||
}
|
||||
|
||||
return num_levels;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
326
libobs/graphics/image-file.c
Normal file
326
libobs/graphics/image-file.c
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2016 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "image-file.h"
|
||||
#include "../util/base.h"
|
||||
#include "../util/platform.h"
|
||||
|
||||
#define blog(level, format, ...) \
|
||||
blog(level, "%s: " format, __FUNCTION__, __VA_ARGS__)
|
||||
|
||||
static void *bi_def_bitmap_create(int width, int height)
|
||||
{
|
||||
return bmalloc(width * height * 4);
|
||||
}
|
||||
|
||||
static void bi_def_bitmap_set_opaque(void *bitmap, bool opaque)
|
||||
{
|
||||
UNUSED_PARAMETER(bitmap);
|
||||
UNUSED_PARAMETER(opaque);
|
||||
}
|
||||
|
||||
static bool bi_def_bitmap_test_opaque(void *bitmap)
|
||||
{
|
||||
UNUSED_PARAMETER(bitmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned char *bi_def_bitmap_get_buffer(void *bitmap)
|
||||
{
|
||||
return (unsigned char*)bitmap;
|
||||
}
|
||||
|
||||
static void bi_def_bitmap_destroy(void *bitmap)
|
||||
{
|
||||
bfree(bitmap);
|
||||
}
|
||||
|
||||
static void bi_def_bitmap_modified(void *bitmap)
|
||||
{
|
||||
UNUSED_PARAMETER(bitmap);
|
||||
}
|
||||
|
||||
static inline int get_full_decoded_gif_size(gs_image_file_t *image)
|
||||
{
|
||||
return image->gif.width * image->gif.height * 4 * image->gif.frame_count;
|
||||
}
|
||||
|
||||
static bool init_animated_gif(gs_image_file_t *image, const char *path)
|
||||
{
|
||||
bool is_animated_gif = true;
|
||||
gif_result result;
|
||||
uint64_t max_size;
|
||||
size_t size;
|
||||
FILE *file;
|
||||
|
||||
image->bitmap_callbacks.bitmap_create = bi_def_bitmap_create;
|
||||
image->bitmap_callbacks.bitmap_destroy = bi_def_bitmap_destroy;
|
||||
image->bitmap_callbacks.bitmap_get_buffer = bi_def_bitmap_get_buffer;
|
||||
image->bitmap_callbacks.bitmap_modified = bi_def_bitmap_modified;
|
||||
image->bitmap_callbacks.bitmap_set_opaque = bi_def_bitmap_set_opaque;
|
||||
image->bitmap_callbacks.bitmap_test_opaque = bi_def_bitmap_test_opaque;
|
||||
|
||||
gif_create(&image->gif, &image->bitmap_callbacks);
|
||||
|
||||
file = os_fopen(path, "rb");
|
||||
if (!file) {
|
||||
blog(LOG_WARNING, "Failed to open file '%s'", path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
size = (size_t)os_ftelli64(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
image->gif_data = bmalloc(size);
|
||||
fread(image->gif_data, 1, size, file);
|
||||
|
||||
do {
|
||||
result = gif_initialise(&image->gif, size, image->gif_data);
|
||||
if (result < 0) {
|
||||
blog(LOG_WARNING, "Failed to initialize gif '%s', "
|
||||
"possible file corruption", path);
|
||||
goto fail;
|
||||
}
|
||||
} while (result != GIF_OK);
|
||||
|
||||
if (image->gif.width > 4096 || image->gif.height > 4096) {
|
||||
blog(LOG_WARNING, "Bad texture dimensions (%dx%d) in '%s'",
|
||||
image->gif.width, image->gif.height, path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
max_size = (uint64_t)image->gif.width * (uint64_t)image->gif.height *
|
||||
(uint64_t)image->gif.frame_count * 4LLU;
|
||||
|
||||
if ((uint64_t)get_full_decoded_gif_size(image) != max_size) {
|
||||
blog(LOG_WARNING, "Gif '%s' overflowed maximum pointer size",
|
||||
path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
image->is_animated_gif = (image->gif.frame_count > 1 && result >= 0);
|
||||
if (image->is_animated_gif) {
|
||||
gif_decode_frame(&image->gif, 0);
|
||||
|
||||
image->animation_frame_cache = bzalloc(
|
||||
image->gif.frame_count * sizeof(uint8_t*));
|
||||
image->animation_frame_data = bzalloc(
|
||||
get_full_decoded_gif_size(image));
|
||||
|
||||
for (unsigned int i = 0; i < image->gif.frame_count; i++) {
|
||||
if (gif_decode_frame(&image->gif, i) != GIF_OK)
|
||||
blog(LOG_WARNING, "Couldn't decode frame %u "
|
||||
"of '%s'", i, path);
|
||||
}
|
||||
|
||||
gif_decode_frame(&image->gif, 0);
|
||||
|
||||
image->cx = (uint32_t)image->gif.width;
|
||||
image->cy = (uint32_t)image->gif.height;
|
||||
image->format = GS_RGBA;
|
||||
} else {
|
||||
gif_finalise(&image->gif);
|
||||
bfree(image->gif_data);
|
||||
image->gif_data = NULL;
|
||||
is_animated_gif = false;
|
||||
goto not_animated;
|
||||
}
|
||||
|
||||
image->loaded = true;
|
||||
|
||||
fail:
|
||||
if (!image->loaded)
|
||||
gs_image_file_free(image);
|
||||
not_animated:
|
||||
if (file)
|
||||
fclose(file);
|
||||
|
||||
return is_animated_gif;
|
||||
}
|
||||
|
||||
void gs_image_file_init(gs_image_file_t *image, const char *file)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
memset(image, 0, sizeof(*image));
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
len = strlen(file);
|
||||
|
||||
if (len > 4 && strcmp(file + len - 4, ".gif") == 0) {
|
||||
if (init_animated_gif(image, file))
|
||||
return;
|
||||
}
|
||||
|
||||
image->texture_data = gs_create_texture_file_data(file,
|
||||
&image->format, &image->cx, &image->cy);
|
||||
|
||||
image->loaded = !!image->texture_data;
|
||||
if (!image->loaded) {
|
||||
blog(LOG_WARNING, "Failed to load file '%s'", file);
|
||||
gs_image_file_free(image);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_image_file_free(gs_image_file_t *image)
|
||||
{
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
if (image->loaded) {
|
||||
if (image->is_animated_gif) {
|
||||
gif_finalise(&image->gif);
|
||||
bfree(image->animation_frame_cache);
|
||||
bfree(image->animation_frame_data);
|
||||
}
|
||||
|
||||
gs_texture_destroy(image->texture);
|
||||
}
|
||||
|
||||
bfree(image->texture_data);
|
||||
bfree(image->gif_data);
|
||||
memset(image, 0, sizeof(*image));
|
||||
}
|
||||
|
||||
void gs_image_file_init_texture(gs_image_file_t *image)
|
||||
{
|
||||
if (!image->loaded)
|
||||
return;
|
||||
|
||||
if (image->is_animated_gif) {
|
||||
image->texture = gs_texture_create(
|
||||
image->cx, image->cy, image->format, 1,
|
||||
(const uint8_t**)&image->gif.frame_image,
|
||||
GS_DYNAMIC);
|
||||
|
||||
} else {
|
||||
image->texture = gs_texture_create(
|
||||
image->cx, image->cy, image->format, 1,
|
||||
(const uint8_t**)&image->texture_data, 0);
|
||||
bfree(image->texture_data);
|
||||
image->texture_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t get_time(gs_image_file_t *image, int i)
|
||||
{
|
||||
uint64_t val = (uint64_t)image->gif.frames[i].frame_delay * 10000000ULL;
|
||||
if (!val)
|
||||
val = 100000000;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline int calculate_new_frame(gs_image_file_t *image,
|
||||
uint64_t elapsed_time_ns, int loops)
|
||||
{
|
||||
int new_frame = image->cur_frame;
|
||||
|
||||
image->cur_time += elapsed_time_ns;
|
||||
for (;;) {
|
||||
uint64_t t = get_time(image, new_frame);
|
||||
if (image->cur_time <= t)
|
||||
break;
|
||||
|
||||
image->cur_time -= t;
|
||||
if ((unsigned int)++new_frame == image->gif.frame_count) {
|
||||
if (!loops || ++image->cur_loop < loops) {
|
||||
new_frame = 0;
|
||||
} else if (image->cur_loop == loops) {
|
||||
new_frame--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_frame;
|
||||
}
|
||||
|
||||
static void decode_new_frame(gs_image_file_t *image, int new_frame)
|
||||
{
|
||||
if (!image->animation_frame_cache[new_frame]) {
|
||||
int last_frame;
|
||||
|
||||
/* if looped, decode frame 0 */
|
||||
last_frame = (new_frame < image->last_decoded_frame) ?
|
||||
0 : image->last_decoded_frame + 1;
|
||||
|
||||
/* decode missed frames */
|
||||
for (int i = last_frame; i < new_frame; i++) {
|
||||
if (gif_decode_frame(&image->gif, i) != GIF_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
/* decode actual desired frame */
|
||||
if (gif_decode_frame(&image->gif, new_frame) == GIF_OK) {
|
||||
size_t pos = new_frame * image->gif.width *
|
||||
image->gif.height * 4;
|
||||
image->animation_frame_cache[new_frame] =
|
||||
image->animation_frame_data + pos;
|
||||
|
||||
memcpy(image->animation_frame_cache[new_frame],
|
||||
image->gif.frame_image,
|
||||
image->gif.width *
|
||||
image->gif.height * 4);
|
||||
|
||||
image->last_decoded_frame = new_frame;
|
||||
}
|
||||
}
|
||||
|
||||
image->cur_frame = new_frame;
|
||||
}
|
||||
|
||||
bool gs_image_file_tick(gs_image_file_t *image, uint64_t elapsed_time_ns)
|
||||
{
|
||||
int loops;
|
||||
|
||||
if (!image->is_animated_gif || !image->loaded)
|
||||
return false;
|
||||
|
||||
loops = image->gif.loop_count;
|
||||
if (loops >= 0xFFFF)
|
||||
loops = 0;
|
||||
|
||||
if (!loops || image->cur_loop < loops) {
|
||||
int new_frame = calculate_new_frame(image, elapsed_time_ns,
|
||||
loops);
|
||||
|
||||
if (new_frame != image->cur_frame) {
|
||||
decode_new_frame(image, new_frame);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void gs_image_file_update_texture(gs_image_file_t *image)
|
||||
{
|
||||
if (!image->is_animated_gif || !image->loaded)
|
||||
return;
|
||||
|
||||
if (image->animation_frame_cache[image->cur_frame]) {
|
||||
gs_texture_set_image(image->texture,
|
||||
image->animation_frame_cache[image->cur_frame],
|
||||
image->gif.width * 4, false);
|
||||
}
|
||||
}
|
||||
53
libobs/graphics/image-file.h
Normal file
53
libobs/graphics/image-file.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2016 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graphics.h"
|
||||
#include "libnsgif/libnsgif.h"
|
||||
|
||||
struct gs_image_file {
|
||||
gs_texture_t *texture;
|
||||
enum gs_color_format format;
|
||||
uint32_t cx;
|
||||
uint32_t cy;
|
||||
bool is_animated_gif;
|
||||
bool frame_updated;
|
||||
bool loaded;
|
||||
|
||||
gif_animation gif;
|
||||
uint8_t *gif_data;
|
||||
uint8_t **animation_frame_cache;
|
||||
uint8_t *animation_frame_data;
|
||||
uint64_t cur_time;
|
||||
int cur_frame;
|
||||
int cur_loop;
|
||||
int last_decoded_frame;
|
||||
|
||||
uint8_t *texture_data;
|
||||
gif_bitmap_callback_vt bitmap_callbacks;
|
||||
};
|
||||
|
||||
typedef struct gs_image_file gs_image_file_t;
|
||||
|
||||
EXPORT void gs_image_file_init(gs_image_file_t *image, const char *file);
|
||||
EXPORT void gs_image_file_free(gs_image_file_t *image);
|
||||
|
||||
EXPORT void gs_image_file_init_texture(gs_image_file_t *image);
|
||||
EXPORT bool gs_image_file_tick(gs_image_file_t *image,
|
||||
uint64_t elapsed_time_ns);
|
||||
EXPORT void gs_image_file_update_texture(gs_image_file_t *image);
|
||||
152
libobs/graphics/input.h
Normal file
152
libobs/graphics/input.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* TODO: incomplete/may not be necessary */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KBC_ESCAPE 0x0
|
||||
#define KBC_1 0x1
|
||||
#define KBC_2 0x2
|
||||
#define KBC_3 0x3
|
||||
#define KBC_4 0x4
|
||||
#define KBC_5 0x5
|
||||
#define KBC_6 0x6
|
||||
#define KBC_7 0x7
|
||||
#define KBC_8 0x8
|
||||
#define KBC_9 0x9
|
||||
#define KBC_0 0xA
|
||||
#define KBC_MINUS 0xB
|
||||
#define KBC_EQUALS 0xC
|
||||
#define KBC_BACK 0xD
|
||||
#define KBC_TAB 0xE
|
||||
#define KBC_Q 0xF
|
||||
#define KBC_W 0x10
|
||||
#define KBC_E 0x11
|
||||
#define KBC_R 0x12
|
||||
#define KBC_T 0x13
|
||||
#define KBC_Y 0x14
|
||||
#define KBC_U 0x15
|
||||
#define KBC_I 0x16
|
||||
#define KBC_O 0x17
|
||||
#define KBC_P 0x18
|
||||
#define KBC_LBRACKET 0x19
|
||||
#define KBC_RBRACKET 0x1A
|
||||
#define KBC_RETURN 0x1B
|
||||
#define KBC_LCONTROL 0x1C
|
||||
#define KBC_A 0x1D
|
||||
#define KBC_S 0x1E
|
||||
#define KBC_D 0x1F
|
||||
#define KBC_F 0x20
|
||||
#define KBC_G 0x21
|
||||
#define KBC_H 0x22
|
||||
#define KBC_J 0x23
|
||||
#define KBC_K 0x24
|
||||
#define KBC_L 0x25
|
||||
#define KBC_SEMICOLON 0x26
|
||||
#define KBC_APOSTROPHE 0x27
|
||||
#define KBC_TILDE 0x28
|
||||
#define KBC_LSHIFT 0x29
|
||||
#define KBC_BACKSLASH 0x2A
|
||||
#define KBC_Z 0x2B
|
||||
#define KBC_X 0x2C
|
||||
#define KBC_C 0x2D
|
||||
#define KBC_V 0x2E
|
||||
#define KBC_B 0x2F
|
||||
#define KBC_N 0x30
|
||||
#define KBC_M 0x31
|
||||
#define KBC_COMMA 0x32
|
||||
#define KBC_PERIOD 0x33
|
||||
#define KBC_SLASH 0x34
|
||||
#define KBC_RSHIFT 0x35
|
||||
#define KBC_MULTIPLY 0x36
|
||||
#define KBC_LALT 0x37
|
||||
#define KBC_SPACE 0x38
|
||||
#define KBC_CAPSLOCK 0x39
|
||||
#define KBC_F1 0x3A
|
||||
#define KBC_F2 0x3B
|
||||
#define KBC_F3 0x3C
|
||||
#define KBC_F4 0x3D
|
||||
#define KBC_F5 0x3E
|
||||
#define KBC_F6 0x3F
|
||||
#define KBC_F7 0x40
|
||||
#define KBC_F8 0x41
|
||||
#define KBC_F9 0x42
|
||||
#define KBC_F10 0x43
|
||||
#define KBC_NUMLOCK 0x44
|
||||
#define KBC_SCROLLLOCK 0x45
|
||||
#define KBC_NUMPAD7 0x46
|
||||
#define KBC_NUMPAD8 0x47
|
||||
#define KBC_NUMPAD9 0x48
|
||||
#define KBC_SUBTRACT 0x49
|
||||
#define KBC_NUMPAD4 0x4A
|
||||
#define KBC_NUMPAD5 0x4B
|
||||
#define KBC_NUMPAD6 0x4C
|
||||
#define KBC_ADD 0x4D
|
||||
#define KBC_NUMPAD1 0x4E
|
||||
#define KBC_NUMPAD2 0x4F
|
||||
#define KBC_NUMPAD3 0x50
|
||||
#define KBC_NUMPAD0 0x51
|
||||
#define KBC_DECIMAL 0x52
|
||||
#define KBC_F11 0x53
|
||||
#define KBC_F12 0x54
|
||||
#define KBC_NUMPADENTER 0x55
|
||||
#define KBC_RCONTROL 0x56
|
||||
#define KBC_DIVIDE 0x57
|
||||
#define KBC_SYSRQ 0x58
|
||||
#define KBC_RALT 0x59
|
||||
#define KBC_PAUSE 0x5A
|
||||
#define KBC_HOME 0x5B
|
||||
#define KBC_UP 0x5C
|
||||
#define KBC_PAGEDOWN 0x5D
|
||||
#define KBC_LEFT 0x5E
|
||||
#define KBC_RIGHT 0x5F
|
||||
#define KBC_END 0x60
|
||||
#define KBC_DOWN 0x61
|
||||
#define KBC_PAGEUP 0x62
|
||||
#define KBC_INSERT 0x63
|
||||
#define KBC_DELETE 0x64
|
||||
|
||||
#define MOUSE_LEFTBUTTON 0x65
|
||||
#define MOUSE_MIDDLEBUTTON 0x66
|
||||
#define MOUSE_RIGHTBUTTON 0x67
|
||||
#define MOUSE_WHEEL 0x68
|
||||
#define MOUSE_MOVE 0x69
|
||||
|
||||
#define KBC_CONTROL 0xFFFFFFFE
|
||||
#define KBC_ALT 0xFFFFFFFD
|
||||
#define KBC_SHIFT 0xFFFFFFFC
|
||||
|
||||
#define STATE_LBUTTONDOWN (1<<0)
|
||||
#define STATE_RBUTTONDOWN (1<<1)
|
||||
#define STATE_MBUTTONDOWN (1<<2)
|
||||
#define STATE_X4BUTTONDOWN (1<<3)
|
||||
#define STATE_X5BUTTONDOWN (1<<4)
|
||||
|
||||
/* wrapped opaque data types */
|
||||
struct input_subsystem;
|
||||
typedef struct input_subsystem input_t;
|
||||
|
||||
EXPORT int input_getbuttonstate(input_t *input, uint32_t button);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
1274
libobs/graphics/libnsgif/libnsgif.c
Normal file
1274
libobs/graphics/libnsgif/libnsgif.c
Normal file
File diff suppressed because it is too large
Load diff
142
libobs/graphics/libnsgif/libnsgif.h
Normal file
142
libobs/graphics/libnsgif/libnsgif.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2004 Richard Wilson <richard.wilson@netsurf-browser.org>
|
||||
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
|
||||
*
|
||||
* This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
|
||||
* Licenced under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Progressive animated GIF file decoding (interface).
|
||||
*/
|
||||
|
||||
#ifndef _LIBNSGIF_H_
|
||||
#define _LIBNSGIF_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/* Error return values
|
||||
*/
|
||||
typedef enum {
|
||||
GIF_WORKING = 1,
|
||||
GIF_OK = 0,
|
||||
GIF_INSUFFICIENT_FRAME_DATA = -1,
|
||||
GIF_FRAME_DATA_ERROR = -2,
|
||||
GIF_INSUFFICIENT_DATA = -3,
|
||||
GIF_DATA_ERROR = -4,
|
||||
GIF_INSUFFICIENT_MEMORY = -5,
|
||||
GIF_FRAME_NO_DISPLAY = -6,
|
||||
GIF_END_OF_FRAME = -7
|
||||
} gif_result;
|
||||
|
||||
/* Maximum LZW bits available
|
||||
*/
|
||||
#define GIF_MAX_LZW 12
|
||||
|
||||
/* The GIF frame data
|
||||
*/
|
||||
typedef struct gif_frame {
|
||||
bool display; /**< whether the frame should be displayed/animated */
|
||||
unsigned int frame_delay; /**< delay (in 100th second intervals) before animating the frame */
|
||||
/** Internal members are listed below
|
||||
*/
|
||||
unsigned int frame_pointer; /**< offset (in bytes) to the GIF frame data */
|
||||
bool virgin; /**< whether the frame has previously been used */
|
||||
bool opaque; /**< whether the frame is totally opaque */
|
||||
bool redraw_required; /**< whether a forcable screen redraw is required */
|
||||
unsigned char disposal_method; /**< how the previous frame should be disposed; affects plotting */
|
||||
bool transparency; /**< whether we acknoledge transparency */
|
||||
unsigned char transparency_index; /**< the index designating a transparent pixel */
|
||||
unsigned int redraw_x; /**< x co-ordinate of redraw rectangle */
|
||||
unsigned int redraw_y; /**< y co-ordinate of redraw rectangle */
|
||||
unsigned int redraw_width; /**< width of redraw rectangle */
|
||||
unsigned int redraw_height; /**< height of redraw rectangle */
|
||||
} gif_frame;
|
||||
|
||||
/* API for Bitmap callbacks
|
||||
*/
|
||||
typedef void* (*gif_bitmap_cb_create)(int width, int height);
|
||||
typedef void (*gif_bitmap_cb_destroy)(void *bitmap);
|
||||
typedef unsigned char* (*gif_bitmap_cb_get_buffer)(void *bitmap);
|
||||
typedef void (*gif_bitmap_cb_set_opaque)(void *bitmap, bool opaque);
|
||||
typedef bool (*gif_bitmap_cb_test_opaque)(void *bitmap);
|
||||
typedef void (*gif_bitmap_cb_modified)(void *bitmap);
|
||||
|
||||
/* The Bitmap callbacks function table
|
||||
*/
|
||||
typedef struct gif_bitmap_callback_vt {
|
||||
gif_bitmap_cb_create bitmap_create; /**< Create a bitmap. */
|
||||
gif_bitmap_cb_destroy bitmap_destroy; /**< Free a bitmap. */
|
||||
gif_bitmap_cb_get_buffer bitmap_get_buffer; /**< Return a pointer to the pixel data in a bitmap. */
|
||||
/** Members below are optional
|
||||
*/
|
||||
gif_bitmap_cb_set_opaque bitmap_set_opaque; /**< Sets whether a bitmap should be plotted opaque. */
|
||||
gif_bitmap_cb_test_opaque bitmap_test_opaque; /**< Tests whether a bitmap has an opaque alpha channel. */
|
||||
gif_bitmap_cb_modified bitmap_modified; /**< The bitmap image has changed, so flush any persistant cache. */
|
||||
} gif_bitmap_callback_vt;
|
||||
|
||||
/* The GIF animation data
|
||||
*/
|
||||
typedef struct gif_animation {
|
||||
gif_bitmap_callback_vt bitmap_callbacks; /**< callbacks for bitmap functions */
|
||||
unsigned char *gif_data; /**< pointer to GIF data */
|
||||
unsigned int width; /**< width of GIF (may increase during decoding) */
|
||||
unsigned int height; /**< heigth of GIF (may increase during decoding) */
|
||||
unsigned int frame_count; /**< number of frames decoded */
|
||||
unsigned int frame_count_partial; /**< number of frames partially decoded */
|
||||
gif_frame *frames; /**< decoded frames */
|
||||
int decoded_frame; /**< current frame decoded to bitmap */
|
||||
void *frame_image; /**< currently decoded image; stored as bitmap from bitmap_create callback */
|
||||
int loop_count; /**< number of times to loop animation */
|
||||
gif_result current_error; /**< current error type, or 0 for none*/
|
||||
/** Internal members are listed below
|
||||
*/
|
||||
unsigned int buffer_position; /**< current index into GIF data */
|
||||
unsigned int buffer_size; /**< total number of bytes of GIF data available */
|
||||
unsigned int frame_holders; /**< current number of frame holders */
|
||||
unsigned int background_index; /**< index in the colour table for the background colour */
|
||||
unsigned int aspect_ratio; /**< image aspect ratio (ignored) */
|
||||
unsigned int colour_table_size; /**< size of colour table (in entries) */
|
||||
bool global_colours; /**< whether the GIF has a global colour table */
|
||||
unsigned int *global_colour_table; /**< global colour table */
|
||||
unsigned int *local_colour_table; /**< local colour table */
|
||||
|
||||
|
||||
/* General LZW values. They are NO LONGER shared for all GIFs being decoded BECAUSE
|
||||
THAT IS A TERRIBLE IDEA TO SAVE 10Kb or so per GIF.
|
||||
*/
|
||||
unsigned char buf[4];
|
||||
unsigned char *direct;
|
||||
|
||||
int table[2][(1 << GIF_MAX_LZW)];
|
||||
unsigned char stack[(1 << GIF_MAX_LZW) * 2];
|
||||
unsigned char *stack_pointer;
|
||||
int code_size, set_code_size;
|
||||
int max_code, max_code_size;
|
||||
int clear_code, end_code;
|
||||
int curbit, lastbit, last_byte;
|
||||
int firstcode, oldcode;
|
||||
bool zero_data_block;
|
||||
bool get_done;
|
||||
|
||||
/* Whether to clear the decoded image rather than plot
|
||||
*/
|
||||
bool clear_image;
|
||||
} gif_animation;
|
||||
|
||||
void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
|
||||
gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data);
|
||||
gif_result gif_decode_frame(gif_animation *gif, unsigned int frame);
|
||||
void gif_finalise(gif_animation *gif);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
45
libobs/graphics/math-defs.h
Normal file
45
libobs/graphics/math-defs.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795f
|
||||
#endif
|
||||
|
||||
#define RAD(val) ((val)*0.0174532925199432957692369076848f)
|
||||
#define DEG(val) ((val)*57.295779513082320876798154814105f)
|
||||
#define LARGE_EPSILON 1e-2f
|
||||
#define EPSILON 1e-4f
|
||||
#define TINY_EPSILON 1e-5f
|
||||
#define M_INFINITE 3.4e38f
|
||||
|
||||
static inline bool close_float(float f1, float f2, float precision)
|
||||
{
|
||||
return fabsf(f1-f2) <= precision;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
133
libobs/graphics/math-extra.c
Normal file
133
libobs/graphics/math-extra.c
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "vec2.h"
|
||||
#include "vec3.h"
|
||||
#include "math-defs.h"
|
||||
#include "math-extra.h"
|
||||
|
||||
void polar_to_cart(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
struct vec3 cart;
|
||||
float sinx = cosf(v->x);
|
||||
float sinx_z = v->z * sinx;
|
||||
|
||||
cart.x = sinx_z * sinf(v->y);
|
||||
cart.z = sinx_z * cosf(v->y);
|
||||
cart.y = v->z * sinf(v->x);
|
||||
|
||||
vec3_copy(dst, &cart);
|
||||
}
|
||||
|
||||
void cart_to_polar(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
struct vec3 polar;
|
||||
polar.z = vec3_len(v);
|
||||
|
||||
if (close_float(polar.z, 0.0f, EPSILON)) {
|
||||
vec3_zero(&polar);
|
||||
} else {
|
||||
polar.x = asinf(v->y / polar.z);
|
||||
polar.y = atan2f(v->x, v->z);
|
||||
}
|
||||
|
||||
vec3_copy(dst, &polar);
|
||||
}
|
||||
|
||||
void norm_to_polar(struct vec2 *dst, const struct vec3 *norm)
|
||||
{
|
||||
dst->x = atan2f(norm->x, norm->z);
|
||||
dst->y = asinf(norm->y);
|
||||
}
|
||||
|
||||
void polar_to_norm(struct vec3 *dst, const struct vec2 *polar)
|
||||
{
|
||||
float sinx = sinf(polar->x);
|
||||
|
||||
dst->x = sinx * cosf(polar->y);
|
||||
dst->y = sinx * sinf(polar->y);
|
||||
dst->z = cosf(polar->x);
|
||||
}
|
||||
|
||||
float calc_torquef(float val1, float val2, float torque, float min_adjust,
|
||||
float t)
|
||||
{
|
||||
float out = val1;
|
||||
float dist;
|
||||
bool over;
|
||||
|
||||
if (close_float(val1, val2, EPSILON))
|
||||
return val1;
|
||||
|
||||
dist = (val2-val1)*torque;
|
||||
over = dist > 0.0f;
|
||||
|
||||
if (over) {
|
||||
if (dist < min_adjust) /* prevents from going too slow */
|
||||
dist = min_adjust;
|
||||
out += dist*t; /* add torque */
|
||||
if (out > val2) /* clamp if overshoot */
|
||||
out = val2;
|
||||
} else {
|
||||
if (dist > -min_adjust)
|
||||
dist = -min_adjust;
|
||||
out += dist*t;
|
||||
if (out < val2)
|
||||
out = val2;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void calc_torque(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2, float torque, float min_adjust,
|
||||
float t)
|
||||
{
|
||||
struct vec3 line, dir;
|
||||
float orig_dist, torque_dist, adjust_dist;
|
||||
|
||||
if (vec3_close(v1, v2, EPSILON)) {
|
||||
vec3_copy(dst, v1);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3_sub(&line, v2, v1);
|
||||
orig_dist = vec3_len(&line);
|
||||
vec3_mulf(&dir, &line, 1.0f/orig_dist);
|
||||
|
||||
torque_dist = orig_dist*torque; /* use distance to determine speed */
|
||||
if (torque_dist < min_adjust) /* prevent from going too slow */
|
||||
torque_dist = min_adjust;
|
||||
|
||||
adjust_dist = torque_dist*t;
|
||||
|
||||
if (adjust_dist <= (orig_dist-LARGE_EPSILON)) {
|
||||
vec3_mulf(dst, &dir, adjust_dist);
|
||||
vec3_add(dst, dst, v1); /* add torque */
|
||||
} else {
|
||||
vec3_copy(dst, v2); /* clamp if overshoot */
|
||||
}
|
||||
}
|
||||
|
||||
float rand_float(int positive_only)
|
||||
{
|
||||
if (positive_only)
|
||||
return (float)((double)rand()/(double)RAND_MAX);
|
||||
else
|
||||
return (float)(((double)rand()/(double)RAND_MAX*2.0)-1.0);
|
||||
}
|
||||
63
libobs/graphics/math-extra.h
Normal file
63
libobs/graphics/math-extra.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
|
||||
/*
|
||||
* A few general math functions that I couldn't really decide where to put.
|
||||
*
|
||||
* Polar/Cart conversion, torque functions (for smooth movement), percentage,
|
||||
* random floats.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct vec2;
|
||||
struct vec3;
|
||||
|
||||
EXPORT void polar_to_cart(struct vec3 *dst, const struct vec3 *v);
|
||||
EXPORT void cart_to_polar(struct vec3 *dst, const struct vec3 *v);
|
||||
|
||||
EXPORT void norm_to_polar(struct vec2 *dst, const struct vec3 *norm);
|
||||
EXPORT void polar_to_norm(struct vec3 *dst, const struct vec2 *polar);
|
||||
|
||||
EXPORT float calc_torquef(float val1, float val2, float torque,
|
||||
float min_adjust, float t);
|
||||
|
||||
EXPORT void calc_torque(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2, float torque, float min_adjust,
|
||||
float t);
|
||||
|
||||
static inline float get_percentage(float start, float end, float mid)
|
||||
{
|
||||
return (mid-start) / (end-start);
|
||||
}
|
||||
|
||||
static inline float get_percentagei(int start, int end, int mid)
|
||||
{
|
||||
return (float)(mid-start) / (float)(end-start);
|
||||
}
|
||||
|
||||
EXPORT float rand_float(int positive_only);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
145
libobs/graphics/matrix3.c
Normal file
145
libobs/graphics/matrix3.c
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "matrix3.h"
|
||||
#include "matrix4.h"
|
||||
#include "plane.h"
|
||||
#include "quat.h"
|
||||
|
||||
|
||||
void matrix3_from_quat(struct matrix3 *dst, const struct quat *q)
|
||||
{
|
||||
float norm = quat_dot(q, q);
|
||||
float s = (norm > 0.0f) ? (2.0f/norm) : 0.0f;
|
||||
|
||||
float xx = q->x * q->x * s;
|
||||
float yy = q->y * q->y * s;
|
||||
float zz = q->z * q->z * s;
|
||||
float xy = q->x * q->y * s;
|
||||
float xz = q->x * q->z * s;
|
||||
float yz = q->y * q->z * s;
|
||||
float wx = q->w * q->x * s;
|
||||
float wy = q->w * q->y * s;
|
||||
float wz = q->w * q->z * s;
|
||||
|
||||
vec3_set(&dst->x, 1.0f - (yy + zz), xy + wz, xz - wy);
|
||||
vec3_set(&dst->y, xy - wz, 1.0f - (xx + zz), yz + wx);
|
||||
vec3_set(&dst->z, xz + wy, yz - wx, 1.0f - (xx + yy));
|
||||
vec3_zero(&dst->t);
|
||||
}
|
||||
|
||||
void matrix3_from_axisang(struct matrix3 *dst, const struct axisang *aa)
|
||||
{
|
||||
struct quat q;
|
||||
quat_from_axisang(&q, aa);
|
||||
matrix3_from_quat(dst, &q);
|
||||
}
|
||||
|
||||
void matrix3_from_matrix4(struct matrix3 *dst, const struct matrix4 *m)
|
||||
{
|
||||
dst->x.m = m->x.m;
|
||||
dst->y.m = m->y.m;
|
||||
dst->z.m = m->z.m;
|
||||
dst->t.m = m->t.m;
|
||||
dst->x.w = 0.0f;
|
||||
dst->y.w = 0.0f;
|
||||
dst->z.w = 0.0f;
|
||||
dst->t.w = 0.0f;
|
||||
}
|
||||
|
||||
void matrix3_mul(struct matrix3 *dst, const struct matrix3 *m1,
|
||||
const struct matrix3 *m2)
|
||||
{
|
||||
if (dst == m2) {
|
||||
struct matrix3 temp;
|
||||
vec3_rotate(&temp.x, &m1->x, m2);
|
||||
vec3_rotate(&temp.y, &m1->y, m2);
|
||||
vec3_rotate(&temp.z, &m1->z, m2);
|
||||
vec3_transform3x4(&temp.t, &m1->t, m2);
|
||||
matrix3_copy(dst, &temp);
|
||||
} else {
|
||||
vec3_rotate(&dst->x, &m1->x, m2);
|
||||
vec3_rotate(&dst->y, &m1->y, m2);
|
||||
vec3_rotate(&dst->z, &m1->z, m2);
|
||||
vec3_transform3x4(&dst->t, &m1->t, m2);
|
||||
}
|
||||
}
|
||||
|
||||
void matrix3_rotate(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct quat *q)
|
||||
{
|
||||
struct matrix3 temp;
|
||||
matrix3_from_quat(&temp, q);
|
||||
matrix3_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix3_rotate_aa(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct axisang *aa)
|
||||
{
|
||||
struct matrix3 temp;
|
||||
matrix3_from_axisang(&temp, aa);
|
||||
matrix3_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix3_scale(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
vec3_mul(&dst->x, &m->x, v);
|
||||
vec3_mul(&dst->y, &m->y, v);
|
||||
vec3_mul(&dst->z, &m->z, v);
|
||||
vec3_mul(&dst->t, &m->t, v);
|
||||
}
|
||||
|
||||
void matrix3_transpose(struct matrix3 *dst, const struct matrix3 *m)
|
||||
{
|
||||
__m128 tmp1, tmp2;
|
||||
vec3_rotate(&dst->t, &m->t, m);
|
||||
vec3_neg(&dst->t, &dst->t);
|
||||
|
||||
tmp1 = _mm_movelh_ps(m->x.m, m->y.m);
|
||||
tmp2 = _mm_movehl_ps(m->y.m, m->x.m);
|
||||
dst->x.m = _mm_shuffle_ps(tmp1, m->z.m, _MM_SHUFFLE(3, 0, 2, 0));
|
||||
dst->y.m = _mm_shuffle_ps(tmp1, m->z.m, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
dst->z.m = _mm_shuffle_ps(tmp2, m->z.m, _MM_SHUFFLE(3, 2, 2, 0));
|
||||
}
|
||||
|
||||
void matrix3_inv(struct matrix3 *dst, const struct matrix3 *m)
|
||||
{
|
||||
struct matrix4 m4;
|
||||
matrix4_from_matrix3(&m4, m);
|
||||
matrix4_inv((struct matrix4*)dst, &m4);
|
||||
dst->t.w = 0.0f;
|
||||
}
|
||||
|
||||
void matrix3_mirror(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct plane *p)
|
||||
{
|
||||
vec3_mirrorv(&dst->x, &m->x, &p->dir);
|
||||
vec3_mirrorv(&dst->y, &m->y, &p->dir);
|
||||
vec3_mirrorv(&dst->z, &m->z, &p->dir);
|
||||
vec3_mirror(&dst->t, &m->t, p);
|
||||
}
|
||||
|
||||
void matrix3_mirrorv(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
vec3_mirrorv(&dst->x, &m->x, v);
|
||||
vec3_mirrorv(&dst->y, &m->y, v);
|
||||
vec3_mirrorv(&dst->z, &m->z, v);
|
||||
vec3_mirrorv(&dst->t, &m->t, v);
|
||||
}
|
||||
108
libobs/graphics/matrix3.h
Normal file
108
libobs/graphics/matrix3.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vec3.h"
|
||||
#include "axisang.h"
|
||||
|
||||
/* 3x4 Matrix */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct matrix4;
|
||||
|
||||
struct matrix3 {
|
||||
struct vec3 x;
|
||||
struct vec3 y;
|
||||
struct vec3 z;
|
||||
struct vec3 t;
|
||||
};
|
||||
|
||||
static inline void matrix3_copy(struct matrix3 *dst, const struct matrix3 *m)
|
||||
{
|
||||
vec3_copy(&dst->x, &m->x);
|
||||
vec3_copy(&dst->y, &m->y);
|
||||
vec3_copy(&dst->z, &m->z);
|
||||
vec3_copy(&dst->t, &m->t);
|
||||
}
|
||||
|
||||
static inline void matrix3_identity(struct matrix3 *dst)
|
||||
{
|
||||
vec3_zero(&dst->x);
|
||||
vec3_zero(&dst->y);
|
||||
vec3_zero(&dst->z);
|
||||
vec3_zero(&dst->t);
|
||||
dst->x.x = dst->y.y = dst->z.z = 1.0f;
|
||||
}
|
||||
|
||||
EXPORT void matrix3_from_quat(struct matrix3 *dst, const struct quat *q);
|
||||
EXPORT void matrix3_from_axisang(struct matrix3 *dst,
|
||||
const struct axisang *aa);
|
||||
EXPORT void matrix3_from_matrix4(struct matrix3 *dst, const struct matrix4 *m);
|
||||
|
||||
EXPORT void matrix3_mul(struct matrix3 *dst, const struct matrix3 *m1,
|
||||
const struct matrix3 *m2);
|
||||
static inline void matrix3_translate(struct matrix3 *dst,
|
||||
const struct matrix3 *m, const struct vec3 *v)
|
||||
{
|
||||
vec3_sub(&dst->t, &m->t, v);
|
||||
}
|
||||
|
||||
EXPORT void matrix3_rotate(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct quat *q);
|
||||
EXPORT void matrix3_rotate_aa(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct axisang *aa);
|
||||
EXPORT void matrix3_scale(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct vec3 *v);
|
||||
EXPORT void matrix3_transpose(struct matrix3 *dst, const struct matrix3 *m);
|
||||
EXPORT void matrix3_inv(struct matrix3 *dst, const struct matrix3 *m);
|
||||
|
||||
EXPORT void matrix3_mirror(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct plane *p);
|
||||
EXPORT void matrix3_mirrorv(struct matrix3 *dst, const struct matrix3 *m,
|
||||
const struct vec3 *v);
|
||||
|
||||
static inline void matrix3_translate3f(struct matrix3 *dst,
|
||||
const struct matrix3 *m, float x, float y, float z)
|
||||
{
|
||||
struct vec3 v;
|
||||
vec3_set(&v, x, y, z);
|
||||
matrix3_translate(dst, m, &v);
|
||||
}
|
||||
|
||||
static inline void matrix3_rotate_aa4f(struct matrix3 *dst,
|
||||
const struct matrix3 *m, float x, float y, float z, float rot)
|
||||
{
|
||||
struct axisang aa;
|
||||
axisang_set(&aa, x, y, z, rot);
|
||||
matrix3_rotate_aa(dst, m, &aa);
|
||||
}
|
||||
|
||||
static inline void matrix3_scale3f(struct matrix3 *dst,
|
||||
const struct matrix3 *m, float x, float y, float z)
|
||||
{
|
||||
struct vec3 v;
|
||||
vec3_set(&v, x, y, z);
|
||||
matrix3_scale(dst, m, &v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
285
libobs/graphics/matrix4.c
Normal file
285
libobs/graphics/matrix4.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "math-defs.h"
|
||||
#include "matrix4.h"
|
||||
#include "matrix3.h"
|
||||
#include "quat.h"
|
||||
|
||||
void matrix4_from_matrix3(struct matrix4 *dst, const struct matrix3 *m)
|
||||
{
|
||||
dst->x.m = m->x.m;
|
||||
dst->y.m = m->y.m;
|
||||
dst->z.m = m->z.m;
|
||||
dst->t.m = m->t.m;
|
||||
dst->t.w = 1.0f;
|
||||
}
|
||||
|
||||
void matrix4_from_quat(struct matrix4 *dst, const struct quat *q)
|
||||
{
|
||||
float norm = quat_dot(q, q);
|
||||
float s = (norm > 0.0f) ? (2.0f/norm) : 0.0f;
|
||||
|
||||
float xx = q->x * q->x * s;
|
||||
float yy = q->y * q->y * s;
|
||||
float zz = q->z * q->z * s;
|
||||
float xy = q->x * q->y * s;
|
||||
float xz = q->x * q->z * s;
|
||||
float yz = q->y * q->z * s;
|
||||
float wx = q->w * q->x * s;
|
||||
float wy = q->w * q->y * s;
|
||||
float wz = q->w * q->z * s;
|
||||
|
||||
vec4_set(&dst->x, 1.0f - (yy + zz), xy + wz, xz - wy, 0.0f);
|
||||
vec4_set(&dst->y, xy - wz, 1.0f - (xx + zz), yz + wx, 0.0f);
|
||||
vec4_set(&dst->z, xz + wy, yz - wx, 1.0f - (xx + yy), 0.0f);
|
||||
vec4_set(&dst->t, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void matrix4_from_axisang(struct matrix4 *dst, const struct axisang *aa)
|
||||
{
|
||||
struct quat q;
|
||||
quat_from_axisang(&q, aa);
|
||||
matrix4_from_quat(dst, &q);
|
||||
}
|
||||
|
||||
void matrix4_mul(struct matrix4 *dst, const struct matrix4 *m1,
|
||||
const struct matrix4 *m2)
|
||||
{
|
||||
const struct vec4 *m1v = (const struct vec4*)m1;
|
||||
const float *m2f = (const float*)m2;
|
||||
struct vec4 out[4];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
struct vec4 temp;
|
||||
vec4_set(&temp, m2f[j], m2f[j+4], m2f[j+8], m2f[j+12]);
|
||||
out[i].ptr[j] = vec4_dot(&m1v[i], &temp);
|
||||
}
|
||||
}
|
||||
|
||||
matrix4_copy(dst, (struct matrix4*)out);
|
||||
}
|
||||
|
||||
static inline void get_3x3_submatrix(float *dst, const struct matrix4 *m,
|
||||
int i, int j)
|
||||
{
|
||||
const float *mf = (const float *)m;
|
||||
int ti, tj, idst, jdst;
|
||||
|
||||
for (ti = 0; ti < 4; ti++) {
|
||||
if (ti < i)
|
||||
idst = ti;
|
||||
else if (ti > i)
|
||||
idst = ti-1;
|
||||
else
|
||||
continue;
|
||||
|
||||
for (tj = 0; tj < 4; tj++) {
|
||||
if (tj < j)
|
||||
jdst = tj;
|
||||
else if (tj > j)
|
||||
jdst = tj-1;
|
||||
else
|
||||
continue;
|
||||
|
||||
dst[(idst*3) + jdst] = mf[(ti*4) + tj];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline float get_3x3_determinant(const float *m)
|
||||
{
|
||||
return (m[0] * ((m[4]*m[8]) - (m[7]*m[5]))) -
|
||||
(m[1] * ((m[3]*m[8]) - (m[6]*m[5]))) +
|
||||
(m[2] * ((m[3]*m[7]) - (m[6]*m[4])));
|
||||
}
|
||||
|
||||
float matrix4_determinant(const struct matrix4 *m)
|
||||
{
|
||||
const float *mf = (const float *)m;
|
||||
float det, result = 0.0f, i = 1.0f;
|
||||
float m3x3[9];
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 4; n++, i *= -1.0f) {
|
||||
get_3x3_submatrix(m3x3, m, 0, n);
|
||||
|
||||
det = get_3x3_determinant(m3x3);
|
||||
result += mf[n] * det * i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void matrix4_translate3v(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, 1.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
vec4_from_vec3(&temp.t, v);
|
||||
|
||||
matrix4_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix4_translate4v(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec4 *v)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, 1.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
vec4_copy(&temp.t, v);
|
||||
|
||||
matrix4_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix4_rotate(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct quat *q)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
matrix4_from_quat(&temp, q);
|
||||
matrix4_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix4_rotate_aa(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct axisang *aa)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
matrix4_from_axisang(&temp, aa);
|
||||
matrix4_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix4_scale(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec3 *v)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, v->x, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, v->y, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, v->z, 0.0f);
|
||||
vec4_set(&temp.t, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
matrix4_mul(dst, m, &temp);
|
||||
}
|
||||
|
||||
void matrix4_translate3v_i(struct matrix4 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, 1.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
vec4_from_vec3(&temp.t, v);
|
||||
|
||||
matrix4_mul(dst, &temp, m);
|
||||
}
|
||||
|
||||
void matrix4_translate4v_i(struct matrix4 *dst, const struct vec4 *v,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, 1.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||
vec4_copy(&temp.t, v);
|
||||
|
||||
matrix4_mul(dst, &temp, m);
|
||||
}
|
||||
|
||||
void matrix4_rotate_i(struct matrix4 *dst, const struct quat *q,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
matrix4_from_quat(&temp, q);
|
||||
matrix4_mul(dst, &temp, m);
|
||||
}
|
||||
|
||||
void matrix4_rotate_aa_i(struct matrix4 *dst, const struct axisang *aa,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
matrix4_from_axisang(&temp, aa);
|
||||
matrix4_mul(dst, &temp, m);
|
||||
}
|
||||
|
||||
void matrix4_scale_i(struct matrix4 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
vec4_set(&temp.x, v->x, 0.0f, 0.0f, 0.0f);
|
||||
vec4_set(&temp.y, 0.0f, v->y, 0.0f, 0.0f);
|
||||
vec4_set(&temp.z, 0.0f, 0.0f, v->z, 0.0f);
|
||||
vec4_set(&temp.t, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
matrix4_mul(dst, &temp, m);
|
||||
}
|
||||
|
||||
bool matrix4_inv(struct matrix4 *dst, const struct matrix4 *m)
|
||||
{
|
||||
struct vec4 *dstv = (struct vec4 *)dst;
|
||||
float det = matrix4_determinant(m);
|
||||
float m3x3[9];
|
||||
int i, j, sign;
|
||||
|
||||
if (dst == m) {
|
||||
struct matrix4 temp = *m;
|
||||
return matrix4_inv(dst, &temp);
|
||||
}
|
||||
|
||||
dstv = (struct vec4 *)dst;
|
||||
det = matrix4_determinant(m);
|
||||
|
||||
if (fabs(det) < 0.0005f)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
sign = 1 - ((i+j) % 2) * 2;
|
||||
get_3x3_submatrix(m3x3, m, i, j);
|
||||
dstv[j].ptr[i] = get_3x3_determinant(m3x3) *
|
||||
(float)sign / det;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void matrix4_transpose(struct matrix4 *dst, const struct matrix4 *m)
|
||||
{
|
||||
struct matrix4 temp;
|
||||
|
||||
/* TODO: Add SSE */
|
||||
temp.x.x = m->x.x;
|
||||
temp.x.y = m->y.x;
|
||||
temp.x.z = m->z.x;
|
||||
temp.x.w = m->t.x;
|
||||
temp.y.x = m->x.y;
|
||||
temp.y.y = m->y.y;
|
||||
temp.y.z = m->z.y;
|
||||
temp.y.w = m->t.y;
|
||||
temp.z.x = m->x.z;
|
||||
temp.z.y = m->y.z;
|
||||
temp.z.z = m->z.z;
|
||||
temp.z.w = m->t.z;
|
||||
temp.t.x = m->x.w;
|
||||
temp.t.y = m->y.w;
|
||||
temp.t.z = m->z.w;
|
||||
temp.t.w = m->t.w;
|
||||
|
||||
matrix4_copy(dst, &temp);
|
||||
}
|
||||
116
libobs/graphics/matrix4.h
Normal file
116
libobs/graphics/matrix4.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vec3.h"
|
||||
#include "vec4.h"
|
||||
#include "axisang.h"
|
||||
|
||||
/* 4x4 Matrix */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct matrix3;
|
||||
|
||||
struct matrix4 {
|
||||
struct vec4 x, y, z, t;
|
||||
};
|
||||
|
||||
static inline void matrix4_copy(struct matrix4 *dst, const struct matrix4 *m)
|
||||
{
|
||||
dst->x.m = m->x.m;
|
||||
dst->y.m = m->y.m;
|
||||
dst->z.m = m->z.m;
|
||||
dst->t.m = m->t.m;
|
||||
}
|
||||
|
||||
static inline void matrix4_identity(struct matrix4 *dst)
|
||||
{
|
||||
vec4_zero(&dst->x);
|
||||
vec4_zero(&dst->y);
|
||||
vec4_zero(&dst->z);
|
||||
vec4_zero(&dst->t);
|
||||
dst->x.x = 1.0f;
|
||||
dst->y.y = 1.0f;
|
||||
dst->z.z = 1.0f;
|
||||
dst->t.w = 1.0f;
|
||||
}
|
||||
|
||||
EXPORT void matrix4_from_matrix3(struct matrix4 *dst, const struct matrix3 *m);
|
||||
EXPORT void matrix4_from_quat(struct matrix4 *dst, const struct quat *q);
|
||||
EXPORT void matrix4_from_axisang(struct matrix4 *dst,
|
||||
const struct axisang *aa);
|
||||
|
||||
EXPORT void matrix4_mul(struct matrix4 *dst, const struct matrix4 *m1,
|
||||
const struct matrix4 *m2);
|
||||
|
||||
EXPORT float matrix4_determinant(const struct matrix4 *m);
|
||||
|
||||
EXPORT void matrix4_translate3v(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec3 *v);
|
||||
EXPORT void matrix4_translate4v(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec4 *v);
|
||||
EXPORT void matrix4_rotate(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct quat *q);
|
||||
EXPORT void matrix4_rotate_aa(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct axisang *aa);
|
||||
EXPORT void matrix4_scale(struct matrix4 *dst, const struct matrix4 *m,
|
||||
const struct vec3 *v);
|
||||
EXPORT bool matrix4_inv(struct matrix4 *dst, const struct matrix4 *m);
|
||||
EXPORT void matrix4_transpose(struct matrix4 *dst, const struct matrix4 *m);
|
||||
|
||||
EXPORT void matrix4_translate3v_i(struct matrix4 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void matrix4_translate4v_i(struct matrix4 *dst, const struct vec4 *v,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void matrix4_rotate_i(struct matrix4 *dst, const struct quat *q,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void matrix4_rotate_aa_i(struct matrix4 *dst, const struct axisang *aa,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void matrix4_scale_i(struct matrix4 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m);
|
||||
|
||||
static inline void matrix4_translate3f(struct matrix4 *dst,
|
||||
const struct matrix4 *m, float x, float y, float z)
|
||||
{
|
||||
struct vec3 v;
|
||||
vec3_set(&v, x, y, z);
|
||||
matrix4_translate3v(dst, m, &v);
|
||||
}
|
||||
|
||||
static inline void matrix4_rotate_aa4f(struct matrix4 *dst,
|
||||
const struct matrix4 *m, float x, float y, float z, float rot)
|
||||
{
|
||||
struct axisang aa;
|
||||
axisang_set(&aa, x, y, z, rot);
|
||||
matrix4_rotate_aa(dst, m, &aa);
|
||||
}
|
||||
|
||||
static inline void matrix4_scale3f(struct matrix4 *dst,
|
||||
const struct matrix4 *m, float x, float y, float z)
|
||||
{
|
||||
struct vec3 v;
|
||||
vec3_set(&v, x, y, z);
|
||||
matrix4_scale(dst, m, &v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
162
libobs/graphics/plane.c
Normal file
162
libobs/graphics/plane.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
#include "matrix3.h"
|
||||
#include "plane.h"
|
||||
|
||||
void plane_from_tri(struct plane *dst,
|
||||
const struct vec3 *v1,
|
||||
const struct vec3 *v2,
|
||||
const struct vec3 *v3)
|
||||
{
|
||||
struct vec3 temp;
|
||||
|
||||
vec3_sub(&temp, v2, v1);
|
||||
vec3_sub(&dst->dir, v3, v1);
|
||||
vec3_cross(&dst->dir, &temp, &dst->dir);
|
||||
vec3_norm(&dst->dir, &dst->dir);
|
||||
dst->dist = vec3_dot(v1, &dst->dir);
|
||||
}
|
||||
|
||||
void plane_transform(struct plane *dst, const struct plane *p,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct vec3 temp;
|
||||
|
||||
vec3_zero(&temp);
|
||||
|
||||
vec3_transform(&dst->dir, &p->dir, m);
|
||||
vec3_norm(&dst->dir, &dst->dir);
|
||||
|
||||
vec3_transform(&temp, &temp, m);
|
||||
dst->dist = p->dist - vec3_dot(&dst->dir, &temp);
|
||||
}
|
||||
|
||||
void plane_transform3x4(struct plane *dst, const struct plane *p,
|
||||
const struct matrix3 *m)
|
||||
{
|
||||
struct vec3 temp;
|
||||
|
||||
vec3_transform3x4(&dst->dir, &p->dir, m);
|
||||
vec3_norm(&dst->dir, &dst->dir);
|
||||
|
||||
vec3_transform3x4(&temp, &m->t, m);
|
||||
dst->dist = p->dist - vec3_dot(&dst->dir, &temp);
|
||||
}
|
||||
|
||||
bool plane_intersection_ray(const struct plane *p, const struct vec3 *orig,
|
||||
const struct vec3 *dir, float *t)
|
||||
{
|
||||
float c = vec3_dot(&p->dir, dir);
|
||||
|
||||
if (fabsf(c) < EPSILON) {
|
||||
*t = 0.0f;
|
||||
return false;
|
||||
} else {
|
||||
*t = (p->dist - vec3_dot(&p->dir, orig)) / c;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool plane_intersection_line(const struct plane *p, const struct vec3 *v1,
|
||||
const struct vec3 *v2, float *t)
|
||||
{
|
||||
float p1_dist, p2_dist, p1_abs_dist, dist2;
|
||||
bool p1_over, p2_over;
|
||||
|
||||
p1_dist = vec3_plane_dist(v1, p);
|
||||
p2_dist = vec3_plane_dist(v2, p);
|
||||
|
||||
if (close_float(p1_dist, 0.0f, EPSILON)) {
|
||||
if (close_float(p2_dist, 0.0f, EPSILON))
|
||||
return false;
|
||||
|
||||
*t = 0.0f;
|
||||
return true;
|
||||
} else if (close_float(p2_dist, 0.0f, EPSILON)) {
|
||||
*t = 1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
p1_over = (p1_dist > 0.0f);
|
||||
p2_over = (p2_dist > 0.0f);
|
||||
|
||||
if (p1_over == p2_over)
|
||||
return false;
|
||||
|
||||
p1_abs_dist = fabsf(p1_dist);
|
||||
dist2 = p1_abs_dist + fabsf(p2_dist);
|
||||
if (dist2 < EPSILON)
|
||||
return false;
|
||||
|
||||
*t = p1_abs_dist / dist2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool plane_tri_inside(const struct plane *p,
|
||||
const struct vec3 *v1,
|
||||
const struct vec3 *v2,
|
||||
const struct vec3 *v3,
|
||||
float precision)
|
||||
{
|
||||
/* bit 1: part or all is behind the plane */
|
||||
/* bit 2: part or all is in front of the plane */
|
||||
int sides = 0;
|
||||
float d1 = vec3_plane_dist(v1, p);
|
||||
float d2 = vec3_plane_dist(v2, p);
|
||||
float d3 = vec3_plane_dist(v3, p);
|
||||
|
||||
if (d1 >= precision)
|
||||
sides = 2;
|
||||
else if (d1 <= -precision)
|
||||
sides = 1;
|
||||
|
||||
if (d2 >= precision)
|
||||
sides |= 2;
|
||||
else if (d2 <= -precision)
|
||||
sides |= 1;
|
||||
|
||||
if (d3 >= precision)
|
||||
sides |= 2;
|
||||
else if (d3 <= -precision)
|
||||
sides |= 1;
|
||||
|
||||
return sides;
|
||||
}
|
||||
|
||||
bool plane_line_inside(const struct plane *p, const struct vec3 *v1,
|
||||
const struct vec3 *v2, float precision)
|
||||
{
|
||||
/* bit 1: part or all is behind the plane */
|
||||
/* bit 2: part or all is in front of the plane */
|
||||
int sides = 0;
|
||||
float d1 = vec3_plane_dist(v1, p);
|
||||
float d2 = vec3_plane_dist(v2, p);
|
||||
|
||||
if (d1 >= precision)
|
||||
sides = 2;
|
||||
else if (d1 <= -precision)
|
||||
sides = 1;
|
||||
|
||||
if (d2 >= precision)
|
||||
sides |= 2;
|
||||
else if (d2 <= -precision)
|
||||
sides |= 1;
|
||||
|
||||
return sides;
|
||||
}
|
||||
101
libobs/graphics/plane.h
Normal file
101
libobs/graphics/plane.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math-defs.h"
|
||||
#include "vec3.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct matrix3;
|
||||
struct matrix4;
|
||||
|
||||
struct plane {
|
||||
struct vec3 dir;
|
||||
float dist;
|
||||
};
|
||||
|
||||
static inline void plane_copy(struct plane *dst, const struct plane *p)
|
||||
{
|
||||
vec3_copy(&dst->dir, &p->dir);
|
||||
dst->dist = p->dist;
|
||||
}
|
||||
|
||||
static inline void plane_set(struct plane *dst, const struct vec3 *dir,
|
||||
float dist)
|
||||
{
|
||||
vec3_copy(&dst->dir, dir);
|
||||
dst->dist = dist;
|
||||
}
|
||||
|
||||
static inline void plane_setf(struct plane *dst, float a, float b, float c,
|
||||
float d)
|
||||
{
|
||||
vec3_set(&dst->dir, a, b, c);
|
||||
dst->dist = d;
|
||||
}
|
||||
|
||||
EXPORT void plane_from_tri(struct plane *dst,
|
||||
const struct vec3 *v1,
|
||||
const struct vec3 *v2,
|
||||
const struct vec3 *v3);
|
||||
|
||||
EXPORT void plane_transform(struct plane *dst, const struct plane *p,
|
||||
const struct matrix4 *m);
|
||||
EXPORT void plane_transform3x4(struct plane *dst, const struct plane *p,
|
||||
const struct matrix3 *m);
|
||||
|
||||
EXPORT bool plane_intersection_ray(const struct plane *p,
|
||||
const struct vec3 *orig, const struct vec3 *dir, float *t);
|
||||
EXPORT bool plane_intersection_line(const struct plane *p,
|
||||
const struct vec3 *v1, const struct vec3 *v2, float *t);
|
||||
|
||||
EXPORT bool plane_tri_inside(const struct plane *p,
|
||||
const struct vec3 *v1,
|
||||
const struct vec3 *v2,
|
||||
const struct vec3 *v3,
|
||||
float precision);
|
||||
|
||||
EXPORT bool plane_line_inside(const struct plane *p, const struct vec3 *v1,
|
||||
const struct vec3 *v2, float precision);
|
||||
|
||||
static inline bool plane_close(const struct plane *p1, const struct plane *p2,
|
||||
float precision)
|
||||
{
|
||||
return vec3_close(&p1->dir, &p2->dir, precision) &&
|
||||
close_float(p1->dist, p2->dist, precision);
|
||||
}
|
||||
|
||||
static inline bool plane_coplanar(const struct plane *p1,
|
||||
const struct plane *p2, float precision)
|
||||
{
|
||||
float cos_angle = vec3_dot(&p1->dir, &p2->dir);
|
||||
|
||||
if (close_float(cos_angle, 1.0f, precision))
|
||||
return close_float(p1->dist, p2->dist, precision);
|
||||
else if (close_float(cos_angle, -1.0f, precision))
|
||||
return close_float(-p1->dist, p2->dist, precision);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
222
libobs/graphics/quat.c
Normal file
222
libobs/graphics/quat.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "quat.h"
|
||||
#include "vec3.h"
|
||||
#include "matrix3.h"
|
||||
#include "matrix4.h"
|
||||
#include "axisang.h"
|
||||
|
||||
static inline void quat_vec3(struct vec3 *v, const struct quat *q)
|
||||
{
|
||||
v->m = q->m;
|
||||
v->w = 0.0f;
|
||||
}
|
||||
|
||||
void quat_mul(struct quat *dst, const struct quat *q1, const struct quat *q2)
|
||||
{
|
||||
struct vec3 q1axis, q2axis;
|
||||
struct vec3 temp1, temp2;
|
||||
|
||||
quat_vec3(&q1axis, q1);
|
||||
quat_vec3(&q2axis, q2);
|
||||
|
||||
vec3_mulf(&temp1, &q2axis, q1->w);
|
||||
vec3_mulf(&temp2, &q1axis, q2->w);
|
||||
vec3_add(&temp1, &temp1, &temp2);
|
||||
vec3_cross(&temp2, &q1axis, &q2axis);
|
||||
vec3_add((struct vec3 *)dst, &temp1, &temp2);
|
||||
|
||||
dst->w = (q1->w * q2->w) - vec3_dot(&q1axis, &q2axis);
|
||||
}
|
||||
|
||||
void quat_from_axisang(struct quat *dst, const struct axisang *aa)
|
||||
{
|
||||
float halfa = aa->w * 0.5f;
|
||||
float sine = sinf(halfa);
|
||||
|
||||
dst->x = aa->x * sine;
|
||||
dst->y = aa->y * sine;
|
||||
dst->z = aa->z * sine;
|
||||
dst->w = cosf(halfa);
|
||||
}
|
||||
|
||||
struct f4x4 {
|
||||
float ptr[4][4];
|
||||
};
|
||||
|
||||
void quat_from_matrix3(struct quat *dst, const struct matrix3 *m)
|
||||
{
|
||||
quat_from_matrix4(dst, (const struct matrix4*)m);
|
||||
}
|
||||
|
||||
void quat_from_matrix4(struct quat *dst, const struct matrix4 *m)
|
||||
{
|
||||
float tr = (m->x.x + m->y.y + m->z.z);
|
||||
float inv_half;
|
||||
float four_d;
|
||||
int i,j,k;
|
||||
|
||||
if (tr > 0.0f) {
|
||||
four_d = sqrtf(tr + 1.0f);
|
||||
dst->w = four_d * 0.5f;
|
||||
|
||||
inv_half = 0.5f / four_d;
|
||||
dst->x = (m->y.z - m->z.y) * inv_half;
|
||||
dst->y = (m->z.x - m->x.z) * inv_half;
|
||||
dst->z = (m->x.y - m->y.x) * inv_half;
|
||||
} else {
|
||||
struct f4x4 *val = (struct f4x4*)m;
|
||||
|
||||
i = (m->x.x > m->y.y) ? 0 : 1;
|
||||
|
||||
if (m->z.z > val->ptr[i][i])
|
||||
i = 2;
|
||||
|
||||
j = (i+1) % 3;
|
||||
k = (i+2) % 3;
|
||||
|
||||
/* ---------------------------------- */
|
||||
|
||||
four_d = sqrtf((val->ptr[i][i] - val->ptr[j][j] -
|
||||
val->ptr[k][k]) + 1.0f);
|
||||
|
||||
dst->ptr[i] = four_d * 0.5f;
|
||||
|
||||
inv_half = 0.5f / four_d;
|
||||
dst->ptr[j] = (val->ptr[i][j] + val->ptr[j][i]) * inv_half;
|
||||
dst->ptr[k] = (val->ptr[i][k] + val->ptr[k][i]) * inv_half;
|
||||
dst->w = (val->ptr[j][k] - val->ptr[k][j]) * inv_half;
|
||||
}
|
||||
}
|
||||
|
||||
void quat_get_dir(struct vec3 *dst, const struct quat *q)
|
||||
{
|
||||
struct matrix3 m;
|
||||
matrix3_from_quat(&m, q);
|
||||
vec3_copy(dst, &m.z);
|
||||
}
|
||||
|
||||
void quat_set_look_dir(struct quat *dst, const struct vec3 *dir)
|
||||
{
|
||||
struct vec3 new_dir;
|
||||
struct quat xz_rot, yz_rot;
|
||||
bool xz_valid;
|
||||
bool yz_valid;
|
||||
struct axisang aa;
|
||||
|
||||
vec3_norm(&new_dir, dir);
|
||||
vec3_neg(&new_dir, &new_dir);
|
||||
|
||||
quat_identity(&xz_rot);
|
||||
quat_identity(&yz_rot);
|
||||
|
||||
xz_valid = close_float(new_dir.x, 0.0f, EPSILON) ||
|
||||
close_float(new_dir.z, 0.0f, EPSILON);
|
||||
yz_valid = close_float(new_dir.y, 0.0f, EPSILON);
|
||||
|
||||
if (xz_valid) {
|
||||
axisang_set(&aa, 0.0f, 1.0f, 0.0f,
|
||||
atan2f(new_dir.x, new_dir.z));
|
||||
|
||||
quat_from_axisang(&xz_rot, &aa);
|
||||
}
|
||||
if (yz_valid) {
|
||||
axisang_set(&aa, -1.0f, 0.0f, 0.0f, asinf(new_dir.y));
|
||||
quat_from_axisang(&yz_rot, &aa);
|
||||
}
|
||||
|
||||
if (!xz_valid)
|
||||
quat_copy(dst, &yz_rot);
|
||||
else if (!yz_valid)
|
||||
quat_copy(dst, &xz_rot);
|
||||
else
|
||||
quat_mul(dst, &xz_rot, &yz_rot);
|
||||
}
|
||||
|
||||
void quat_log(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
float angle = acosf(q->w);
|
||||
float sine = sinf(angle);
|
||||
float w = q->w;
|
||||
|
||||
quat_copy(dst, q);
|
||||
dst->w = 0.0f;
|
||||
|
||||
if ((fabsf(w) < 1.0f) && (fabsf(sine) >= EPSILON)) {
|
||||
sine = angle/sine;
|
||||
quat_mulf(dst, dst, sine);
|
||||
}
|
||||
}
|
||||
|
||||
void quat_exp(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
float length = sqrtf(q->x*q->x + q->y*q->y + q->z*q->z);
|
||||
float sine = sinf(length);
|
||||
|
||||
quat_copy(dst, q);
|
||||
sine = (length > EPSILON) ? (sine/length) : 1.0f;
|
||||
quat_mulf(dst, dst, sine);
|
||||
dst->w = cosf(length);
|
||||
}
|
||||
|
||||
void quat_interpolate(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2, float t)
|
||||
{
|
||||
float dot = quat_dot(q1, q2);
|
||||
float anglef = acosf(dot);
|
||||
float sine, sinei, sinet, sineti;
|
||||
struct quat temp;
|
||||
|
||||
if (anglef >= EPSILON) {
|
||||
sine = sinf(anglef);
|
||||
sinei = 1/sine;
|
||||
sinet = sinf(anglef*t)*sinei;
|
||||
sineti = sinf(anglef*(1.0f-t))*sinei;
|
||||
|
||||
quat_mulf(&temp, q1, sineti);
|
||||
quat_mulf(dst, q2, sinet);
|
||||
quat_add(dst, &temp, dst);
|
||||
} else {
|
||||
quat_sub(&temp, q2, q1);
|
||||
quat_mulf(&temp, &temp, t);
|
||||
quat_add(dst, &temp, q1);
|
||||
}
|
||||
}
|
||||
|
||||
void quat_get_tangent(struct quat *dst, const struct quat *prev,
|
||||
const struct quat *q, const struct quat *next)
|
||||
{
|
||||
struct quat temp;
|
||||
|
||||
quat_sub(&temp, q, prev);
|
||||
quat_add(&temp, &temp, next);
|
||||
quat_sub(&temp, &temp, q);
|
||||
quat_mulf(dst, &temp, 0.5f);
|
||||
}
|
||||
|
||||
void quat_interpolate_cubic(struct quat *dst,
|
||||
const struct quat *q1, const struct quat *q2,
|
||||
const struct quat *m1, const struct quat *m2,
|
||||
float t)
|
||||
{
|
||||
struct quat temp1, temp2;
|
||||
|
||||
quat_interpolate(&temp1, q1, q2, t);
|
||||
quat_interpolate(&temp2, m1, m2, t);
|
||||
quat_interpolate(dst, &temp1, &temp2, 2.0f*(1.0f-t)*t);
|
||||
}
|
||||
184
libobs/graphics/quat.h
Normal file
184
libobs/graphics/quat.h
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
#include "math-defs.h"
|
||||
#include "vec3.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
/*
|
||||
* Quaternion math
|
||||
*
|
||||
* Generally used to represent rotational data more than anything. Allows
|
||||
* for efficient and correct rotational interpolation without suffering from
|
||||
* things like gimbal lock.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct matrix3;
|
||||
struct matrix4;
|
||||
struct axisang;
|
||||
|
||||
struct quat {
|
||||
union {
|
||||
struct {float x, y, z, w;};
|
||||
float ptr[4];
|
||||
__m128 m;
|
||||
};
|
||||
};
|
||||
|
||||
static inline void quat_identity(struct quat *q)
|
||||
{
|
||||
q->m = _mm_setzero_ps();
|
||||
q->w = 1.0f;
|
||||
}
|
||||
|
||||
static inline void quat_set(struct quat *dst, float x, float y, float z,
|
||||
float w)
|
||||
{
|
||||
dst->m = _mm_set_ps(x, y, z, w);
|
||||
}
|
||||
|
||||
static inline void quat_copy(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
dst->m = q->m;
|
||||
}
|
||||
|
||||
static inline void quat_add(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2)
|
||||
{
|
||||
dst->m = _mm_add_ps(q1->m, q2->m);
|
||||
}
|
||||
|
||||
static inline void quat_sub(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2)
|
||||
{
|
||||
dst->m = _mm_sub_ps(q1->m, q2->m);
|
||||
}
|
||||
|
||||
EXPORT void quat_mul(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2);
|
||||
|
||||
static inline void quat_addf(struct quat *dst, const struct quat *q,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_add_ps(q->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void quat_subf(struct quat *dst, const struct quat *q,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_sub_ps(q->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void quat_mulf(struct quat *dst, const struct quat *q,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_mul_ps(q->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void quat_divf(struct quat *dst, const struct quat *q,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_div_ps(q->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline float quat_dot(const struct quat *q1, const struct quat *q2)
|
||||
{
|
||||
struct vec3 add;
|
||||
__m128 mul = _mm_mul_ps(q1->m, q2->m);
|
||||
add.m = _mm_add_ps(_mm_movehl_ps(mul, mul), mul);
|
||||
add.m = _mm_add_ps(_mm_shuffle_ps(add.m, add.m, 0x55), add.m);
|
||||
return add.x;
|
||||
}
|
||||
|
||||
static inline void quat_inv(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
dst->x = -q->x;
|
||||
dst->y = -q->y;
|
||||
dst->z = -q->z;
|
||||
}
|
||||
|
||||
static inline void quat_neg(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
dst->x = -q->x;
|
||||
dst->y = -q->y;
|
||||
dst->z = -q->z;
|
||||
dst->w = -q->w;
|
||||
}
|
||||
|
||||
static inline float quat_len(const struct quat *q)
|
||||
{
|
||||
float dot_val = quat_dot(q, q);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline float quat_dist(const struct quat *q1, const struct quat *q2)
|
||||
{
|
||||
struct quat temp;
|
||||
float dot_val;
|
||||
|
||||
quat_sub(&temp, q1, q2);
|
||||
dot_val = quat_dot(&temp, &temp);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline void quat_norm(struct quat *dst, const struct quat *q)
|
||||
{
|
||||
float dot_val = quat_dot(q, q);
|
||||
dst->m = (dot_val > 0.0f) ?
|
||||
_mm_mul_ps(q->m, _mm_set1_ps(1.0f/sqrtf(dot_val))) :
|
||||
_mm_setzero_ps();
|
||||
}
|
||||
|
||||
static inline bool quat_close(const struct quat *q1, const struct quat *q2,
|
||||
float epsilon)
|
||||
{
|
||||
struct quat test;
|
||||
quat_sub(&test, q1, q2);
|
||||
return test.x < epsilon &&
|
||||
test.y < epsilon &&
|
||||
test.z < epsilon &&
|
||||
test.w < epsilon;
|
||||
}
|
||||
|
||||
EXPORT void quat_from_axisang(struct quat *dst, const struct axisang *aa);
|
||||
EXPORT void quat_from_matrix3(struct quat *dst, const struct matrix3 *m);
|
||||
EXPORT void quat_from_matrix4(struct quat *dst, const struct matrix4 *m);
|
||||
|
||||
EXPORT void quat_get_dir(struct vec3 *dst, const struct quat *q);
|
||||
EXPORT void quat_set_look_dir(struct quat *dst, const struct vec3 *dir);
|
||||
|
||||
EXPORT void quat_log(struct quat *dst, const struct quat *q);
|
||||
EXPORT void quat_exp(struct quat *dst, const struct quat *q);
|
||||
|
||||
EXPORT void quat_interpolate(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2, float t);
|
||||
EXPORT void quat_get_tangent(struct quat *dst, const struct quat *prev,
|
||||
const struct quat *q, const struct quat *next);
|
||||
EXPORT void quat_interpolate_cubic(struct quat *dst, const struct quat *q1,
|
||||
const struct quat *q2, const struct quat *m1,
|
||||
const struct quat *m2, float t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
693
libobs/graphics/shader-parser.c
Normal file
693
libobs/graphics/shader-parser.c
Normal file
|
|
@ -0,0 +1,693 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "../util/platform.h"
|
||||
#include "shader-parser.h"
|
||||
|
||||
enum gs_shader_param_type get_shader_param_type(const char *type)
|
||||
{
|
||||
if (strcmp(type, "float") == 0)
|
||||
return GS_SHADER_PARAM_FLOAT;
|
||||
else if (strcmp(type, "float2") == 0)
|
||||
return GS_SHADER_PARAM_VEC2;
|
||||
else if (strcmp(type, "float3") == 0)
|
||||
return GS_SHADER_PARAM_VEC3;
|
||||
else if (strcmp(type, "float4") == 0)
|
||||
return GS_SHADER_PARAM_VEC4;
|
||||
else if (astrcmp_n(type, "texture", 7) == 0)
|
||||
return GS_SHADER_PARAM_TEXTURE;
|
||||
else if (strcmp(type, "float4x4") == 0)
|
||||
return GS_SHADER_PARAM_MATRIX4X4;
|
||||
else if (strcmp(type, "bool") == 0)
|
||||
return GS_SHADER_PARAM_BOOL;
|
||||
else if (strcmp(type, "int") == 0)
|
||||
return GS_SHADER_PARAM_INT;
|
||||
else if (strcmp(type, "string") == 0)
|
||||
return GS_SHADER_PARAM_STRING;
|
||||
|
||||
return GS_SHADER_PARAM_UNKNOWN;
|
||||
}
|
||||
|
||||
enum gs_sample_filter get_sample_filter(const char *filter)
|
||||
{
|
||||
if (astrcmpi(filter, "Anisotropy") == 0)
|
||||
return GS_FILTER_ANISOTROPIC;
|
||||
|
||||
else if (astrcmpi(filter, "Point") == 0 ||
|
||||
strcmp(filter, "MIN_MAG_MIP_POINT") == 0)
|
||||
return GS_FILTER_POINT;
|
||||
|
||||
else if (astrcmpi(filter, "Linear") == 0 ||
|
||||
strcmp(filter, "MIN_MAG_MIP_LINEAR") == 0)
|
||||
return GS_FILTER_LINEAR;
|
||||
|
||||
else if (strcmp(filter, "MIN_MAG_POINT_MIP_LINEAR") == 0)
|
||||
return GS_FILTER_MIN_MAG_POINT_MIP_LINEAR;
|
||||
|
||||
else if (strcmp(filter, "MIN_POINT_MAG_LINEAR_MIP_POINT") == 0)
|
||||
return GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
|
||||
else if (strcmp(filter, "MIN_POINT_MAG_MIP_LINEAR") == 0)
|
||||
return GS_FILTER_MIN_POINT_MAG_MIP_LINEAR;
|
||||
|
||||
else if (strcmp(filter, "MIN_LINEAR_MAG_MIP_POINT") == 0)
|
||||
return GS_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
|
||||
else if (strcmp(filter, "MIN_LINEAR_MAG_POINT_MIP_LINEAR") == 0)
|
||||
return GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
|
||||
|
||||
else if (strcmp(filter, "MIN_MAG_LINEAR_MIP_POINT") == 0)
|
||||
return GS_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
|
||||
return GS_FILTER_LINEAR;
|
||||
}
|
||||
|
||||
extern enum gs_address_mode get_address_mode(const char *mode)
|
||||
{
|
||||
if (astrcmpi(mode, "Wrap") == 0 || astrcmpi(mode, "Repeat") == 0)
|
||||
return GS_ADDRESS_WRAP;
|
||||
else if (astrcmpi(mode, "Clamp") == 0 || astrcmpi(mode, "None") == 0)
|
||||
return GS_ADDRESS_CLAMP;
|
||||
else if (astrcmpi(mode, "Mirror") == 0)
|
||||
return GS_ADDRESS_MIRROR;
|
||||
else if (astrcmpi(mode, "Border") == 0)
|
||||
return GS_ADDRESS_BORDER;
|
||||
else if (astrcmpi(mode, "MirrorOnce") == 0)
|
||||
return GS_ADDRESS_MIRRORONCE;
|
||||
|
||||
return GS_ADDRESS_CLAMP;
|
||||
}
|
||||
|
||||
void shader_sampler_convert(struct shader_sampler *ss,
|
||||
struct gs_sampler_info *info)
|
||||
{
|
||||
size_t i;
|
||||
memset(info, 0, sizeof(struct gs_sampler_info));
|
||||
|
||||
for (i = 0; i < ss->states.num; i++) {
|
||||
const char *state = ss->states.array[i];
|
||||
const char *value = ss->values.array[i];
|
||||
|
||||
if (astrcmpi(state, "Filter") == 0)
|
||||
info->filter = get_sample_filter(value);
|
||||
else if (astrcmpi(state, "AddressU") == 0)
|
||||
info->address_u = get_address_mode(value);
|
||||
else if (astrcmpi(state, "AddressV") == 0)
|
||||
info->address_v = get_address_mode(value);
|
||||
else if (astrcmpi(state, "AddressW") == 0)
|
||||
info->address_w = get_address_mode(value);
|
||||
else if (astrcmpi(state, "MaxAnisotropy") == 0)
|
||||
info->max_anisotropy = (int)strtol(value, NULL, 10);
|
||||
else if (astrcmpi(state, "BorderColor") == 0)
|
||||
info->border_color = (*value == '#') ?
|
||||
strtol(value + 1, NULL, 16) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int sp_parse_sampler_state_item(struct shader_parser *sp,
|
||||
struct shader_sampler *ss)
|
||||
{
|
||||
int ret;
|
||||
char *state = NULL, *value = NULL;
|
||||
|
||||
ret = cf_next_name(&sp->cfp, &state, "state name", ";");
|
||||
if (ret != PARSE_SUCCESS) goto fail;
|
||||
|
||||
ret = cf_next_token_should_be(&sp->cfp, "=", ";", NULL);
|
||||
if (ret != PARSE_SUCCESS) goto fail;
|
||||
|
||||
ret = cf_next_name(&sp->cfp, &value, "value name", ";");
|
||||
if (ret != PARSE_SUCCESS) goto fail;
|
||||
|
||||
ret = cf_next_token_should_be(&sp->cfp, ";", ";", NULL);
|
||||
if (ret != PARSE_SUCCESS) goto fail;
|
||||
|
||||
da_push_back(ss->states, &state);
|
||||
da_push_back(ss->values, &value);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
bfree(state);
|
||||
bfree(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sp_parse_sampler_state(struct shader_parser *sp)
|
||||
{
|
||||
struct shader_sampler ss;
|
||||
struct cf_token peek;
|
||||
shader_sampler_init(&ss);
|
||||
|
||||
if (cf_next_name(&sp->cfp, &ss.name, "name", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
if (cf_next_token_should_be(&sp->cfp, "{", ";", NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (!cf_peek_valid_token(&sp->cfp, &peek))
|
||||
goto error;
|
||||
|
||||
while (strref_cmp(&peek.str, "}") != 0) {
|
||||
int ret = sp_parse_sampler_state_item(sp, &ss);
|
||||
if (ret == PARSE_EOF)
|
||||
goto error;
|
||||
|
||||
if (!cf_peek_valid_token(&sp->cfp, &peek))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (cf_next_token_should_be(&sp->cfp, "}", ";", NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
if (cf_next_token_should_be(&sp->cfp, ";", NULL, NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
da_push_back(sp->samplers, &ss);
|
||||
return;
|
||||
|
||||
error:
|
||||
shader_sampler_free(&ss);
|
||||
}
|
||||
|
||||
static inline int sp_parse_struct_var(struct shader_parser *sp,
|
||||
struct shader_var *var)
|
||||
{
|
||||
int code;
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable type */
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp)) return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, ";")) return PARSE_CONTINUE;
|
||||
if (cf_token_is(&sp->cfp, "}")) return PARSE_BREAK;
|
||||
|
||||
code = cf_token_is_type(&sp->cfp, CFTOKEN_NAME, "type name", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
cf_copy_token(&sp->cfp, &var->type);
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable name */
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp)) return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, ";")) return PARSE_UNEXPECTED_CONTINUE;
|
||||
if (cf_token_is(&sp->cfp, "}")) return PARSE_UNEXPECTED_BREAK;
|
||||
|
||||
code = cf_token_is_type(&sp->cfp, CFTOKEN_NAME, "variable name",
|
||||
";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
cf_copy_token(&sp->cfp, &var->name);
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable mapping if any (POSITION, TEXCOORD, etc) */
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp)) return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, ":")) {
|
||||
if (!cf_next_valid_token(&sp->cfp)) return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, ";"))
|
||||
return PARSE_UNEXPECTED_CONTINUE;
|
||||
if (cf_token_is(&sp->cfp, "}"))
|
||||
return PARSE_UNEXPECTED_BREAK;
|
||||
|
||||
code = cf_token_is_type(&sp->cfp, CFTOKEN_NAME,
|
||||
"mapping name", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
cf_copy_token(&sp->cfp, &var->mapping);
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp)) return PARSE_EOF;
|
||||
}
|
||||
|
||||
/* -------------------------------------- */
|
||||
|
||||
if (!cf_token_is(&sp->cfp, ";")) {
|
||||
if (!cf_go_to_valid_token(&sp->cfp, ";", "}"))
|
||||
return PARSE_EOF;
|
||||
return PARSE_CONTINUE;
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static void sp_parse_struct(struct shader_parser *sp)
|
||||
{
|
||||
struct shader_struct ss;
|
||||
shader_struct_init(&ss);
|
||||
|
||||
if (cf_next_name(&sp->cfp, &ss.name, "name", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
if (cf_next_token_should_be(&sp->cfp, "{", ";", NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
/* get structure variables */
|
||||
while (true) {
|
||||
bool do_break = false;
|
||||
struct shader_var var;
|
||||
|
||||
shader_var_init(&var);
|
||||
|
||||
switch (sp_parse_struct_var(sp, &var)) {
|
||||
|
||||
case PARSE_UNEXPECTED_CONTINUE:
|
||||
cf_adderror_syntax_error(&sp->cfp);
|
||||
case PARSE_CONTINUE:
|
||||
shader_var_free(&var);
|
||||
continue;
|
||||
|
||||
case PARSE_UNEXPECTED_BREAK:
|
||||
cf_adderror_syntax_error(&sp->cfp);
|
||||
case PARSE_BREAK:
|
||||
shader_var_free(&var);
|
||||
do_break = true;
|
||||
break;
|
||||
|
||||
case PARSE_EOF:
|
||||
shader_var_free(&var);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (do_break)
|
||||
break;
|
||||
|
||||
da_push_back(ss.vars, &var);
|
||||
}
|
||||
|
||||
if (cf_next_token_should_be(&sp->cfp, ";", NULL, NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
da_push_back(sp->structs, &ss);
|
||||
return;
|
||||
|
||||
error:
|
||||
shader_struct_free(&ss);
|
||||
}
|
||||
|
||||
static inline int sp_check_for_keyword(struct shader_parser *sp,
|
||||
const char *keyword, bool *val)
|
||||
{
|
||||
bool new_val = cf_token_is(&sp->cfp, keyword);
|
||||
if (new_val) {
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (new_val && *val)
|
||||
cf_adderror(&sp->cfp, "'$1' keyword already specified",
|
||||
LEX_WARNING, keyword, NULL, NULL);
|
||||
*val = new_val;
|
||||
|
||||
return PARSE_CONTINUE;
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static inline int sp_parse_func_param(struct shader_parser *sp,
|
||||
struct shader_var *var)
|
||||
{
|
||||
int code;
|
||||
bool is_uniform = false;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
code = sp_check_for_keyword(sp, "uniform", &is_uniform);
|
||||
if (code == PARSE_EOF)
|
||||
return PARSE_EOF;
|
||||
|
||||
var->var_type = is_uniform ? SHADER_VAR_UNIFORM : SHADER_VAR_NONE;
|
||||
|
||||
code = cf_get_name(&sp->cfp, &var->type, "type", ")");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
code = cf_next_name(&sp->cfp, &var->name, "name", ")");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, ":")) {
|
||||
code = cf_next_name(&sp->cfp, &var->mapping,
|
||||
"mapping specifier", ")");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool sp_parse_func_params(struct shader_parser *sp,
|
||||
struct shader_func *func)
|
||||
{
|
||||
struct cf_token peek;
|
||||
int code;
|
||||
|
||||
cf_token_clear(&peek);
|
||||
|
||||
if (!cf_peek_valid_token(&sp->cfp, &peek))
|
||||
return false;
|
||||
|
||||
if (*peek.str.array == ')') {
|
||||
cf_next_token(&sp->cfp);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
do {
|
||||
struct shader_var var;
|
||||
shader_var_init(&var);
|
||||
|
||||
if (!cf_token_is(&sp->cfp, "(") && !cf_token_is(&sp->cfp, ","))
|
||||
cf_adderror_syntax_error(&sp->cfp);
|
||||
|
||||
code = sp_parse_func_param(sp, &var);
|
||||
if (code != PARSE_SUCCESS) {
|
||||
shader_var_free(&var);
|
||||
|
||||
if (code == PARSE_CONTINUE)
|
||||
goto exit;
|
||||
else if (code == PARSE_EOF)
|
||||
return false;
|
||||
}
|
||||
|
||||
da_push_back(func->params, &var);
|
||||
} while (!cf_token_is(&sp->cfp, ")"));
|
||||
|
||||
exit:
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sp_parse_function(struct shader_parser *sp, char *type, char *name)
|
||||
{
|
||||
struct shader_func func;
|
||||
|
||||
shader_func_init(&func, type, name);
|
||||
if (!sp_parse_func_params(sp, &func))
|
||||
goto error;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
goto error;
|
||||
|
||||
/* if function is mapped to something, for example COLOR */
|
||||
if (cf_token_is(&sp->cfp, ":")) {
|
||||
char *mapping = NULL;
|
||||
int errorcode = cf_next_name(&sp->cfp, &mapping, "mapping",
|
||||
"{");
|
||||
if (errorcode != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
func.mapping = mapping;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!cf_token_is(&sp->cfp, "{")) {
|
||||
cf_adderror_expecting(&sp->cfp, "{");
|
||||
goto error;
|
||||
}
|
||||
|
||||
func.start = sp->cfp.cur_token;
|
||||
if (!cf_pass_pair(&sp->cfp, '{', '}'))
|
||||
goto error;
|
||||
|
||||
/* it is established that the current token is '}' if we reach this */
|
||||
cf_next_token(&sp->cfp);
|
||||
|
||||
func.end = sp->cfp.cur_token;
|
||||
da_push_back(sp->funcs, &func);
|
||||
return;
|
||||
|
||||
error:
|
||||
shader_func_free(&func);
|
||||
}
|
||||
|
||||
/* parses "array[count]" */
|
||||
static bool sp_parse_param_array(struct shader_parser *sp,
|
||||
struct shader_var *param)
|
||||
{
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return false;
|
||||
|
||||
if (sp->cfp.cur_token->type != CFTOKEN_NUM ||
|
||||
!valid_int_str(sp->cfp.cur_token->str.array,
|
||||
sp->cfp.cur_token->str.len))
|
||||
return false;
|
||||
|
||||
param->array_count =(int)strtol(sp->cfp.cur_token->str.array, NULL, 10);
|
||||
|
||||
if (cf_next_token_should_be(&sp->cfp, "]", ";", NULL) == PARSE_EOF)
|
||||
return false;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline int sp_parse_param_assign_intfloat(struct shader_parser *sp,
|
||||
struct shader_var *param, bool is_float)
|
||||
{
|
||||
int code;
|
||||
bool is_negative = false;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&sp->cfp, "-")) {
|
||||
is_negative = true;
|
||||
|
||||
if (!cf_next_token(&sp->cfp))
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
code = cf_token_is_type(&sp->cfp, CFTOKEN_NUM, "numeric value", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
if (is_float) {
|
||||
float f = (float)os_strtod(sp->cfp.cur_token->str.array);
|
||||
if (is_negative) f = -f;
|
||||
da_push_back_array(param->default_val, &f, sizeof(float));
|
||||
} else {
|
||||
long l = strtol(sp->cfp.cur_token->str.array, NULL, 10);
|
||||
if (is_negative) l = -l;
|
||||
da_push_back_array(param->default_val, &l, sizeof(long));
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses assignment for float1, float2, float3, float4, and any combination
|
||||
* for float3x3, float4x4, etc
|
||||
*/
|
||||
static inline int sp_parse_param_assign_float_array(struct shader_parser *sp,
|
||||
struct shader_var *param)
|
||||
{
|
||||
const char *float_type = param->type+5;
|
||||
int float_count = 0, code, i;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
if (float_type[0] < '1' || float_type[0] > '4')
|
||||
cf_adderror(&sp->cfp, "Invalid row count", LEX_ERROR,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
float_count = float_type[0]-'0';
|
||||
|
||||
if (float_type[1] == 'x') {
|
||||
if (float_type[2] < '1' || float_type[2] > '4')
|
||||
cf_adderror(&sp->cfp, "Invalid column count",
|
||||
LEX_ERROR, NULL, NULL, NULL);
|
||||
|
||||
float_count *= float_type[2]-'0';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
code = cf_next_token_should_be(&sp->cfp, "{", ";", NULL);
|
||||
if (code != PARSE_SUCCESS) return code;
|
||||
|
||||
for (i = 0; i < float_count; i++) {
|
||||
char *next = ((i+1) < float_count) ? "," : "}";
|
||||
|
||||
code = sp_parse_param_assign_intfloat(sp, param, true);
|
||||
if (code != PARSE_SUCCESS) return code;
|
||||
|
||||
code = cf_next_token_should_be(&sp->cfp, next, ";", NULL);
|
||||
if (code != PARSE_SUCCESS) return code;
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static int sp_parse_param_assignment_val(struct shader_parser *sp,
|
||||
struct shader_var *param)
|
||||
{
|
||||
if (strcmp(param->type, "int") == 0)
|
||||
return sp_parse_param_assign_intfloat(sp, param, false);
|
||||
else if (strcmp(param->type, "float") == 0)
|
||||
return sp_parse_param_assign_intfloat(sp, param, true);
|
||||
else if (astrcmp_n(param->type, "float", 5) == 0)
|
||||
return sp_parse_param_assign_float_array(sp, param);
|
||||
|
||||
cf_adderror(&sp->cfp, "Invalid type '$1' used for assignment",
|
||||
LEX_ERROR, param->type, NULL, NULL);
|
||||
|
||||
return PARSE_CONTINUE;
|
||||
}
|
||||
|
||||
static inline bool sp_parse_param_assign(struct shader_parser *sp,
|
||||
struct shader_var *param)
|
||||
{
|
||||
if (sp_parse_param_assignment_val(sp, param) != PARSE_SUCCESS)
|
||||
return false;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sp_parse_param(struct shader_parser *sp,
|
||||
char *type, char *name, bool is_const, bool is_uniform)
|
||||
{
|
||||
struct shader_var param;
|
||||
shader_var_init_param(¶m, type, name, is_uniform, is_const);
|
||||
|
||||
if (cf_token_is(&sp->cfp, ";"))
|
||||
goto complete;
|
||||
if (cf_token_is(&sp->cfp, "[") && !sp_parse_param_array(sp, ¶m))
|
||||
goto error;
|
||||
if (cf_token_is(&sp->cfp, "=") && !sp_parse_param_assign(sp, ¶m))
|
||||
goto error;
|
||||
if (!cf_token_is(&sp->cfp, ";"))
|
||||
goto error;
|
||||
|
||||
complete:
|
||||
da_push_back(sp->params, ¶m);
|
||||
return;
|
||||
|
||||
error:
|
||||
shader_var_free(¶m);
|
||||
}
|
||||
|
||||
static bool sp_get_var_specifiers(struct shader_parser *sp,
|
||||
bool *is_const, bool *is_uniform)
|
||||
{
|
||||
while(true) {
|
||||
int code = sp_check_for_keyword(sp, "const", is_const);
|
||||
if (code == PARSE_EOF)
|
||||
return false;
|
||||
else if (code == PARSE_CONTINUE)
|
||||
continue;
|
||||
|
||||
code = sp_check_for_keyword(sp, "uniform", is_uniform);
|
||||
if (code == PARSE_EOF)
|
||||
return false;
|
||||
else if (code == PARSE_CONTINUE)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void report_invalid_func_keyword(struct shader_parser *sp,
|
||||
const char *name, bool val)
|
||||
{
|
||||
if (val)
|
||||
cf_adderror(&sp->cfp, "'$1' keyword cannot be used with a "
|
||||
"function", LEX_ERROR,
|
||||
name, NULL, NULL);
|
||||
}
|
||||
|
||||
static void sp_parse_other(struct shader_parser *sp)
|
||||
{
|
||||
bool is_const = false, is_uniform = false;
|
||||
char *type = NULL, *name = NULL;
|
||||
|
||||
if (!sp_get_var_specifiers(sp, &is_const, &is_uniform))
|
||||
goto error;
|
||||
|
||||
if (cf_get_name(&sp->cfp, &type, "type", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
if (cf_next_name(&sp->cfp, &name, "name", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (!cf_next_valid_token(&sp->cfp))
|
||||
goto error;
|
||||
|
||||
if (cf_token_is(&sp->cfp, "(")) {
|
||||
report_invalid_func_keyword(sp, "const", is_const);
|
||||
report_invalid_func_keyword(sp, "uniform", is_uniform);
|
||||
|
||||
sp_parse_function(sp, type, name);
|
||||
return;
|
||||
} else {
|
||||
sp_parse_param(sp, type, name, is_const, is_uniform);
|
||||
return;
|
||||
}
|
||||
|
||||
error:
|
||||
bfree(type);
|
||||
bfree(name);
|
||||
}
|
||||
|
||||
bool shader_parse(struct shader_parser *sp, const char *shader,
|
||||
const char *file)
|
||||
{
|
||||
if (!cf_parser_parse(&sp->cfp, shader, file))
|
||||
return false;
|
||||
|
||||
while (sp->cfp.cur_token && sp->cfp.cur_token->type != CFTOKEN_NONE) {
|
||||
if (cf_token_is(&sp->cfp, ";") ||
|
||||
is_whitespace(*sp->cfp.cur_token->str.array)) {
|
||||
sp->cfp.cur_token++;
|
||||
|
||||
} else if (cf_token_is(&sp->cfp, "struct")) {
|
||||
sp_parse_struct(sp);
|
||||
|
||||
} else if (cf_token_is(&sp->cfp, "sampler_state")) {
|
||||
sp_parse_sampler_state(sp);
|
||||
|
||||
} else if (cf_token_is(&sp->cfp, "{")) {
|
||||
cf_adderror(&sp->cfp, "Unexpected code segment",
|
||||
LEX_ERROR, NULL, NULL, NULL);
|
||||
cf_pass_pair(&sp->cfp, '{', '}');
|
||||
|
||||
} else {
|
||||
/* parameters and functions */
|
||||
sp_parse_other(sp);
|
||||
}
|
||||
}
|
||||
|
||||
return !error_data_has_errors(&sp->cfp.error_list);
|
||||
}
|
||||
278
libobs/graphics/shader-parser.h
Normal file
278
libobs/graphics/shader-parser.h
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/cf-parser.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EXPORT enum gs_shader_param_type get_shader_param_type(const char *type);
|
||||
EXPORT enum gs_sample_filter get_sample_filter(const char *filter);
|
||||
EXPORT enum gs_address_mode get_address_mode(const char *address_mode);
|
||||
|
||||
/*
|
||||
* Shader Parser
|
||||
*
|
||||
* Parses a shader and extracts data such as shader constants, samplers,
|
||||
* and vertex input information. Also allows the reformatting of shaders for
|
||||
* different libraries. This is usually used only by graphics libraries,
|
||||
*/
|
||||
|
||||
enum shader_var_type {
|
||||
SHADER_VAR_NONE,
|
||||
SHADER_VAR_UNIFORM,
|
||||
SHADER_VAR_CONST
|
||||
};
|
||||
|
||||
struct shader_var {
|
||||
char *type;
|
||||
char *name;
|
||||
char *mapping;
|
||||
enum shader_var_type var_type;
|
||||
int array_count;
|
||||
size_t gl_sampler_id; /* optional: used/parsed by GL */
|
||||
|
||||
DARRAY(uint8_t) default_val;
|
||||
};
|
||||
|
||||
static inline void shader_var_init(struct shader_var *sv)
|
||||
{
|
||||
memset(sv, 0, sizeof(struct shader_var));
|
||||
}
|
||||
|
||||
static inline void shader_var_init_param(struct shader_var *sv,
|
||||
char *type, char *name, bool is_uniform,
|
||||
bool is_const)
|
||||
{
|
||||
if (is_uniform)
|
||||
sv->var_type = SHADER_VAR_UNIFORM;
|
||||
else if (is_const)
|
||||
sv->var_type = SHADER_VAR_CONST;
|
||||
else
|
||||
sv->var_type = SHADER_VAR_NONE;
|
||||
|
||||
sv->type = type;
|
||||
sv->name = name;
|
||||
sv->mapping = NULL;
|
||||
sv->array_count = 0;
|
||||
da_init(sv->default_val);
|
||||
}
|
||||
|
||||
static inline void shader_var_free(struct shader_var *sv)
|
||||
{
|
||||
bfree(sv->type);
|
||||
bfree(sv->name);
|
||||
bfree(sv->mapping);
|
||||
da_free(sv->default_val);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct shader_sampler {
|
||||
char *name;
|
||||
DARRAY(char*) states;
|
||||
DARRAY(char*) values;
|
||||
};
|
||||
|
||||
static inline void shader_sampler_init(struct shader_sampler *ss)
|
||||
{
|
||||
memset(ss, 0, sizeof(struct shader_sampler));
|
||||
}
|
||||
|
||||
static inline void shader_sampler_free(struct shader_sampler *ss)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < ss->states.num; i++)
|
||||
bfree(ss->states.array[i]);
|
||||
for (i = 0; i < ss->values.num; i++)
|
||||
bfree(ss->values.array[i]);
|
||||
|
||||
bfree(ss->name);
|
||||
da_free(ss->states);
|
||||
da_free(ss->values);
|
||||
}
|
||||
|
||||
EXPORT void shader_sampler_convert(struct shader_sampler *ss,
|
||||
struct gs_sampler_info *info);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct shader_struct {
|
||||
char *name;
|
||||
DARRAY(struct shader_var) vars;
|
||||
};
|
||||
|
||||
static inline void shader_struct_init(struct shader_struct *ss)
|
||||
{
|
||||
memset(ss, 0, sizeof(struct shader_struct));
|
||||
}
|
||||
|
||||
static inline void shader_struct_free(struct shader_struct *ss)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ss->vars.num; i++)
|
||||
shader_var_free(ss->vars.array+i);
|
||||
|
||||
bfree(ss->name);
|
||||
da_free(ss->vars);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct shader_func {
|
||||
char *name;
|
||||
char *return_type;
|
||||
char *mapping;
|
||||
DARRAY(struct shader_var) params;
|
||||
|
||||
struct cf_token *start, *end;
|
||||
};
|
||||
|
||||
static inline void shader_func_init(struct shader_func *sf,
|
||||
char *return_type, char *name)
|
||||
{
|
||||
da_init(sf->params);
|
||||
|
||||
sf->return_type = return_type;
|
||||
sf->mapping = NULL;
|
||||
sf->name = name;
|
||||
sf->start = NULL;
|
||||
sf->end = NULL;
|
||||
}
|
||||
|
||||
static inline void shader_func_free(struct shader_func *sf)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sf->params.num; i++)
|
||||
shader_var_free(sf->params.array+i);
|
||||
|
||||
bfree(sf->name);
|
||||
bfree(sf->return_type);
|
||||
bfree(sf->mapping);
|
||||
da_free(sf->params);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct shader_parser {
|
||||
struct cf_parser cfp;
|
||||
|
||||
DARRAY(struct shader_var) params;
|
||||
DARRAY(struct shader_struct) structs;
|
||||
DARRAY(struct shader_sampler) samplers;
|
||||
DARRAY(struct shader_func) funcs;
|
||||
};
|
||||
|
||||
static inline void shader_parser_init(struct shader_parser *sp)
|
||||
{
|
||||
cf_parser_init(&sp->cfp);
|
||||
|
||||
da_init(sp->params);
|
||||
da_init(sp->structs);
|
||||
da_init(sp->samplers);
|
||||
da_init(sp->funcs);
|
||||
}
|
||||
|
||||
static inline void shader_parser_free(struct shader_parser *sp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sp->params.num; i++)
|
||||
shader_var_free(sp->params.array+i);
|
||||
for (i = 0; i < sp->structs.num; i++)
|
||||
shader_struct_free(sp->structs.array+i);
|
||||
for (i = 0; i < sp->samplers.num; i++)
|
||||
shader_sampler_free(sp->samplers.array+i);
|
||||
for (i = 0; i < sp->funcs.num; i++)
|
||||
shader_func_free(sp->funcs.array+i);
|
||||
|
||||
cf_parser_free(&sp->cfp);
|
||||
da_free(sp->params);
|
||||
da_free(sp->structs);
|
||||
da_free(sp->samplers);
|
||||
da_free(sp->funcs);
|
||||
}
|
||||
|
||||
EXPORT bool shader_parse(struct shader_parser *sp, const char *shader,
|
||||
const char *file);
|
||||
|
||||
static inline char *shader_parser_geterrors(struct shader_parser *sp)
|
||||
{
|
||||
return error_data_buildstring(&sp->cfp.error_list);
|
||||
}
|
||||
|
||||
static inline struct shader_var *shader_parser_getparam(
|
||||
struct shader_parser *sp, const char *param_name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sp->params.num; i++) {
|
||||
struct shader_var *param = sp->params.array+i;
|
||||
if (strcmp(param->name, param_name) == 0)
|
||||
return param;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct shader_struct *shader_parser_getstruct(
|
||||
struct shader_parser *sp, const char *struct_name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sp->structs.num; i++) {
|
||||
struct shader_struct *st = sp->structs.array+i;
|
||||
if (strcmp(st->name, struct_name) == 0)
|
||||
return st;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct shader_sampler *shader_parser_getsampler(
|
||||
struct shader_parser *sp, const char *sampler_name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sp->samplers.num; i++) {
|
||||
struct shader_sampler *sampler = sp->samplers.array+i;
|
||||
if (strcmp(sampler->name, sampler_name) == 0)
|
||||
return sampler;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct shader_func *shader_parser_getfunc(
|
||||
struct shader_parser *sp, const char *func_name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sp->funcs.num; i++) {
|
||||
struct shader_func *func = sp->funcs.array+i;
|
||||
if (strcmp(func->name, func_name) == 0)
|
||||
return func;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
139
libobs/graphics/texture-render.c
Normal file
139
libobs/graphics/texture-render.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* This is a set of helper functions to more easily render to textures
|
||||
* without having to duplicate too much code.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "graphics.h"
|
||||
|
||||
struct gs_texture_render {
|
||||
gs_texture_t *target, *prev_target;
|
||||
gs_zstencil_t *zs, *prev_zs;
|
||||
|
||||
uint32_t cx, cy;
|
||||
|
||||
enum gs_color_format format;
|
||||
enum gs_zstencil_format zsformat;
|
||||
|
||||
bool rendered;
|
||||
};
|
||||
|
||||
gs_texrender_t *gs_texrender_create(enum gs_color_format format,
|
||||
enum gs_zstencil_format zsformat)
|
||||
{
|
||||
struct gs_texture_render *texrender;
|
||||
texrender = bzalloc(sizeof(struct gs_texture_render));
|
||||
texrender->format = format;
|
||||
texrender->zsformat = zsformat;
|
||||
|
||||
return texrender;
|
||||
}
|
||||
|
||||
void gs_texrender_destroy(gs_texrender_t *texrender)
|
||||
{
|
||||
if (texrender) {
|
||||
gs_texture_destroy(texrender->target);
|
||||
gs_zstencil_destroy(texrender->zs);
|
||||
bfree(texrender);
|
||||
}
|
||||
}
|
||||
|
||||
static bool texrender_resetbuffer(gs_texrender_t *texrender, uint32_t cx,
|
||||
uint32_t cy)
|
||||
{
|
||||
if (!texrender)
|
||||
return false;
|
||||
|
||||
gs_texture_destroy(texrender->target);
|
||||
gs_zstencil_destroy(texrender->zs);
|
||||
|
||||
texrender->target = NULL;
|
||||
texrender->zs = NULL;
|
||||
texrender->cx = cx;
|
||||
texrender->cy = cy;
|
||||
|
||||
texrender->target = gs_texture_create(cx, cy, texrender->format,
|
||||
1, NULL, GS_RENDER_TARGET);
|
||||
if (!texrender->target)
|
||||
return false;
|
||||
|
||||
if (texrender->zsformat != GS_ZS_NONE) {
|
||||
texrender->zs = gs_zstencil_create(cx, cy, texrender->zsformat);
|
||||
if (!texrender->zs) {
|
||||
gs_texture_destroy(texrender->target);
|
||||
texrender->target = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gs_texrender_begin(gs_texrender_t *texrender, uint32_t cx, uint32_t cy)
|
||||
{
|
||||
if (!texrender || texrender->rendered)
|
||||
return false;
|
||||
|
||||
if (!cx || !cy)
|
||||
return false;
|
||||
|
||||
if (texrender->cx != cx || texrender->cy != cy)
|
||||
if (!texrender_resetbuffer(texrender, cx, cy))
|
||||
return false;
|
||||
|
||||
gs_viewport_push();
|
||||
gs_projection_push();
|
||||
gs_matrix_push();
|
||||
gs_matrix_identity();
|
||||
|
||||
texrender->prev_target = gs_get_render_target();
|
||||
texrender->prev_zs = gs_get_zstencil_target();
|
||||
gs_set_render_target(texrender->target, texrender->zs);
|
||||
|
||||
gs_set_viewport(0, 0, texrender->cx, texrender->cy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void gs_texrender_end(gs_texrender_t *texrender)
|
||||
{
|
||||
if (!texrender)
|
||||
return;
|
||||
|
||||
gs_set_render_target(texrender->prev_target, texrender->prev_zs);
|
||||
|
||||
gs_matrix_pop();
|
||||
gs_projection_pop();
|
||||
gs_viewport_pop();
|
||||
|
||||
texrender->rendered = true;
|
||||
}
|
||||
|
||||
void gs_texrender_reset(gs_texrender_t *texrender)
|
||||
{
|
||||
if (texrender)
|
||||
texrender->rendered = false;
|
||||
}
|
||||
|
||||
gs_texture_t *gs_texrender_get_texture(const gs_texrender_t *texrender)
|
||||
{
|
||||
return texrender ? texrender->target : NULL;
|
||||
}
|
||||
52
libobs/graphics/vec2.c
Normal file
52
libobs/graphics/vec2.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include "math-extra.h"
|
||||
#include "math-defs.h"
|
||||
#include "vec2.h"
|
||||
|
||||
void vec2_abs(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
vec2_set(dst, fabsf(v->x), fabsf(v->y));
|
||||
}
|
||||
|
||||
void vec2_floor(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
vec2_set(dst, floorf(v->x), floorf(v->y));
|
||||
}
|
||||
|
||||
void vec2_ceil(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
vec2_set(dst, ceilf(v->x), ceilf(v->y));
|
||||
}
|
||||
|
||||
int vec2_close(const struct vec2 *v1, const struct vec2 *v2, float epsilon)
|
||||
{
|
||||
return close_float(v1->x, v2->x, epsilon) &&
|
||||
close_float(v1->y, v2->y, epsilon);
|
||||
}
|
||||
|
||||
void vec2_norm(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
float len = vec2_len(v);
|
||||
|
||||
if (len > 0.0f) {
|
||||
len = 1.0f / len;
|
||||
vec2_mulf(dst, v, len);
|
||||
}
|
||||
}
|
||||
169
libobs/graphics/vec2.h
Normal file
169
libobs/graphics/vec2.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../util/c99defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct vec2 {
|
||||
union {
|
||||
struct {
|
||||
float x, y;
|
||||
};
|
||||
float ptr[2];
|
||||
};
|
||||
};
|
||||
|
||||
static inline void vec2_zero(struct vec2 *dst)
|
||||
{
|
||||
dst->x = 0.0f;
|
||||
dst->y = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec2_set(struct vec2 *dst, float x, float y)
|
||||
{
|
||||
dst->x = x;
|
||||
dst->y = y;
|
||||
}
|
||||
|
||||
static inline void vec2_copy(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
dst->x = v->x;
|
||||
dst->y = v->y;
|
||||
}
|
||||
|
||||
static inline void vec2_add(struct vec2 *dst, const struct vec2 *v1,
|
||||
const struct vec2 *v2)
|
||||
{
|
||||
vec2_set(dst, v1->x+v2->x, v1->y+v2->y);
|
||||
}
|
||||
|
||||
static inline void vec2_sub(struct vec2 *dst, const struct vec2 *v1,
|
||||
const struct vec2 *v2)
|
||||
{
|
||||
vec2_set(dst, v1->x-v2->x, v1->y-v2->y);
|
||||
}
|
||||
|
||||
static inline void vec2_mul(struct vec2 *dst, const struct vec2 *v1,
|
||||
const struct vec2 *v2)
|
||||
{
|
||||
vec2_set(dst, v1->x*v2->x, v1->y*v2->y);
|
||||
}
|
||||
|
||||
static inline void vec2_div(struct vec2 *dst, const struct vec2 *v1,
|
||||
const struct vec2 *v2)
|
||||
{
|
||||
vec2_set(dst, v1->x/v2->x, v1->y/v2->y);
|
||||
}
|
||||
|
||||
static inline void vec2_addf(struct vec2 *dst, const struct vec2 *v,
|
||||
float f)
|
||||
{
|
||||
vec2_set(dst, v->x+f, v->y+f);
|
||||
}
|
||||
|
||||
static inline void vec2_subf(struct vec2 *dst, const struct vec2 *v,
|
||||
float f)
|
||||
{
|
||||
vec2_set(dst, v->x-f, v->y-f);
|
||||
}
|
||||
|
||||
static inline void vec2_mulf(struct vec2 *dst, const struct vec2 *v,
|
||||
float f)
|
||||
{
|
||||
vec2_set(dst, v->x*f, v->y*f);
|
||||
}
|
||||
|
||||
static inline void vec2_divf(struct vec2 *dst, const struct vec2 *v,
|
||||
float f)
|
||||
{
|
||||
vec2_set(dst, v->x/f, v->y/f);
|
||||
}
|
||||
|
||||
static inline void vec2_neg(struct vec2 *dst, const struct vec2 *v)
|
||||
{
|
||||
vec2_set(dst, -v->x, -v->y);
|
||||
}
|
||||
|
||||
static inline float vec2_dot(const struct vec2 *v1, const struct vec2 *v2)
|
||||
{
|
||||
return (v1->x+v2->x) * (v1->y+v2->y);
|
||||
}
|
||||
|
||||
static inline float vec2_len(const struct vec2 *v)
|
||||
{
|
||||
return sqrtf(v->x*v->x + v->y*v->y);
|
||||
}
|
||||
|
||||
static inline float vec2_dist(const struct vec2 *v1, const struct vec2 *v2)
|
||||
{
|
||||
struct vec2 temp;
|
||||
vec2_sub(&temp, v1, v2);
|
||||
return vec2_len(&temp);
|
||||
}
|
||||
|
||||
static inline void vec2_minf(struct vec2 *dst, const struct vec2 *v,
|
||||
float val)
|
||||
{
|
||||
if (v->x < val)
|
||||
dst->x = val;
|
||||
if (v->y < val)
|
||||
dst->y = val;
|
||||
}
|
||||
|
||||
static inline void vec2_min(struct vec2 *dst, const struct vec2 *v,
|
||||
const struct vec2 *min_v)
|
||||
{
|
||||
if (v->x < min_v->x)
|
||||
dst->x = min_v->x;
|
||||
if (v->y < min_v->y)
|
||||
dst->y = min_v->y;
|
||||
}
|
||||
|
||||
static inline void vec2_maxf(struct vec2 *dst, const struct vec2 *v,
|
||||
float val)
|
||||
{
|
||||
if (v->x > val)
|
||||
dst->x = val;
|
||||
if (v->y > val)
|
||||
dst->y = val;
|
||||
}
|
||||
|
||||
static inline void vec2_max(struct vec2 *dst, const struct vec2 *v,
|
||||
const struct vec2 *max_v)
|
||||
{
|
||||
if (v->x > max_v->x)
|
||||
dst->x = max_v->x;
|
||||
if (v->y > max_v->y)
|
||||
dst->y = max_v->y;
|
||||
}
|
||||
|
||||
EXPORT void vec2_abs(struct vec2 *dst, const struct vec2 *v);
|
||||
EXPORT void vec2_floor(struct vec2 *dst, const struct vec2 *v);
|
||||
EXPORT void vec2_ceil(struct vec2 *dst, const struct vec2 *v);
|
||||
EXPORT int vec2_close(const struct vec2 *v1, const struct vec2 *v2,
|
||||
float epsilon);
|
||||
EXPORT void vec2_norm(struct vec2 *dst, const struct vec2 *v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
91
libobs/graphics/vec3.c
Normal file
91
libobs/graphics/vec3.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "vec3.h"
|
||||
#include "vec4.h"
|
||||
#include "quat.h"
|
||||
#include "axisang.h"
|
||||
#include "plane.h"
|
||||
#include "matrix3.h"
|
||||
#include "math-extra.h"
|
||||
|
||||
void vec3_from_vec4(struct vec3 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->m = v->m;
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
float vec3_plane_dist(const struct vec3 *v, const struct plane *p)
|
||||
{
|
||||
return vec3_dot(v, &p->dir) - p->dist;
|
||||
}
|
||||
|
||||
void vec3_rotate(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix3 *m)
|
||||
{
|
||||
struct vec3 temp;
|
||||
vec3_copy(&temp, v);
|
||||
|
||||
dst->x = vec3_dot(&temp, &m->x);
|
||||
dst->y = vec3_dot(&temp, &m->y);
|
||||
dst->z = vec3_dot(&temp, &m->z);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
void vec3_transform(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct vec4 v4;
|
||||
vec4_from_vec3(&v4, v);
|
||||
vec4_transform(&v4, &v4, m);
|
||||
vec3_from_vec4(dst, &v4);
|
||||
}
|
||||
|
||||
void vec3_transform3x4(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix3 *m)
|
||||
{
|
||||
struct vec3 temp;
|
||||
vec3_sub(&temp, v, &m->t);
|
||||
|
||||
dst->x = vec3_dot(&temp, &m->x);
|
||||
dst->y = vec3_dot(&temp, &m->y);
|
||||
dst->z = vec3_dot(&temp, &m->z);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
void vec3_mirror(struct vec3 *dst, const struct vec3 *v, const struct plane *p)
|
||||
{
|
||||
struct vec3 temp;
|
||||
vec3_mulf(&temp, &p->dir, vec3_plane_dist(v, p) * 2.0f);
|
||||
vec3_sub(dst, v, &temp);
|
||||
}
|
||||
|
||||
void vec3_mirrorv(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct vec3 *vec)
|
||||
{
|
||||
struct vec3 temp;
|
||||
vec3_mulf(&temp, vec, vec3_dot(v, vec) * 2.0f);
|
||||
vec3_sub(dst, v, &temp);
|
||||
}
|
||||
|
||||
void vec3_rand(struct vec3 *dst, int positive_only)
|
||||
{
|
||||
dst->x = rand_float(positive_only);
|
||||
dst->y = rand_float(positive_only);
|
||||
dst->z = rand_float(positive_only);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
244
libobs/graphics/vec3.h
Normal file
244
libobs/graphics/vec3.h
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math-defs.h"
|
||||
#include "vec4.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct plane;
|
||||
struct matrix3;
|
||||
struct matrix4;
|
||||
struct quat;
|
||||
|
||||
struct vec3 {
|
||||
union {
|
||||
struct {
|
||||
float x, y, z, w;
|
||||
};
|
||||
float ptr[4];
|
||||
__m128 m;
|
||||
};
|
||||
};
|
||||
|
||||
static inline void vec3_zero(struct vec3 *v)
|
||||
{
|
||||
v->m = _mm_setzero_ps();
|
||||
}
|
||||
|
||||
static inline void vec3_set(struct vec3 *dst, float x, float y, float z)
|
||||
{
|
||||
dst->m = _mm_set_ps(0.0f, z, y, x);
|
||||
}
|
||||
|
||||
static inline void vec3_copy(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->m = v->m;
|
||||
}
|
||||
|
||||
EXPORT void vec3_from_vec4(struct vec3 *dst, const struct vec4 *v);
|
||||
|
||||
static inline void vec3_add(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_add_ps(v1->m, v2->m);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_sub(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_sub_ps(v1->m, v2->m);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_mul(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_mul_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec3_div(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_div_ps(v1->m, v2->m);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_addf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_add_ps(v->m, _mm_set1_ps(f));
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_subf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_sub_ps(v->m, _mm_set1_ps(f));
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_mulf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_mul_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec3_divf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_div_ps(v->m, _mm_set1_ps(f));
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline float vec3_dot(const struct vec3 *v1, const struct vec3 *v2)
|
||||
{
|
||||
struct vec3 add;
|
||||
__m128 mul = _mm_mul_ps(v1->m, v2->m);
|
||||
add.m = _mm_add_ps(_mm_movehl_ps(mul, mul), mul);
|
||||
add.m = _mm_add_ps(_mm_shuffle_ps(add.m, add.m, 0x55), add.m);
|
||||
return add.x;
|
||||
}
|
||||
|
||||
static inline void vec3_cross(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
__m128 s1v1 = _mm_shuffle_ps(v1->m, v1->m, _MM_SHUFFLE(3, 0, 2, 1));
|
||||
__m128 s1v2 = _mm_shuffle_ps(v2->m, v2->m, _MM_SHUFFLE(3, 1, 0, 2));
|
||||
__m128 s2v1 = _mm_shuffle_ps(v1->m, v1->m, _MM_SHUFFLE(3, 1, 0, 2));
|
||||
__m128 s2v2 = _mm_shuffle_ps(v2->m, v2->m, _MM_SHUFFLE(3, 0, 2, 1));
|
||||
dst->m = _mm_sub_ps(_mm_mul_ps(s1v1, s1v2), _mm_mul_ps(s2v1, s2v2));
|
||||
}
|
||||
|
||||
static inline void vec3_neg(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->x = -v->x;
|
||||
dst->y = -v->y;
|
||||
dst->z = -v->z;
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline float vec3_len(const struct vec3 *v)
|
||||
{
|
||||
float dot_val = vec3_dot(v, v);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline float vec3_dist(const struct vec3 *v1, const struct vec3 *v2)
|
||||
{
|
||||
struct vec3 temp;
|
||||
float dot_val;
|
||||
|
||||
vec3_sub(&temp, v1, v2);
|
||||
dot_val = vec3_dot(&temp, &temp);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_norm(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
float dot_val = vec3_dot(v, v);
|
||||
dst->m = (dot_val > 0.0f) ?
|
||||
_mm_mul_ps(v->m, _mm_set1_ps(1.0f/sqrtf(dot_val))) :
|
||||
_mm_setzero_ps();
|
||||
}
|
||||
|
||||
static inline bool vec3_close(const struct vec3 *v1, const struct vec3 *v2,
|
||||
float epsilon)
|
||||
{
|
||||
struct vec3 test;
|
||||
vec3_sub(&test, v1, v2);
|
||||
return test.x < epsilon && test.y < epsilon && test.z < epsilon;
|
||||
}
|
||||
|
||||
static inline void vec3_min(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_min_ps(v1->m, v2->m);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_minf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_min_ps(v->m, _mm_set1_ps(f));
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_max(struct vec3 *dst, const struct vec3 *v1,
|
||||
const struct vec3 *v2)
|
||||
{
|
||||
dst->m = _mm_max_ps(v1->m, v2->m);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_maxf(struct vec3 *dst, const struct vec3 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_max_ps(v->m, _mm_set1_ps(f));
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_abs(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->x = fabsf(v->x);
|
||||
dst->y = fabsf(v->y);
|
||||
dst->z = fabsf(v->z);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_floor(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->x = floorf(v->x);
|
||||
dst->y = floorf(v->y);
|
||||
dst->z = floorf(v->z);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec3_ceil(struct vec3 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->x = ceilf(v->x);
|
||||
dst->y = ceilf(v->y);
|
||||
dst->z = ceilf(v->z);
|
||||
dst->w = 0.0f;
|
||||
}
|
||||
|
||||
EXPORT float vec3_plane_dist(const struct vec3 *v, const struct plane *p);
|
||||
|
||||
EXPORT void vec3_transform(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix4 *m);
|
||||
|
||||
EXPORT void vec3_rotate(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix3 *m);
|
||||
EXPORT void vec3_transform3x4(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct matrix3 *m);
|
||||
|
||||
EXPORT void vec3_mirror(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct plane *p);
|
||||
EXPORT void vec3_mirrorv(struct vec3 *dst, const struct vec3 *v,
|
||||
const struct vec3 *vec);
|
||||
|
||||
EXPORT void vec3_rand(struct vec3 *dst, int positive_only);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
42
libobs/graphics/vec4.c
Normal file
42
libobs/graphics/vec4.c
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "vec4.h"
|
||||
#include "vec3.h"
|
||||
#include "matrix4.h"
|
||||
|
||||
void vec4_from_vec3(struct vec4 *dst, const struct vec3 *v)
|
||||
{
|
||||
dst->m = v->m;
|
||||
dst->w = 1.0f;
|
||||
}
|
||||
|
||||
void vec4_transform(struct vec4 *dst, const struct vec4 *v,
|
||||
const struct matrix4 *m)
|
||||
{
|
||||
struct vec4 temp;
|
||||
struct matrix4 transpose;
|
||||
|
||||
matrix4_transpose(&transpose, m);
|
||||
|
||||
temp.x = vec4_dot(&transpose.x, v);
|
||||
temp.y = vec4_dot(&transpose.y, v);
|
||||
temp.z = vec4_dot(&transpose.z, v);
|
||||
temp.w = vec4_dot(&transpose.t, v);
|
||||
|
||||
vec4_copy(dst, &temp);
|
||||
}
|
||||
253
libobs/graphics/vec4.h
Normal file
253
libobs/graphics/vec4.h
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math-defs.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct vec3;
|
||||
struct matrix4;
|
||||
|
||||
struct vec4 {
|
||||
union {
|
||||
struct {
|
||||
float x, y, z, w;
|
||||
};
|
||||
float ptr[4];
|
||||
__m128 m;
|
||||
};
|
||||
};
|
||||
|
||||
static inline void vec4_zero(struct vec4 *v)
|
||||
{
|
||||
v->m = _mm_setzero_ps();
|
||||
}
|
||||
|
||||
static inline void vec4_set(struct vec4 *dst, float x, float y, float z,
|
||||
float w)
|
||||
{
|
||||
dst->m = _mm_set_ps(w, z, y, x);
|
||||
}
|
||||
|
||||
static inline void vec4_copy(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->m = v->m;
|
||||
}
|
||||
|
||||
EXPORT void vec4_from_vec3(struct vec4 *dst, const struct vec3 *v);
|
||||
|
||||
static inline void vec4_add(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_add_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_sub(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_sub_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_mul(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_mul_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_div(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_div_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_addf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_add_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec4_subf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_sub_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec4_mulf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_mul_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec4_divf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_div_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline float vec4_dot(const struct vec4 *v1, const struct vec4 *v2)
|
||||
{
|
||||
struct vec4 add;
|
||||
__m128 mul = _mm_mul_ps(v1->m, v2->m);
|
||||
add.m = _mm_add_ps(_mm_movehl_ps(mul, mul), mul);
|
||||
add.m = _mm_add_ps(_mm_shuffle_ps(add.m, add.m, 0x55), add.m);
|
||||
return add.x;
|
||||
}
|
||||
|
||||
static inline void vec4_neg(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->x = -v->x;
|
||||
dst->y = -v->y;
|
||||
dst->z = -v->z;
|
||||
dst->w = -v->w;
|
||||
}
|
||||
|
||||
static inline float vec4_len(const struct vec4 *v)
|
||||
{
|
||||
float dot_val = vec4_dot(v, v);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline float vec4_dist(const struct vec4 *v1, const struct vec4 *v2)
|
||||
{
|
||||
struct vec4 temp;
|
||||
float dot_val;
|
||||
|
||||
vec4_sub(&temp, v1, v2);
|
||||
dot_val = vec4_dot(&temp, &temp);
|
||||
return (dot_val > 0.0f) ? sqrtf(dot_val) : 0.0f;
|
||||
}
|
||||
|
||||
static inline void vec4_norm(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
float dot_val = vec4_dot(v, v);
|
||||
dst->m = (dot_val > 0.0f) ?
|
||||
_mm_mul_ps(v->m, _mm_set1_ps(1.0f/sqrtf(dot_val))) :
|
||||
_mm_setzero_ps();
|
||||
}
|
||||
|
||||
static inline int vec4_close(const struct vec4 *v1, const struct vec4 *v2,
|
||||
float epsilon)
|
||||
{
|
||||
struct vec4 test;
|
||||
vec4_sub(&test, v1, v2);
|
||||
return test.x < epsilon &&
|
||||
test.y < epsilon &&
|
||||
test.z < epsilon &&
|
||||
test.w < epsilon;
|
||||
}
|
||||
|
||||
static inline void vec4_min(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_min_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_minf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_min_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec4_max(struct vec4 *dst, const struct vec4 *v1,
|
||||
const struct vec4 *v2)
|
||||
{
|
||||
dst->m = _mm_max_ps(v1->m, v2->m);
|
||||
}
|
||||
|
||||
static inline void vec4_maxf(struct vec4 *dst, const struct vec4 *v,
|
||||
float f)
|
||||
{
|
||||
dst->m = _mm_max_ps(v->m, _mm_set1_ps(f));
|
||||
}
|
||||
|
||||
static inline void vec4_abs(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->x = fabsf(v->x);
|
||||
dst->y = fabsf(v->y);
|
||||
dst->z = fabsf(v->z);
|
||||
dst->w = fabsf(v->w);
|
||||
}
|
||||
|
||||
static inline void vec4_floor(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->x = floorf(v->x);
|
||||
dst->y = floorf(v->y);
|
||||
dst->z = floorf(v->z);
|
||||
dst->w = floorf(v->w);
|
||||
}
|
||||
|
||||
static inline void vec4_ceil(struct vec4 *dst, const struct vec4 *v)
|
||||
{
|
||||
dst->x = ceilf(v->x);
|
||||
dst->y = ceilf(v->y);
|
||||
dst->z = ceilf(v->z);
|
||||
dst->w = ceilf(v->w);
|
||||
}
|
||||
|
||||
static inline uint32_t vec4_to_rgba(const struct vec4 *src)
|
||||
{
|
||||
uint32_t val;
|
||||
val = (uint32_t)((double)src->x * 255.0);
|
||||
val |= (uint32_t)((double)src->y * 255.0) << 8;
|
||||
val |= (uint32_t)((double)src->z * 255.0) << 16;
|
||||
val |= (uint32_t)((double)src->w * 255.0) << 24;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t vec4_to_bgra(const struct vec4 *src)
|
||||
{
|
||||
uint32_t val;
|
||||
val = (uint32_t)((double)src->z * 255.0);
|
||||
val |= (uint32_t)((double)src->y * 255.0) << 8;
|
||||
val |= (uint32_t)((double)src->x * 255.0) << 16;
|
||||
val |= (uint32_t)((double)src->w * 255.0) << 24;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void vec4_from_rgba(struct vec4 *dst, uint32_t rgba)
|
||||
{
|
||||
dst->x = (float)((double)(rgba&0xFF) * (1.0/255.0));
|
||||
rgba >>= 8;
|
||||
dst->y = (float)((double)(rgba&0xFF) * (1.0/255.0));
|
||||
rgba >>= 8;
|
||||
dst->z = (float)((double)(rgba&0xFF) * (1.0/255.0));
|
||||
rgba >>= 8;
|
||||
dst->w = (float)((double)(rgba&0xFF) * (1.0/255.0));
|
||||
}
|
||||
|
||||
static inline void vec4_from_bgra(struct vec4 *dst, uint32_t bgra)
|
||||
{
|
||||
dst->z = (float)((double)(bgra&0xFF) * (1.0/255.0));
|
||||
bgra >>= 8;
|
||||
dst->y = (float)((double)(bgra&0xFF) * (1.0/255.0));
|
||||
bgra >>= 8;
|
||||
dst->x = (float)((double)(bgra&0xFF) * (1.0/255.0));
|
||||
bgra >>= 8;
|
||||
dst->w = (float)((double)(bgra&0xFF) * (1.0/255.0));
|
||||
}
|
||||
|
||||
EXPORT void vec4_transform(struct vec4 *dst, const struct vec4 *v,
|
||||
const struct matrix4 *m);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue