- Reestructuración de ficheros y directorios general
- merge v0.01 --> Añadido fileselector - Añadidas fuentes de Gem y Pure Data - pix2jpg incluído en Gem. Archivos de construcción de Gem modificados. - Añadido fichero ompiling.txt con instrucciones de compilación
This commit is contained in:
parent
c9adfd020b
commit
e85d191b46
3100 changed files with 775434 additions and 3073 deletions
229
Gem/src/Base/CPPExtern.cpp
Normal file
229
Gem/src/Base/CPPExtern.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// mark@danks.org
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "CPPExtern.h"
|
||||
|
||||
#include "RTE/RTE.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
|
||||
# define snprintf _snprintf
|
||||
# define vsnprintf _vsnprintf
|
||||
# define close _close
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
void *Obj_header::operator new(size_t, void *location, void *) {
|
||||
return(location);
|
||||
}
|
||||
|
||||
t_object * CPPExtern::m_holder=NULL;
|
||||
char* CPPExtern::m_holdname=NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPPExtern
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
CPPExtern :: CPPExtern()
|
||||
: x_obj(m_holder),
|
||||
m_objectname(NULL),
|
||||
m_canvas(NULL),
|
||||
m_endpost(true)
|
||||
{
|
||||
m_canvas = canvas_getcurrent();
|
||||
if(m_holdname) {
|
||||
m_objectname=gensym(m_holdname);
|
||||
} else {
|
||||
m_objectname=gensym("unknown Gem object");
|
||||
}
|
||||
}
|
||||
CPPExtern :: CPPExtern(const CPPExtern&org) :
|
||||
x_obj(org.x_obj),
|
||||
m_objectname(org.m_objectname),
|
||||
m_canvas(org.m_canvas),
|
||||
m_endpost(true)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
CPPExtern :: ~CPPExtern()
|
||||
{ }
|
||||
|
||||
|
||||
void CPPExtern :: post(const char*fmt,...) const
|
||||
{
|
||||
char buf[MAXPDSTRING];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
|
||||
va_end(ap);
|
||||
if(m_endpost && NULL!=m_objectname && NULL!=m_objectname->s_name && &s_ != m_objectname){
|
||||
::post("[%s]: %s", m_objectname->s_name, buf);
|
||||
} else {
|
||||
::post("%s", buf);
|
||||
}
|
||||
m_endpost=true;
|
||||
}
|
||||
void CPPExtern :: startpost(const char*fmt,...) const
|
||||
{
|
||||
char buf[MAXPDSTRING];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
|
||||
va_end(ap);
|
||||
if(m_endpost && NULL!=m_objectname && NULL!=m_objectname->s_name && &s_ != m_objectname){
|
||||
::startpost("[%s]: %s", m_objectname->s_name, buf);
|
||||
} else {
|
||||
::startpost("%s", buf);
|
||||
}
|
||||
m_endpost=false;
|
||||
}
|
||||
void CPPExtern :: endpost(void) const
|
||||
{
|
||||
::endpost();
|
||||
m_endpost=true;
|
||||
}
|
||||
typedef void (*verbose_t)(int level, const char *fmt, ...);
|
||||
|
||||
void CPPExtern :: verbose(const int level, const char*fmt,...) const
|
||||
{
|
||||
char buf[MAXPDSTRING];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
|
||||
va_end(ap);
|
||||
static verbose_t rte_verbose=NULL;
|
||||
static bool rte_verbose_checked=false;
|
||||
if(false==rte_verbose_checked) {
|
||||
gem::RTE::RTE*rte=gem::RTE::RTE::getRuntimeEnvironment();
|
||||
if(rte) {
|
||||
rte_verbose=(verbose_t)rte->getFunction("verbose");
|
||||
}
|
||||
}
|
||||
rte_verbose_checked=true;
|
||||
|
||||
/* only pd>=0.39(?) supports ::verbose() */
|
||||
if(rte_verbose) {
|
||||
if(NULL!=m_objectname && NULL!=m_objectname->s_name && &s_ != m_objectname){
|
||||
rte_verbose(level, "[%s]: %s", m_objectname->s_name, buf);
|
||||
} else {
|
||||
rte_verbose(level, "%s", buf);
|
||||
}
|
||||
} else {
|
||||
if(NULL!=m_objectname && NULL!=m_objectname->s_name && &s_ != m_objectname){
|
||||
::post("[%s]: %s", m_objectname->s_name, buf);
|
||||
} else {
|
||||
::post("%s", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPPExtern :: error(const char*fmt,...) const
|
||||
{
|
||||
char buf[MAXPDSTRING];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
|
||||
va_end(ap);
|
||||
if(NULL!=m_objectname && NULL!=m_objectname->s_name && &s_ != m_objectname){
|
||||
char*objname=m_objectname->s_name;
|
||||
if(x_obj)
|
||||
pd_error(x_obj, "[%s]: %s", objname, buf);
|
||||
else if (m_holder)
|
||||
pd_error(m_holder, "[%s]: %s", objname, buf);
|
||||
else
|
||||
::error("[%s]: %s", objname, buf);
|
||||
} else {
|
||||
if(x_obj)
|
||||
pd_error(x_obj, "%s", buf);
|
||||
else if (m_holder)
|
||||
pd_error(m_holder, "%s", buf);
|
||||
else
|
||||
::error("%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*close_t)(int fd);
|
||||
|
||||
std::string CPPExtern::findFile(const std::string f, const std::string e) const {
|
||||
char buf[MAXPDSTRING], buf2[MAXPDSTRING];
|
||||
char*bufptr=0;
|
||||
std::string result="";
|
||||
int fd=-1;
|
||||
|
||||
t_canvas*canvas=const_cast<t_canvas*>(getCanvas());
|
||||
char*filename=const_cast<char*>(f.c_str());
|
||||
char*ext=const_cast<char*>(e.c_str());
|
||||
|
||||
if ((fd=open_via_path(canvas_getdir(canvas)->s_name, filename, ext,
|
||||
buf2, &bufptr, MAXPDSTRING, 1))>=0){
|
||||
static close_t rte_close=NULL;
|
||||
if(NULL==rte_close) {
|
||||
gem::RTE::RTE*rte=gem::RTE::RTE::getRuntimeEnvironment();
|
||||
if(rte) {
|
||||
rte_close=(close_t)rte->getFunction("sys_close");
|
||||
}
|
||||
if(NULL==rte_close) {
|
||||
rte_close=close;
|
||||
}
|
||||
}
|
||||
rte_close(fd);
|
||||
|
||||
result=buf2;
|
||||
result+="/";
|
||||
result+=bufptr;
|
||||
} else {
|
||||
canvas_makefilename(canvas, filename, buf, MAXPDSTRING);
|
||||
result=buf;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CPPExtern::findFile(const std::string file) const {
|
||||
return findFile(file, "");
|
||||
|
||||
}
|
||||
bool CPPExtern :: checkGemVersion(const int major, const int minor) {
|
||||
if(!GemVersion::versionCheck(major, minor)) {
|
||||
::error("GEM version mismatch: compiled for %d.%d but we are running %s",
|
||||
major, minor,
|
||||
GemVersion::versionString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CPPExtern&CPPExtern::operator=(const CPPExtern&org) {
|
||||
x_obj=org.x_obj;
|
||||
m_objectname=org.m_objectname;
|
||||
m_canvas=org.m_canvas;
|
||||
m_endpost=true;
|
||||
return *this;
|
||||
}
|
||||
371
Gem/src/Base/CPPExtern.h
Normal file
371
Gem/src/Base/CPPExtern.h
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The base class for all externs written in C++
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_CPPEXTERN_H_
|
||||
#define _INCLUDE__GEM_BASE_CPPEXTERN_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
#include "Gem/Version.h"
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
class CPPExtern;
|
||||
|
||||
/* forward declaration of a generic exception handler for GemExceptions */
|
||||
namespace gem {
|
||||
GEM_EXTERN void catchGemException(const char*objname, const t_object*obj);
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
Obj_header
|
||||
|
||||
The obligatory object header
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This is in a separate struct to assure that when PD uses the
|
||||
class, the t_object is the very first thing. If it were the
|
||||
first thing in CPPExtern, then there could be problems with
|
||||
the vtable.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
struct GEM_EXTERN Obj_header
|
||||
{
|
||||
//////////
|
||||
// The obligatory object header
|
||||
t_object pd_obj;
|
||||
|
||||
//////////
|
||||
// Our data structure
|
||||
CPPExtern *data;
|
||||
|
||||
// This has a dummy arg so that NT won't complain
|
||||
void *operator new(size_t, void *location, void *dummy);
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
CPPExtern
|
||||
|
||||
The base class for all externs written in C++
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Each extern which is written in C++ needs to use the #defines at the
|
||||
end of this header file. Currently, the operator new(size_t) and
|
||||
operator delete(void *) are not overridden. This will be a problem
|
||||
when PD expects everything to fit in its memory space and control
|
||||
all memory allocation.
|
||||
|
||||
The define
|
||||
|
||||
CPPEXTERN_HEADER(NEW_CLASS, PARENT_CLASS);
|
||||
|
||||
should be somewhere in your header file.
|
||||
One of the defines like
|
||||
|
||||
CPPEXTERN_NEW(NEW_CLASS);
|
||||
CPPEXTERN_NEW_WITH_TWO_ARGS(NEW_CLASS, t_floatarg, A_FLOAT, t_floatarg, A_FLOAT);
|
||||
|
||||
should be the first thing in your implementation file.
|
||||
NEW_CLASS is the name of your class and PARENT_CLASS is the
|
||||
parent of your class.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN CPPExtern
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
CPPExtern(void);
|
||||
|
||||
//////////
|
||||
// The Pd header
|
||||
t_object *x_obj;
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~CPPExtern(void) = 0;
|
||||
|
||||
//////////
|
||||
// Get the object's canvas
|
||||
const t_canvas *getCanvas(void) const { return(m_canvas); }
|
||||
|
||||
//////////
|
||||
// This is a holder - don't touch it
|
||||
static t_object *m_holder;
|
||||
|
||||
//////////
|
||||
// my name
|
||||
static char *m_holdname;
|
||||
t_symbol *m_objectname;
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Creation callback
|
||||
static void real_obj_setupCallback(t_class *) {}
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// The canvas that the object is in
|
||||
t_canvas *m_canvas;
|
||||
|
||||
public:
|
||||
// these call pd's print-functions, and eventually prepend the object's name
|
||||
void startpost(const char*format, ...) const;
|
||||
void post(const char*format, ...) const;
|
||||
void endpost(void) const;
|
||||
void verbose(const int level, const char*format, ...) const;
|
||||
void error(const char*format, ...) const; /* internally uses pd_error() */
|
||||
|
||||
// searches for a file based on the parent abstraction's path
|
||||
// wraps open_via_path() and canvas_makefilename()
|
||||
// the full filename is returned
|
||||
// if the file does not exist, it is constructed
|
||||
std::string findFile(const std::string filename, const std::string ext) const;
|
||||
std::string findFile(const std::string filename) const;
|
||||
|
||||
private:
|
||||
mutable bool m_endpost; /* internal state for startpost/post/endpost */
|
||||
static bool checkGemVersion(const int major, const int minor);
|
||||
CPPExtern(const CPPExtern&);
|
||||
virtual CPPExtern&operator=(const CPPExtern&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// This should be used in the header
|
||||
////////////////////////////////////////
|
||||
|
||||
#define CPPEXTERN_HEADER(NEW_CLASS, PARENT_CLASS) \
|
||||
public: \
|
||||
static void obj_freeCallback(void *data) \
|
||||
{ CPPExtern *mydata = ((Obj_header *)data)->data; delete mydata; \
|
||||
((Obj_header *)data)->Obj_header::~Obj_header(); } \
|
||||
static void real_obj_setupCallback(t_class *classPtr) \
|
||||
{ PARENT_CLASS::real_obj_setupCallback(classPtr); \
|
||||
NEW_CLASS::obj_setupCallback(classPtr); } \
|
||||
private: \
|
||||
static inline NEW_CLASS *GetMyClass(void *data) {return((NEW_CLASS *)((Obj_header *)data)->data);} \
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// This should be the first thing in the implementation file
|
||||
////////////////////////////////////////
|
||||
|
||||
//
|
||||
// NO ARGUMENTS
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW(NEW_CLASS) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (void) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// ONE ARGUMENT
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_ONE_ARG(NEW_CLASS, TYPE, PD_TYPE) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (TYPE arg) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(arg); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
PD_TYPE, \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// GIMME ARGUMENT
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_GIMME(NEW_CLASS) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (t_symbol*s, int argc, t_atom*argv) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(argc,argv); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
A_GIMME, \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// TWO ARGUMENTS
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_TWO_ARGS(NEW_CLASS, TYPE, PD_TYPE, TTWO, PD_TWO) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (TYPE arg, TTWO arg2) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(arg, arg2); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
PD_TYPE, PD_TWO, \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// THREE ARGUMENTS
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_THREE_ARGS(NEW_CLASS, TYPE, PD_TYPE, TTWO, PD_TWO, TTHREE, PD_THREE) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (TYPE arg, TTWO arg2, TTHREE arg3) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(arg, arg2, arg3); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
PD_TYPE, PD_TWO, PD_THREE, \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// FOUR ARGUMENTS
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_FOUR_ARGS(NEW_CLASS, TYPE, PD_TYPE, TTWO, PD_TWO, TTHREE, PD_THREE, TFOUR, PD_FOUR) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (TYPE arg, TTWO arg2, TTHREE arg3, TFOUR arg4) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(arg, arg2, arg3, arg4); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
PD_TYPE, PD_TWO, PD_THREE, PD_FOUR, \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
//
|
||||
// FIVE ARGUMENTS
|
||||
/////////////////////////////////////////////////
|
||||
#define CPPEXTERN_NEW_WITH_FIVE_ARGS(NEW_CLASS, TYPE, PD_TYPE, TTWO, PD_TWO, TTHREE, PD_THREE, TFOUR, PD_FOUR, TFIVE, PD_FIVE) \
|
||||
REAL_NEW__CLASS(NEW_CLASS); \
|
||||
static void* create_ ## NEW_CLASS (TYPE arg, TTWO arg2, TTHREE arg3, TFOUR arg4, TFIVE arg5) \
|
||||
REAL_NEW__CREATE1(NEW_CLASS) \
|
||||
obj->data = new NEW_CLASS(arg, arg2, arg3, arg4, arg5); \
|
||||
REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
PD_TYPE, PD_TWO, PD_THREE, PD_FOUR, PD_FIVE \
|
||||
REAL_NEW__SETUP2(NEW_CLASS)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// These should never be called or used directly!!!
|
||||
//
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define REAL_NEW__CLASS(NEW_CLASS) STATIC_CLASS t_class * NEW_CLASS ## _class
|
||||
#define REAL_NEW__CREATE1(NEW_CLASS) { \
|
||||
try{ \
|
||||
Obj_header *obj = new (pd_new(NEW_CLASS ## _class),(void *)NULL) Obj_header; \
|
||||
CPPExtern::m_holder = &obj->pd_obj; \
|
||||
CPPExtern::m_holdname=(char*)#NEW_CLASS;
|
||||
|
||||
#define REAL_NEW__CREATE2(NEW_CLASS) \
|
||||
CPPExtern::m_holder = NULL; \
|
||||
CPPExtern::m_holdname=NULL; \
|
||||
return(obj); \
|
||||
} catch (...) {gem::catchGemException(CPPExtern::m_holdname, CPPExtern::m_holder); return NULL;} \
|
||||
}
|
||||
|
||||
#define REAL_NEW__SETUP1(NEW_CLASS) \
|
||||
extern "C" { \
|
||||
GEM_EXPORT void NEW_CLASS ## _setup(void) \
|
||||
{ \
|
||||
static int recalled=0; if(recalled)return; recalled=1; \
|
||||
NEW_CLASS ## _class = class_new( \
|
||||
gensym(#NEW_CLASS), \
|
||||
(t_newmethod)create_ ## NEW_CLASS, \
|
||||
(t_method)&NEW_CLASS::obj_freeCallback, \
|
||||
sizeof(Obj_header), GEM_CLASSFLAGS,
|
||||
#define REAL_NEW__SETUP2(NEW_CLASS) \
|
||||
A_NULL); \
|
||||
SET_HELPSYMBOL(NEW_CLASS); \
|
||||
NEW_CLASS::real_obj_setupCallback(NEW_CLASS ## _class); \
|
||||
} \
|
||||
} \
|
||||
AUTO_REGISTER_CLASS(NEW_CLASS);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static class:
|
||||
// by default classes are declared static
|
||||
// however, sometimes we need classes not-static, so we can refer to them
|
||||
// from other classes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef NO_STATIC_CLASS
|
||||
# define STATIC_CLASS
|
||||
#else
|
||||
# define STATIC_CLASS static
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// auto registering a class
|
||||
// this creates a dummy class, whose constructor calls the setup-function
|
||||
// (registering the class with pd)
|
||||
// a static copy of this class is created at runtime, to actually do the setup-call
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef NO_AUTO_REGISTER_CLASS
|
||||
// if NO_AUTO_REGISTER_CLASS is defined, we will not register the class
|
||||
# define AUTO_REGISTER_CLASS(NEW_CLASS) \
|
||||
static int NEW_CLASS ## _dummyinstance
|
||||
#else
|
||||
// for debugging we can show the which classes are auto-registering
|
||||
# if 0
|
||||
# define POST_AUTOREGISTER(NEW_CLASS) post("auto-registering: "#NEW_CLASS)
|
||||
# else
|
||||
# define POST_AUTOREGISTER(NEW_CLASS)
|
||||
# endif
|
||||
# define AUTO_REGISTER_CLASS(NEW_CLASS) \
|
||||
class NEW_CLASS ## _cppclass { \
|
||||
public: \
|
||||
NEW_CLASS ## _cppclass(void) {POST_AUTOREGISTER(NEW_CLASS); NEW_CLASS ## _setup(); } \
|
||||
}; \
|
||||
static NEW_CLASS ## _cppclass NEW_CLASS ## _instance
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// setting the help-symbol
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if defined HELPSYMBOL_BASE || defined HELPSYMBOL
|
||||
# ifndef HELPSYMBOL_BASE
|
||||
# define HELPSYMBOL_BASE ""
|
||||
# endif
|
||||
|
||||
# ifndef HELPSYMBOL
|
||||
# define SET_HELPSYMBOL(NEW_CLASS) \
|
||||
class_sethelpsymbol(NEW_CLASS ## _class, gensym(HELPSYMBOL_BASE #NEW_CLASS))
|
||||
# else
|
||||
# define SET_HELPSYMBOL(NEW_CLASS) \
|
||||
class_sethelpsymbol(NEW_CLASS ## _class, gensym(HELPSYMBOL_BASE HELPSYMBOL))
|
||||
# endif
|
||||
|
||||
#else
|
||||
# define SET_HELPSYMBOL(NEW_CLASS)
|
||||
#endif /* HELPSYMBOL */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// setting the class-flags
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef GEM_CLASSFLAGS
|
||||
# define GEM_CLASSFLAGS 0
|
||||
#endif
|
||||
|
||||
// macros for boilerplate code to object messages
|
||||
#include "RTE/MessageCallbacks.h"
|
||||
|
||||
#endif // for header file
|
||||
242
Gem/src/Base/GemBase.cpp
Normal file
242
Gem/src/Base/GemBase.cpp
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
* m_state: context dependent initialization state
|
||||
*
|
||||
* states:
|
||||
*
|
||||
* INIT: a context has just been created; initialize the object for this context
|
||||
* DISABLED: the object is not useable in this context
|
||||
* ENABLED: the object can run in this context; however, no context-ressources have been allocated yet (needs startRendering())
|
||||
* RENDERING: startRendering() has been called and we can render this object just fine...
|
||||
* MODIFIED: the object has been modified, and need to free it's context-ressources (stopRendering()) and request new ones (startRendering())
|
||||
*
|
||||
* state-change triggers:
|
||||
* reset(): -> INIT
|
||||
* setModified(): -> MODIFIED
|
||||
*
|
||||
* state-changers:
|
||||
* isRunnable(); INIT -> ENABLED|DISABLED
|
||||
* startRendering(): ENABLED->RENDERING
|
||||
* stopRendering(): MODIFIED->ENABLED
|
||||
*
|
||||
* 0..INIT ( => isRunnable() -> (startRendering() -> RENDERING) (-> DISABLED))
|
||||
* 1..RENDERING ( stopRendering() -> STOPPED)
|
||||
* 2..STOPPED ( -> INIT) (startRendering() -> RENDERING)
|
||||
* 3..DISABLED ( -> INIT)
|
||||
*
|
||||
*---
|
||||
* INIT -> isRunnable() -> (DISABLED) (ENABLED)
|
||||
* reset(): DISABLED -> INIT
|
||||
* ENABLED -> startRendering() -> RENDERING
|
||||
* setModified(): ENABLED
|
||||
* STOPPING -> stopRendering() -> ENABLED
|
||||
|
||||
* RENDERING: render()
|
||||
|
||||
* isRunnable() has to be called once for each (new) context
|
||||
* startRendering() has to be called for each context when new IDs are to be generated
|
||||
* stopRendering() has to be called for each context to free IDs
|
||||
|
||||
* we need a mechanism to reset a context (e.g. because a context is destroyed and it's ID might be reused)
|
||||
*/
|
||||
|
||||
#include "GemBase.h"
|
||||
#include "Gem/Cache.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemBase
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemBase :: GemBase(void)
|
||||
: gem_amRendering(false), m_cache(NULL), m_modified(true),
|
||||
m_out1(NULL),
|
||||
m_enabled(true), m_state(INIT)
|
||||
{
|
||||
m_out1 = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemBase :: ~GemBase(void)
|
||||
{
|
||||
if (gem_amRendering){
|
||||
stopRendering();
|
||||
gem_amRendering=false;
|
||||
}
|
||||
|
||||
if (m_out1)
|
||||
outlet_free(m_out1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// gem_cacheMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemBase :: gem_startstopMess(int state)
|
||||
{
|
||||
// for now, this is important, as it is the only way to call the stopRendering
|
||||
#if 1
|
||||
if (state && !gem_amRendering){
|
||||
m_enabled = isRunnable();
|
||||
if(m_enabled) {
|
||||
startRendering();
|
||||
m_state=RENDERING;
|
||||
}
|
||||
}
|
||||
else if (!state && gem_amRendering){
|
||||
if(m_enabled) {
|
||||
stopRendering();
|
||||
m_state=ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
gem_amRendering=(state!=0);
|
||||
|
||||
|
||||
// continue sending out the cache message
|
||||
t_atom ap[1];
|
||||
SETFLOAT(ap, state);
|
||||
outlet_anything(this->m_out1, gensym("gem_state"), 1, ap);
|
||||
#else
|
||||
post("gem_startstopMess(%d) called...please report this to the upstream developers", state);
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// renderMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemBase :: gem_renderMess(GemCache* cache, GemState*state)
|
||||
{
|
||||
m_cache=cache;
|
||||
if(m_cache && m_cache->m_magic!=GEMCACHE_MAGIC)
|
||||
m_cache=NULL;
|
||||
if(INIT==m_state) {
|
||||
if(isRunnable()) {
|
||||
m_state=ENABLED;
|
||||
} else {
|
||||
m_state=DISABLED;
|
||||
}
|
||||
}
|
||||
if(MODIFIED==m_state) {
|
||||
stopRendering();
|
||||
m_state=ENABLED;
|
||||
}
|
||||
if(ENABLED==m_state) {
|
||||
startRendering();
|
||||
m_state=RENDERING;
|
||||
}
|
||||
if(RENDERING==m_state) {
|
||||
gem_amRendering=true;
|
||||
if(state)render(state);
|
||||
continueRender(state);
|
||||
if(state)postrender(state);
|
||||
}
|
||||
m_modified=false;
|
||||
}
|
||||
|
||||
void GemBase :: continueRender(GemState*state){
|
||||
t_atom ap[2];
|
||||
ap->a_type=A_POINTER;
|
||||
ap->a_w.w_gpointer=(t_gpointer *)m_cache; // the cache ?
|
||||
(ap+1)->a_type=A_POINTER;
|
||||
(ap+1)->a_w.w_gpointer=(t_gpointer *)state;
|
||||
outlet_anything(this->m_out1, gensym("gem_state"), 2, ap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setModified
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemBase :: setModified(void)
|
||||
{
|
||||
if (m_cache&& (m_cache->m_magic!=GEMCACHE_MAGIC))
|
||||
m_cache=NULL;
|
||||
if (m_cache) m_cache->dirty = true;
|
||||
m_modified=true;
|
||||
switch(m_state) {
|
||||
case DISABLED:
|
||||
case INIT:
|
||||
break;
|
||||
default:
|
||||
m_state=MODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// realStopRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemBase :: realStopRendering(void)
|
||||
{
|
||||
/* no idea what this function is for; ask the user when it appears */
|
||||
post("realStopRendering() called...please report this to the upstream developers");
|
||||
stopRendering();
|
||||
m_cache = NULL;
|
||||
m_state=ENABLED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// disabling the rendering of this object
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool GemBase :: isRunnable(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
enum GemBase::RenderState GemBase::getState(void) {
|
||||
return m_state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemBase :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&GemBase::gem_MessCallback),
|
||||
gensym("gem_state"), A_GIMME, A_NULL);
|
||||
}
|
||||
void GemBase :: gem_MessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
|
||||
{
|
||||
if (argc==2 && argv->a_type==A_POINTER && (argv+1)->a_type==A_POINTER){
|
||||
GetMyClass(data)->gem_renderMess((GemCache *)argv->a_w.w_gpointer, (GemState *)(argv+1)->a_w.w_gpointer);
|
||||
#if 1
|
||||
} else if (argc==1 && argv->a_type==A_FLOAT){
|
||||
GetMyClass(data)->gem_startstopMess(atom_getint(argv)); // start rendering (forget this !?)
|
||||
#endif
|
||||
} else {
|
||||
GetMyClass(data)->error("wrong arguments in GemTrigger...");
|
||||
}
|
||||
}
|
||||
134
Gem/src/Base/GemBase.h
Normal file
134
Gem/src/Base/GemBase.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The base class for all of the gem objects
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger.
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMBASE_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMBASE_H_
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
#include "Gem/ContextData.h"
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
class GemCache;
|
||||
class GemState;
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemBase
|
||||
|
||||
Base class for gem objects
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemBase : public CPPExtern
|
||||
{
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemBase();
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemBase();
|
||||
|
||||
//////////
|
||||
virtual void render(GemState *state) = 0;
|
||||
|
||||
//////////
|
||||
void continueRender(GemState *state);
|
||||
|
||||
//////////
|
||||
// After objects below you in the chain have finished.
|
||||
// You should reset all GEM/OpenGL states here.
|
||||
virtual void postrender(GemState *) { ; }
|
||||
|
||||
//////////
|
||||
// Called when rendering stops
|
||||
|
||||
#if 1/*(jmz) this seems to be for gem2pdp*/
|
||||
virtual void stoprender() { realStopRendering(); }
|
||||
#endif
|
||||
|
||||
//////////
|
||||
// If you care about the start of rendering
|
||||
virtual void startRendering() { ; }
|
||||
|
||||
//////////
|
||||
// If you care about the stop of rendering
|
||||
virtual void stopRendering() { ; }
|
||||
|
||||
|
||||
//////////
|
||||
// has rendering started ?
|
||||
// deprecated, use 'getState()==RENDERING' instead
|
||||
bool gem_amRendering;
|
||||
|
||||
//////////
|
||||
// If anything in the object has changed
|
||||
virtual void setModified();
|
||||
|
||||
//////////
|
||||
// Don't mess with this unless you know what you are doing.
|
||||
GemCache *m_cache;
|
||||
//////////
|
||||
// check whether this object has changed
|
||||
bool m_modified;
|
||||
|
||||
//////////
|
||||
// The outlet
|
||||
t_outlet *m_out1;
|
||||
|
||||
|
||||
//////////
|
||||
// this gets called in the before the startRendering() routine
|
||||
// if it returns TRUE, the object's startRendering(), render() and stopRendering() functions will be called
|
||||
// it it returns FALSE, the object will be disabled
|
||||
// when rendering is restarted, this function get's called again
|
||||
// the default is to enable rendering
|
||||
// this function is important if you want to disable an object because it cannot be used (e.g. missing driver support)
|
||||
virtual bool isRunnable(void);
|
||||
|
||||
//////////
|
||||
// creation callback
|
||||
static void real_obj_setupCallback(t_class *classPtr)
|
||||
{ CPPExtern::real_obj_setupCallback(classPtr); GemBase::obj_setupCallback(classPtr); }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void realStopRendering();
|
||||
void gem_startstopMess(int state);
|
||||
void gem_renderMess(GemCache* state, GemState* state2);
|
||||
|
||||
static inline GemBase *GetMyClass(void *data) {return((GemBase *)((Obj_header *)data)->data);}
|
||||
|
||||
friend class gemhead;
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
static void gem_MessCallback(void *, t_symbol *,int, t_atom*);
|
||||
|
||||
/* whether the object is internally disabled or not
|
||||
* objects are to be disabled, if the system cannot make use of them, e.g. because of unsupported openGL features
|
||||
*/
|
||||
gem::ContextData<bool>m_enabled;
|
||||
|
||||
enum RenderState {INIT, ENABLED, DISABLED, RENDERING, MODIFIED};
|
||||
gem::ContextData<enum RenderState>m_state;
|
||||
|
||||
protected:
|
||||
enum RenderState getState(void);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
205
Gem/src/Base/GemContext.cpp
Normal file
205
Gem/src/Base/GemContext.cpp
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#include "GemContext.h"
|
||||
#include "Gem/Manager.h"
|
||||
#include "Gem/Exception.h"
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
#include <stack>
|
||||
#include <set>
|
||||
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
# warning multicontext rendering currently under development
|
||||
#endif /* GEM_MULTICONTEXT */
|
||||
|
||||
static GLEWContext*s_glewcontext=NULL;
|
||||
static GemGlewXContext*s_glewxcontext=NULL;
|
||||
|
||||
using namespace gem;
|
||||
|
||||
class Context::PIMPL {
|
||||
public:
|
||||
PIMPL(void) :
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
context(new GLEWContext), xcontext(new GemGlewXContext),
|
||||
#else
|
||||
context(NULL), xcontext(NULL),
|
||||
#endif
|
||||
contextid(makeID())
|
||||
{
|
||||
/* check the stack-sizes */
|
||||
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, maxStackDepth+GemMan::STACKMODELVIEW);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, maxStackDepth+GemMan::STACKTEXTURE);
|
||||
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, maxStackDepth+GemMan::STACKPROJECTION);
|
||||
|
||||
if(GLEW_ARB_imaging)
|
||||
glGetIntegerv(GL_MAX_COLOR_MATRIX_STACK_DEPTH, maxStackDepth+GemMan::STACKCOLOR);
|
||||
else
|
||||
maxStackDepth[GemMan::STACKCOLOR]=0;
|
||||
}
|
||||
|
||||
PIMPL(const PIMPL&p) :
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
context(new GLEWContext(*p.context)), xcontext(new GemGlewXContext(*p.xcontext)),
|
||||
#else
|
||||
context(NULL), xcontext(NULL),
|
||||
#endif
|
||||
contextid(makeID())
|
||||
{
|
||||
/* check the stack-sizes */
|
||||
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, maxStackDepth+GemMan::STACKMODELVIEW);
|
||||
glGetIntegerv(GL_MAX_COLOR_MATRIX_STACK_DEPTH, maxStackDepth+GemMan::STACKCOLOR);
|
||||
glGetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, maxStackDepth+GemMan::STACKTEXTURE);
|
||||
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, maxStackDepth+GemMan::STACKPROJECTION);
|
||||
}
|
||||
|
||||
~PIMPL(void) {
|
||||
freeID(contextid);
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
if(context )delete context; context=NULL;
|
||||
if(xcontext)delete xcontext; xcontext=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
GLint maxStackDepth[4];
|
||||
|
||||
GLEWContext *context;
|
||||
GemGlewXContext*xcontext;
|
||||
|
||||
unsigned int contextid;
|
||||
|
||||
// LATER: reusing IDs prevents a memleak in gem::ContextData
|
||||
// LATER: reusing IDs might make us re-use invalid gem::ContextData!
|
||||
static std::set<unsigned int>s_takenIDs;
|
||||
static unsigned int makeID(void) // GemContext_newid
|
||||
{
|
||||
unsigned int id=0;
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
while(s_takenIDs.find(id) != s_takenIDs.end())
|
||||
id++;
|
||||
#endif /* GEM_MULTICONTEXT */
|
||||
s_takenIDs.insert(id);
|
||||
return id;
|
||||
}
|
||||
static void freeID(unsigned int id)
|
||||
{
|
||||
/* LATER reuse freed ids */
|
||||
/* LATER remove this ID from the s_contextid stack and related (x)context */
|
||||
s_takenIDs.erase(id);
|
||||
}
|
||||
|
||||
static unsigned int s_contextid;
|
||||
static GLEWContext*s_context;
|
||||
static GemGlewXContext*s_xcontext;
|
||||
};
|
||||
unsigned int Context::PIMPL::s_contextid=0;
|
||||
GLEWContext* Context::PIMPL::s_context=NULL;
|
||||
GemGlewXContext*Context::PIMPL::s_xcontext=NULL;
|
||||
std::set<unsigned int> Context::PIMPL::s_takenIDs;
|
||||
|
||||
Context::Context(void)
|
||||
: m_pimpl(new PIMPL())
|
||||
{
|
||||
push();
|
||||
std::string errstring="";
|
||||
|
||||
GLenum err = glewInit();
|
||||
|
||||
if (GLEW_OK != err) {
|
||||
if(GLEW_ERROR_GLX_VERSION_11_ONLY == err) {
|
||||
errstring="failed to init GLEW (glx): continuing anyhow - please report any problems to the gem-dev mailinglist!";
|
||||
} else if (GLEW_ERROR_GL_VERSION_10_ONLY) {
|
||||
errstring="failed to init GLEW: your system only supports openGL-1.0";
|
||||
} else {
|
||||
errstring="failed to init GLEW";
|
||||
}
|
||||
}
|
||||
|
||||
post("GLEW version %s",glewGetString(GLEW_VERSION));
|
||||
|
||||
if(!m_pimpl) {
|
||||
errstring="failed to init GemContext";
|
||||
}
|
||||
|
||||
pop();
|
||||
|
||||
if(!errstring.empty()) {
|
||||
if(m_pimpl)delete m_pimpl; m_pimpl=NULL;
|
||||
throw(GemException(errstring));
|
||||
}
|
||||
GemMan::m_windowState++;
|
||||
}
|
||||
|
||||
Context::Context(const Context&c)
|
||||
: m_pimpl(new PIMPL(*(c.m_pimpl)))
|
||||
{
|
||||
push();
|
||||
post("foo GLEW version %s",glewGetString(GLEW_VERSION));
|
||||
pop();
|
||||
}
|
||||
|
||||
Context&Context::operator=(const Context&c) {
|
||||
if(&c == this || c.m_pimpl == m_pimpl)
|
||||
return (*this);
|
||||
|
||||
if(m_pimpl)delete m_pimpl;
|
||||
m_pimpl=new PIMPL(*c.m_pimpl);
|
||||
push();
|
||||
pop();
|
||||
|
||||
return(*this);
|
||||
}
|
||||
|
||||
|
||||
Context::~Context(void) {
|
||||
if(m_pimpl)delete m_pimpl; m_pimpl=NULL;
|
||||
GemMan::m_windowState--;
|
||||
}
|
||||
|
||||
bool Context::push(void) {
|
||||
GemMan::maxStackDepth[GemMan::STACKMODELVIEW]= m_pimpl->maxStackDepth[GemMan::STACKMODELVIEW];
|
||||
GemMan::maxStackDepth[GemMan::STACKCOLOR]= m_pimpl->maxStackDepth[GemMan::STACKCOLOR];
|
||||
GemMan::maxStackDepth[GemMan::STACKTEXTURE]= m_pimpl->maxStackDepth[GemMan::STACKTEXTURE];
|
||||
GemMan::maxStackDepth[GemMan::STACKPROJECTION]=m_pimpl->maxStackDepth[GemMan::STACKPROJECTION];
|
||||
|
||||
m_pimpl->s_context=m_pimpl->context;
|
||||
m_pimpl->s_xcontext=m_pimpl->xcontext;
|
||||
m_pimpl->s_contextid=m_pimpl->contextid;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Context::pop(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int Context::getContextId(void) {
|
||||
return PIMPL::s_contextid;
|
||||
}
|
||||
|
||||
/* returns the last GemWindow that called makeCurrent()
|
||||
* LATER: what to do if this has been invalidated (e.g. because the context was destroyed) ?
|
||||
*/
|
||||
GLEWContext*Context::getGlewContext(void) {
|
||||
return PIMPL::s_context;
|
||||
}
|
||||
GemGlewXContext*Context::getGlewXContext(void) {
|
||||
return PIMPL::s_xcontext;
|
||||
}
|
||||
|
||||
GLEWContext*glewGetContext(void) {return gem::Context::getGlewContext();}
|
||||
GemGlewXContext*wglewGetContext(void){return gem::Context::getGlewXContext();}
|
||||
GemGlewXContext*glxewGetContext(void){return gem::Context::getGlewXContext();}
|
||||
|
||||
57
Gem/src/Base/GemContext.h
Normal file
57
Gem/src/Base/GemContext.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
a rendering context
|
||||
|
||||
Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMCONTEXT_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMCONTEXT_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
|
||||
# if defined _WIN32
|
||||
typedef struct WGLEWContextStruct WGLEWContext;
|
||||
# define GemGlewXContext WGLEWContext
|
||||
# elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
typedef struct GLXEWContextStruct GLXEWContext;
|
||||
# define GemGlewXContext GLXEWContext
|
||||
# else
|
||||
# define GemGlewXContext void
|
||||
# endif
|
||||
|
||||
typedef struct GLEWContextStruct GLEWContext;
|
||||
|
||||
namespace gem {
|
||||
class GEM_EXTERN Context {
|
||||
private:
|
||||
class PIMPL;
|
||||
PIMPL*m_pimpl;
|
||||
|
||||
public:
|
||||
Context(void);
|
||||
Context(const Context&);
|
||||
virtual ~Context(void);
|
||||
|
||||
Context&operator=(const Context&);
|
||||
|
||||
// make context current
|
||||
bool push(void);
|
||||
|
||||
// make context uncurrent
|
||||
bool pop(void);
|
||||
|
||||
public:
|
||||
static unsigned int getContextId(void);
|
||||
static GLEWContext*getGlewContext(void);
|
||||
static GemGlewXContext*getGlewXContext(void);
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
#endif // for header file
|
||||
23
Gem/src/Base/GemGLBase.h
Normal file
23
Gem/src/Base/GemGLBase.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* ------------------------------------------------------------------
|
||||
* GEM - Graphics Environment for Multimedia
|
||||
*
|
||||
* Copyright (c) 2008 zmoelnig@iem.at
|
||||
* For information on usage and redistribution, and for a DISCLAIMER
|
||||
* OF ALL WARRANTIES, see the file, "GEM.LICENSE.TERMS"
|
||||
*
|
||||
* this file has been generated...
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMGLBASE_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMGLBASE_H_
|
||||
|
||||
#include "Utils/GLUtil.h"
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
class GEM_EXTERN GemGLBase : public GemBase
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* for header file */
|
||||
96
Gem/src/Base/GemGluObj.cpp
Normal file
96
Gem/src/Base/GemGluObj.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemGluObj.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemGluObj
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemGluObj :: GemGluObj(t_floatarg size, t_floatarg slices, t_floatarg stacks)
|
||||
: GemShape(size),
|
||||
m_numSlices((int)slices),m_numStacks((int)stacks),
|
||||
m_sliceInlet(NULL)
|
||||
{
|
||||
m_drawTypes.clear();
|
||||
m_drawTypes["default"]=GL_DEFAULT_GEM;
|
||||
m_drawTypes["line"]=GL_LINE;
|
||||
m_drawTypes["fill"]=GL_FILL;
|
||||
m_drawTypes["point"]=GL_POINT;
|
||||
m_drawTypes["points"]=GL_POINT;
|
||||
|
||||
m_drawType = (GLenum) GL_FILL;
|
||||
if(m_numSlices<=0)m_numSlices=10;
|
||||
if(m_numStacks<=0)m_numStacks=m_numSlices;
|
||||
|
||||
// the number of slices
|
||||
m_sliceInlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("numslices"));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemGluObj :: ~GemGluObj()
|
||||
{
|
||||
// in case we are deleted while still running
|
||||
inlet_free(m_sliceInlet);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// numSlicesMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemGluObj :: numSlicesMess(int numSlices)
|
||||
{
|
||||
m_numSlices = (numSlices < 2) ? 2 : numSlices;
|
||||
m_numStacks = m_numSlices;
|
||||
setModified();
|
||||
}
|
||||
void GemGluObj :: numSlicesMess(int numSlices, int numStacks)
|
||||
{
|
||||
m_numSlices = (numSlices < 2) ? 2 : numSlices;
|
||||
m_numStacks = (numStacks < 2) ? 2 : numStacks;
|
||||
setModified();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemGluObj :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&GemGluObj::numSlicesMessCallback),
|
||||
gensym("numslices"), A_GIMME, A_NULL);
|
||||
}
|
||||
void GemGluObj :: numSlicesMessCallback(void *data, t_symbol*, int argc, t_atom*argv)
|
||||
{
|
||||
switch(argc){
|
||||
case 1:
|
||||
GetMyClass(data)->numSlicesMess(atom_getint(argv));
|
||||
break;
|
||||
case 2:
|
||||
GetMyClass(data)->numSlicesMess(atom_getint(argv), atom_getint(argv+1));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("only 1 or 2 arguments for \"slices [stacks]\" allowed!");
|
||||
}
|
||||
}
|
||||
92
Gem/src/Base/GemGluObj.h
Normal file
92
Gem/src/Base/GemGluObj.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
A Glu object
|
||||
|
||||
Copyright (c) 1997-2000 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMGLUOBJ_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMGLUOBJ_H_
|
||||
|
||||
// I hate Microsoft...I shouldn't have to do this!
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#ifndef M_PI
|
||||
# define M_PI (3.1415926)
|
||||
#endif
|
||||
|
||||
#include "Base/GemShape.h"
|
||||
|
||||
#ifndef GLU_SILHOUETTE
|
||||
# define GLU_SILHOUETTE 0
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemGluObj
|
||||
|
||||
A Glu object
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Inlet for an int - "in2"
|
||||
|
||||
"in2" - the number of slices in the object
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemGluObj : public GemShape
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemGluObj(t_floatarg size, t_floatarg slices=10.f, t_floatarg stacks=0.f);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemGluObj();
|
||||
|
||||
//////////
|
||||
// The number of slices in the quadric
|
||||
void numSlicesMess(int numSlices);
|
||||
void numSlicesMess(int numSlices, int numStacks);
|
||||
|
||||
//////////
|
||||
// The number of slices
|
||||
int m_numSlices, m_numStacks;
|
||||
|
||||
//////////
|
||||
t_inlet *m_sliceInlet;
|
||||
|
||||
//////////
|
||||
// creation callback
|
||||
static void real_obj_setupCallback(t_class *classPtr)
|
||||
{ GemShape::real_obj_setupCallback(classPtr); GemGluObj::obj_setupCallback(classPtr); }
|
||||
|
||||
private:
|
||||
|
||||
static inline GemGluObj *GetMyClass(void *data) {return((GemGluObj *)((Obj_header *)data)->data);}
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
static void numSlicesMessCallback(void *data, t_symbol*, int, t_atom*);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
78
Gem/src/Base/GemPathBase.cpp
Normal file
78
Gem/src/Base/GemPathBase.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemPathBase.h"
|
||||
#include "Utils/Functions.h"
|
||||
|
||||
// CPPEXTERN_NEW_WITH_GIMME(GemPathBase);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemPathBase :: GemPathBase(int argc, t_atom *argv)
|
||||
: m_numDimens(1), m_array(NULL),
|
||||
m_out1(NULL)
|
||||
{
|
||||
m_out1 = outlet_new(this->x_obj, 0);
|
||||
|
||||
if (argc >= 2)
|
||||
openMess(atom_getsymbol(&argv[1]));
|
||||
if (argc >= 1)
|
||||
{
|
||||
m_numDimens = (int)atom_getfloat(&argv[0]);
|
||||
if (m_numDimens < 1) m_numDimens = 1;
|
||||
if (m_numDimens > 64)
|
||||
{
|
||||
error("too many dimensions, must be below 64");
|
||||
m_numDimens = 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemPathBase :: ~GemPathBase()
|
||||
{
|
||||
outlet_free(m_out1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// openMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPathBase :: openMess(t_symbol *arrayname)
|
||||
{
|
||||
m_array = (t_garray *)pd_findbyclass(arrayname, garray_class);
|
||||
if (!m_array)
|
||||
{
|
||||
error("unable to find array %s", arrayname->s_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPathBase :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG1(classPtr, "open", openMess, t_symbol*);
|
||||
CPPEXTERN_MSG1(classPtr, "float", floatMess, t_float);
|
||||
}
|
||||
67
Gem/src/Base/GemPathBase.h
Normal file
67
Gem/src/Base/GemPathBase.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Base class for paths
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMPATHBASE_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMPATHBASE_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemPathBase
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemPathBase : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(GemPathBase, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemPathBase(int argc, t_atom *argv);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemPathBase();
|
||||
|
||||
//////////
|
||||
// When an open is received
|
||||
virtual void openMess(t_symbol *arrayname);
|
||||
|
||||
//////////
|
||||
// When a float val is received
|
||||
virtual void floatMess(t_float val) = 0;
|
||||
|
||||
//////////
|
||||
// The number of dimensions
|
||||
int m_numDimens;
|
||||
|
||||
//////////
|
||||
// The array
|
||||
t_garray *m_array;
|
||||
|
||||
//////////
|
||||
// The outlet
|
||||
t_outlet *m_out1;
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
232
Gem/src/Base/GemPixDualObj.cpp
Normal file
232
Gem/src/Base/GemPixDualObj.cpp
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2002 James Tittle & Chris Clepper
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemPixDualObj.h"
|
||||
|
||||
#include "Gem/Cache.h"
|
||||
#include "Gem/State.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemPixDualObj
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemPixDualObj :: GemPixDualObj()
|
||||
: m_cacheRight(NULL),
|
||||
m_pixRight(NULL),// was dsiabled by DH 8/5/02
|
||||
m_pixRightValid(-1),
|
||||
org_pixRightValid(-1),
|
||||
m_inlet(NULL)
|
||||
{
|
||||
m_inlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("gem_state"), gensym("gem_right"));
|
||||
memset(&m_pixRight, 0, sizeof(m_pixRight));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemPixDualObj :: ~GemPixDualObj()
|
||||
{
|
||||
inlet_free(m_inlet);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processImage
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixDualObj :: render(GemState *state)
|
||||
{
|
||||
GemPixObj::render(state);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processImage
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#define PROCESS_DUALIMAGE_SIMD(CS) \
|
||||
switch(m_simd){ \
|
||||
case (GEM_SIMD_MMX): \
|
||||
process##CS ##_MMX(image, m_pixRight->image); \
|
||||
break; \
|
||||
case(GEM_SIMD_SSE2): \
|
||||
process##CS ##_SSE2(image, m_pixRight->image); \
|
||||
break; \
|
||||
case(GEM_SIMD_ALTIVEC): \
|
||||
process##CS ##_Altivec(image, m_pixRight->image); \
|
||||
break; \
|
||||
default: \
|
||||
process##CS ##_##CS(image, m_pixRight->image); \
|
||||
}
|
||||
|
||||
#define PROCESS_DUALIMAGE(CS1, CS2) \
|
||||
process##CS1 ##_##CS2 (image, m_pixRight->image);
|
||||
|
||||
#define PROCESS_COLORSPACE(FUN_RGBA, FUN_YUV, FUN_GRAY) \
|
||||
switch (m_pixRight->image.format) { \
|
||||
case GL_RGBA: case GL_BGRA_EXT: \
|
||||
found=true; FUN_RGBA; break; \
|
||||
case GL_LUMINANCE: \
|
||||
found=true; FUN_GRAY; break; \
|
||||
case GL_YCBCR_422_GEM: \
|
||||
found=true; FUN_YUV ; break; \
|
||||
default:break;}
|
||||
|
||||
void GemPixDualObj :: processImage(imageStruct &image)
|
||||
{
|
||||
if (!m_cacheRight || m_cacheRight->m_magic!=GEMCACHE_MAGIC){
|
||||
m_cacheRight=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
//if (!m_cacheRight || !&image || !&m_pixRight || !&m_pixRight->image) return;
|
||||
if (!m_pixRightValid || !&image || !&m_pixRight || !&m_pixRight->image) return;
|
||||
|
||||
if (image.xsize != m_pixRight->image.xsize ||
|
||||
image.ysize != m_pixRight->image.ysize) {
|
||||
error("two images do not have equal dimensions (%dx%d != %dx%d)",
|
||||
image.xsize, image.ysize,
|
||||
m_pixRight->image.xsize, m_pixRight->image.ysize);
|
||||
m_pixRightValid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(image.upsidedown != m_pixRight->image.upsidedown) {
|
||||
image.fixUpDown();
|
||||
m_pixRight->image.fixUpDown();
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
switch (image.format) {
|
||||
case GL_RGBA:
|
||||
case GL_BGRA_EXT:
|
||||
PROCESS_COLORSPACE(PROCESS_DUALIMAGE_SIMD(RGBA),
|
||||
PROCESS_DUALIMAGE(RGBA, YUV),
|
||||
PROCESS_DUALIMAGE(RGBA, Gray));
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
PROCESS_COLORSPACE(PROCESS_DUALIMAGE(Gray, RGBA),
|
||||
PROCESS_DUALIMAGE(Gray, YUV),
|
||||
PROCESS_DUALIMAGE_SIMD(Gray));
|
||||
break;
|
||||
case GL_YCBCR_422_GEM:
|
||||
PROCESS_COLORSPACE(PROCESS_DUALIMAGE(YUV, RGBA),
|
||||
PROCESS_DUALIMAGE_SIMD(YUV),
|
||||
PROCESS_DUALIMAGE(YUV, Gray));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (!found)processDualImage(image, m_pixRight->image);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// process
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void GemPixDualObj :: processDualImage(imageStruct &left, imageStruct &right){
|
||||
char *lformat, *rformat;
|
||||
switch (left.format) {
|
||||
case GL_RGBA:
|
||||
case GL_BGRA_EXT:
|
||||
lformat =(char*)"RGBA";break;
|
||||
case GL_LUMINANCE:
|
||||
lformat =(char*)"Gray";break;
|
||||
case GL_YCBCR_422_GEM:
|
||||
lformat =(char*)"YUV";break;
|
||||
default:
|
||||
lformat = new char[6];
|
||||
sprintf(lformat,"0x%04X", (unsigned int)left.format);
|
||||
}
|
||||
switch (right.format) {
|
||||
case GL_RGBA:
|
||||
case GL_BGRA_EXT:
|
||||
rformat =(char*)"RGBA";break;
|
||||
case GL_LUMINANCE:
|
||||
rformat =(char*)"Gray";break;
|
||||
case GL_YCBCR_422_GEM:
|
||||
rformat =(char*)"YUV";break;
|
||||
default:
|
||||
rformat = new char[6];
|
||||
sprintf(rformat, "0x%04X", (unsigned int)left.format);
|
||||
}
|
||||
|
||||
error("no method to combine (%s) and (%s)", lformat, rformat);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// postrender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixDualObj :: postrender(GemState *state)
|
||||
{
|
||||
if (org_pixRightValid != m_pixRightValid)setPixModified();
|
||||
|
||||
org_pixRightValid = m_pixRightValid;
|
||||
|
||||
m_pixRightValid = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// stopRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixDualObj :: stopRendering()
|
||||
{
|
||||
m_pixRightValid = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// rightRender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixDualObj :: rightRender(GemState *statePtr)
|
||||
{
|
||||
if (!statePtr || !statePtr->get(GemState::_PIX, m_pixRight) || !m_pixRight) {
|
||||
m_pixRightValid = 0;
|
||||
m_pixRight = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_pixRightValid = 1;
|
||||
if (m_pixRight->newimage)setPixModified(); // force the left arm to create a new image
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixDualObj :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&GemPixDualObj::gem_rightMessCallback),
|
||||
gensym("gem_right"), A_GIMME, A_NULL);
|
||||
}
|
||||
void GemPixDualObj :: gem_rightMessCallback(void *data, t_symbol *s, int argc, t_atom *argv)
|
||||
{
|
||||
if (argc==1 && argv->a_type==A_FLOAT){
|
||||
} else if (argc==2 && argv->a_type==A_POINTER && (argv+1)->a_type==A_POINTER){
|
||||
GetMyClass(data)->m_cacheRight = (GemCache*)argv->a_w.w_gpointer;
|
||||
GetMyClass(data)->rightRender((GemState *)(argv+1)->a_w.w_gpointer);
|
||||
} else GetMyClass(data)->error("wrong righthand arguments....");
|
||||
}
|
||||
190
Gem/src/Base/GemPixDualObj.h
Normal file
190
Gem/src/Base/GemPixDualObj.h
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
An object which accepts two pixes.
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
Copyright (c) 2002 James Tittle & Chris Clepper
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMPIXDUALOBJ_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMPIXDUALOBJ_H_
|
||||
|
||||
#define NEW_DUAL_PIX
|
||||
|
||||
#include "Base/GemPixObj.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemPixDualObj
|
||||
|
||||
An object which accepts two pixes.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Inlet for a gem - "gem_right"
|
||||
|
||||
"gem_right" - The second gem list
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemPixDualObj : public GemPixObj
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemPixDualObj();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemPixDualObj();
|
||||
|
||||
void render(GemState *state);
|
||||
|
||||
//////////
|
||||
// Derived classes should NOT override this!
|
||||
// This makes sure that the images are the same size.
|
||||
// This calls the other process functions based on the input images.
|
||||
virtual void processImage(imageStruct &image);
|
||||
|
||||
#ifndef NEW_DUAL_PIX
|
||||
//////////
|
||||
// The derived class HAS override this.
|
||||
// This is called whenever a new image comes through and
|
||||
// both of the image structs are RGBA
|
||||
virtual void processDualImage(imageStruct &image, imageStruct &right) = 0;
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and both
|
||||
// of the image structs are gray8.
|
||||
// The default behavior is to output an error.
|
||||
virtual void processDualGray(imageStruct &image, imageStruct &right);
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and
|
||||
// the left image is an RGBA while the right is a gray8.
|
||||
// The default behavior is to output an error.
|
||||
virtual void processRightGray(imageStruct &image, imageStruct &right);
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and
|
||||
// the left image is a gray8, the right is an RGBA
|
||||
// The default behavior is to output an error.
|
||||
virtual void processLeftGray(imageStruct &image, imageStruct &right);
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and both
|
||||
// of the image structs are YUV.
|
||||
// The default behavior is to output an error.
|
||||
virtual void processDualYUV(imageStruct &image, imageStruct &right);
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and
|
||||
// the left image is an RGBA while the right is a YUV.
|
||||
// The default behavior is to output an error.
|
||||
virtual void processRightYUV(imageStruct &image, imageStruct &right);
|
||||
|
||||
//////////
|
||||
// The derived class CAN override this.
|
||||
// This is called whenever a new image comes through and
|
||||
// the left image is a YUV, the right is an RGBA
|
||||
// The default behavior is to output an error.
|
||||
virtual void processLeftYUV(imageStruct &image, imageStruct &right);
|
||||
#else
|
||||
//////////
|
||||
// The derived class SHOULD override this, if it provides a method for "all" formats
|
||||
virtual void processDualImage(imageStruct &left, imageStruct &right);
|
||||
// Here come the more specific dual-processors
|
||||
// The derived class SHOULD override these as needed
|
||||
|
||||
/* for simplicity this is done via preprocessor defines:
|
||||
* the functions defined are like :
|
||||
** processRGBA_RGBA(left, right);
|
||||
*/
|
||||
|
||||
#define PROCESS_DUALIMAGE(CS1, CS2) \
|
||||
virtual void process##CS1 ##_##CS2 (imageStruct &left, imageStruct &right){processDualImage(left, right);}
|
||||
PROCESS_DUALIMAGE(RGBA, RGBA);
|
||||
PROCESS_DUALIMAGE(RGBA, Gray);
|
||||
PROCESS_DUALIMAGE(RGBA, YUV );
|
||||
|
||||
PROCESS_DUALIMAGE(Gray, RGBA);
|
||||
PROCESS_DUALIMAGE(Gray, Gray);
|
||||
PROCESS_DUALIMAGE(Gray, YUV );
|
||||
|
||||
PROCESS_DUALIMAGE(YUV, RGBA);
|
||||
PROCESS_DUALIMAGE(YUV, Gray);
|
||||
PROCESS_DUALIMAGE(YUV, YUV );
|
||||
#undef PROCESS_DUALIMAGE
|
||||
|
||||
/* for simplicity this is done via preprocessor defines:
|
||||
* the functions defined are like :
|
||||
** processRGBA_Altivec(left, right);
|
||||
*/
|
||||
#define PROCESS_DUALIMAGE_SIMD(CS1, CS2,_SIMD_EXT) \
|
||||
virtual void process##CS1 ##_##_SIMD_EXT (imageStruct &left, imageStruct &right){ \
|
||||
process##CS1 ##_##CS2 (left, right);}
|
||||
|
||||
PROCESS_DUALIMAGE_SIMD(RGBA, RGBA, MMX);
|
||||
PROCESS_DUALIMAGE_SIMD(RGBA, MMX , SSE2);
|
||||
PROCESS_DUALIMAGE_SIMD(RGBA, RGBA, Altivec);
|
||||
|
||||
PROCESS_DUALIMAGE_SIMD(YUV , YUV , MMX);
|
||||
PROCESS_DUALIMAGE_SIMD(YUV , MMX , SSE2);
|
||||
PROCESS_DUALIMAGE_SIMD(YUV , YUV , Altivec);
|
||||
|
||||
PROCESS_DUALIMAGE_SIMD(Gray, Gray, MMX);
|
||||
PROCESS_DUALIMAGE_SIMD(Gray, MMX , SSE2);
|
||||
PROCESS_DUALIMAGE_SIMD(Gray, Gray, Altivec);
|
||||
#undef PROCESS_DUALIMAGE_SIMD
|
||||
|
||||
#endif
|
||||
//////////
|
||||
virtual void postrender(GemState *);
|
||||
virtual void stopRendering();
|
||||
virtual void rightstopRendering() { ; }
|
||||
virtual void rightRender(GemState *state);
|
||||
virtual void rightPostrender(GemState *) { ; }
|
||||
virtual void rightStoprender() { ; }
|
||||
|
||||
//////////
|
||||
GemCache *m_cacheRight;
|
||||
|
||||
//////////
|
||||
pixBlock *m_pixRight;
|
||||
|
||||
int m_pixRightValid;
|
||||
int org_pixRightValid;
|
||||
|
||||
//////////
|
||||
t_inlet *m_inlet;
|
||||
|
||||
//////////
|
||||
// creation callback
|
||||
static void real_obj_setupCallback(t_class *classPtr)
|
||||
{ GemPixObj::real_obj_setupCallback(classPtr); GemPixDualObj::obj_setupCallback(classPtr); }
|
||||
|
||||
private:
|
||||
|
||||
static inline GemPixDualObj *GetMyClass(void *data) {return((GemPixDualObj *)((Obj_header *)data)->data);}
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
static void gem_rightMessCallback(void *x, t_symbol *s, int argc, t_atom *argv);
|
||||
};
|
||||
#endif // for header file
|
||||
220
Gem/src/Base/GemPixObj.cpp
Normal file
220
Gem/src/Base/GemPixObj.cpp
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemPixObj.h"
|
||||
#include "Gem/Cache.h"
|
||||
#include "Gem/State.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemPixObj
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemPixObj :: GemPixObj() :
|
||||
cachedPixBlock(pixBlock()),
|
||||
orgPixBlock(NULL), m_processOnOff(1),
|
||||
m_simd(GemSIMD::getCPU())
|
||||
{
|
||||
cachedPixBlock.newimage=0;
|
||||
cachedPixBlock.newfilm =0;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setPixModified
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: setPixModified()
|
||||
{
|
||||
if(m_cache && m_cache->m_magic!=GEMCACHE_MAGIC)m_cache=NULL;
|
||||
if(m_cache)m_cache->resendImage = 1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// render
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: render(GemState *state){
|
||||
// We save all information of our image, so the pix-processors can do what they want:
|
||||
// change formats, sizes, databuffer, whatever
|
||||
// the data is restored in the <postrender> call,
|
||||
// so that the objects can rely on their (buffered) images
|
||||
pixBlock*image=NULL;
|
||||
if (!state || !state->get(GemState::_PIX, image))return;
|
||||
if(!image ||
|
||||
!&image->image) return;
|
||||
cachedPixBlock.newimage=image->newimage;
|
||||
if (!image->newimage) {
|
||||
image = &cachedPixBlock;
|
||||
} else {
|
||||
orgPixBlock = image;
|
||||
cachedPixBlock.newimage = image->newimage;
|
||||
cachedPixBlock.newfilm = image->newfilm; //added for newfilm copy from cache cgc 6-21-03
|
||||
image->image.copy2ImageStruct(&cachedPixBlock.image);
|
||||
image = &cachedPixBlock;
|
||||
if (m_processOnOff){
|
||||
switch(image->image.format){
|
||||
case GL_RGBA:
|
||||
case GL_BGRA_EXT:
|
||||
switch(m_simd){
|
||||
case(GEM_SIMD_MMX):
|
||||
processRGBAMMX(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_SSE2):
|
||||
processRGBASSE2(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_ALTIVEC):
|
||||
processRGBAAltivec(image->image);
|
||||
break;
|
||||
default:
|
||||
processRGBAImage(image->image);
|
||||
}
|
||||
break;
|
||||
case GL_RGB:
|
||||
case GL_BGR_EXT:
|
||||
processRGBImage(image->image);
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
switch(m_simd){
|
||||
case(GEM_SIMD_MMX):
|
||||
processGrayMMX(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_SSE2):
|
||||
processGraySSE2(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_ALTIVEC):
|
||||
processGrayAltivec(image->image);
|
||||
break;
|
||||
default:
|
||||
processGrayImage(image->image);
|
||||
}
|
||||
break;
|
||||
case GL_YCBCR_422_GEM:
|
||||
switch(m_simd){
|
||||
case(GEM_SIMD_MMX):
|
||||
processYUVMMX(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_SSE2):
|
||||
processYUVSSE2(image->image);
|
||||
break;
|
||||
case(GEM_SIMD_ALTIVEC):
|
||||
processYUVAltivec(image->image);
|
||||
break;
|
||||
default:
|
||||
processYUVImage(image->image);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
processImage(image->image);
|
||||
}
|
||||
}
|
||||
}
|
||||
state->set(GemState::_PIX, image);
|
||||
}
|
||||
|
||||
//////////
|
||||
// get the original state back
|
||||
void GemPixObj :: postrender(GemState *state){
|
||||
state->set(GemState::_PIX, orgPixBlock);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processImage
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: processImage(imageStruct &image)
|
||||
{
|
||||
switch (image.format) {
|
||||
case GL_RGBA:
|
||||
case GL_BGRA_EXT:
|
||||
error("cannot handle RGBA image");
|
||||
break;
|
||||
case GL_RGB:
|
||||
case GL_BGR_EXT:
|
||||
error("cannot handle RGB image");
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
error("cannot handle Grey image");
|
||||
break;
|
||||
case GL_YCBCR_422_GEM:
|
||||
error("cannot handle YUV image");
|
||||
break;
|
||||
default:
|
||||
error("cannot handle this format (%x) !", image.format);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processImage (typed)
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: processRGBAImage(imageStruct &image)
|
||||
{ processImage(image); }
|
||||
void GemPixObj :: processRGBImage(imageStruct &image)
|
||||
{ processImage(image); }
|
||||
void GemPixObj :: processGrayImage(imageStruct &image)
|
||||
{ processImage(image); }
|
||||
void GemPixObj :: processYUVImage(imageStruct &image)
|
||||
{ processImage(image); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processImage - SIMD (typed)
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: processRGBAMMX (imageStruct &image)
|
||||
{ processRGBAImage(image); }
|
||||
void GemPixObj :: processGrayMMX (imageStruct &image)
|
||||
{ processGrayImage(image); }
|
||||
void GemPixObj :: processYUVMMX (imageStruct &image)
|
||||
{ processYUVImage(image); }
|
||||
void GemPixObj :: processRGBASSE2 (imageStruct &image)
|
||||
{ processRGBAMMX(image); }
|
||||
void GemPixObj :: processGraySSE2 (imageStruct &image)
|
||||
{ processGrayMMX(image); }
|
||||
void GemPixObj :: processYUVSSE2 (imageStruct &image)
|
||||
{ processYUVMMX(image); }
|
||||
void GemPixObj :: processRGBAAltivec(imageStruct &image)
|
||||
{ processRGBAImage(image); }
|
||||
void GemPixObj :: processGrayAltivec(imageStruct &image)
|
||||
{ processGrayImage(image); }
|
||||
void GemPixObj :: processYUVAltivec (imageStruct &image)
|
||||
{ processYUVImage(image); }
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// processOnOff
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: processOnOff(int on)
|
||||
{
|
||||
m_processOnOff = on;
|
||||
setPixModified();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member functions
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemPixObj :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG1(classPtr, "float", processOnOff, int);
|
||||
CPPEXTERN_MSG1(classPtr, "simd" , SIMD , int);
|
||||
}
|
||||
void GemPixObj :: SIMD(int n)
|
||||
{
|
||||
m_simd=GemSIMD::requestCPU(n);
|
||||
}
|
||||
143
Gem/src/Base/GemPixObj.h
Normal file
143
Gem/src/Base/GemPixObj.h
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Base class for pix class gem objects
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMPIXOBJ_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMPIXOBJ_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
#include "Gem/Image.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "math.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemPixObj
|
||||
|
||||
Base class for pix class gem objects
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemPixObj : public GemBase
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemPixObj();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemPixObj() { }
|
||||
|
||||
//////////
|
||||
// The derived class should override this if it provides
|
||||
// processing independent of the image.format
|
||||
// This is called whenever a new image comes through.
|
||||
// The default is to output an error
|
||||
virtual void processImage(imageStruct &image);
|
||||
|
||||
//////////
|
||||
// The derived class should override this.
|
||||
// This is called whenever a new RGB image comes through.
|
||||
// The default is to call processImage().
|
||||
virtual void processRGBImage(imageStruct &image);
|
||||
|
||||
//////////
|
||||
// The derived class should override this.
|
||||
// This is called whenever a new RGBA image comes through.
|
||||
// The default is to call processImage().
|
||||
virtual void processRGBAImage(imageStruct &image);
|
||||
// SIMD-optimized functions: by default the non-optimized function is called
|
||||
virtual void processRGBAMMX(imageStruct &image);
|
||||
virtual void processRGBASSE2(imageStruct &image);
|
||||
virtual void processRGBAAltivec(imageStruct &image);
|
||||
|
||||
//////////
|
||||
// The derived class should override this.
|
||||
// This is called whenever a new gray8 image comes through.
|
||||
// The default is to call processImage().
|
||||
virtual void processGrayImage(imageStruct &image);
|
||||
// SIMD-optimized functions: by default the non-optimized function is called
|
||||
virtual void processGrayMMX(imageStruct &image);
|
||||
virtual void processGraySSE2(imageStruct &image);
|
||||
virtual void processGrayAltivec(imageStruct &image);
|
||||
|
||||
//////////
|
||||
// The derived class should override this.
|
||||
// This is called whenever a new YUV422 image comes through.
|
||||
// The default is to call processImage().
|
||||
virtual void processYUVImage(imageStruct &image);
|
||||
// SIMD-optimized functions: by default the non-optimized function is called
|
||||
virtual void processYUVMMX(imageStruct &image);
|
||||
virtual void processYUVSSE2(imageStruct &image);
|
||||
virtual void processYUVAltivec(imageStruct &image);
|
||||
|
||||
//////////
|
||||
// If the derived class needs the image resent.
|
||||
// This sets the dirty bit on the pixBlock.
|
||||
void setPixModified();
|
||||
|
||||
//////////
|
||||
// Turn on/off processing
|
||||
void processOnOff(int on);
|
||||
|
||||
//////////
|
||||
// the pixBlock-cache
|
||||
pixBlock cachedPixBlock;
|
||||
pixBlock *orgPixBlock;
|
||||
|
||||
//////////
|
||||
int m_processOnOff;
|
||||
int m_simd;
|
||||
|
||||
//////////
|
||||
// creation callback
|
||||
static void real_obj_setupCallback(t_class *classPtr) {
|
||||
GemBase::real_obj_setupCallback(classPtr);
|
||||
GemPixObj::obj_setupCallback(classPtr);
|
||||
}
|
||||
|
||||
//////////
|
||||
// The derived class should NOT override this unless they have some
|
||||
// very special behavior.
|
||||
// Do the rendering, which calls processImage or processGrayImage, etc...
|
||||
// save the image-information
|
||||
virtual void render(GemState *state);
|
||||
// turn the pointer back to the old data after rendering
|
||||
virtual void postrender(GemState *state);
|
||||
|
||||
void startRendering(void) {
|
||||
//post("start rendering");
|
||||
setPixModified();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static inline GemPixObj *GetMyClass(void *data) {return((GemPixObj *)((Obj_header *)data)->data);}
|
||||
|
||||
//////////
|
||||
// static member functions
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
|
||||
protected:
|
||||
virtual void SIMD(int);
|
||||
};
|
||||
|
||||
|
||||
#endif // for header file
|
||||
261
Gem/src/Base/GemShape.cpp
Normal file
261
Gem/src/Base/GemShape.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemShape.h"
|
||||
#include "Gem/State.h"
|
||||
#include <algorithm>
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// a generic GemShape
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
static char mytolower(char in){
|
||||
if(in<='Z' && in>='A')
|
||||
return in-('Z'-'z');
|
||||
return in;
|
||||
}
|
||||
|
||||
static void initialize_drawtypes(std::map<std::string, GLenum>&drawtypes) {
|
||||
drawtypes["default"]=GL_DEFAULT_GEM;
|
||||
|
||||
drawtypes["point"]=GL_POINTS;
|
||||
drawtypes["points"]=GL_POINTS;
|
||||
|
||||
/* how about GL_LINE ?? */
|
||||
drawtypes["line"]=GL_LINE_LOOP;
|
||||
drawtypes["lineloop"]=GL_LINE_LOOP;
|
||||
drawtypes["lines"]=GL_LINES;
|
||||
drawtypes["linestrip"]=GL_LINE_STRIP;
|
||||
|
||||
drawtypes["tri"]=GL_TRIANGLES;
|
||||
drawtypes["triangle"]=GL_TRIANGLES;
|
||||
drawtypes["tristrip"]=GL_TRIANGLE_STRIP;
|
||||
drawtypes["trifan"]=GL_TRIANGLE_FAN;
|
||||
|
||||
drawtypes["quad"]=GL_QUADS;
|
||||
drawtypes["quads"]=GL_QUADS;
|
||||
drawtypes["quadstrip"]=GL_QUAD_STRIP;
|
||||
|
||||
drawtypes["strip"]=GL_TRIANGLE_STRIP;
|
||||
drawtypes["fill"]=GL_POLYGON;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GemShape :: GemShape(t_floatarg size)
|
||||
: m_linewidth(1.0f), m_size((float)size), m_drawType(GL_DEFAULT_GEM), m_blend(0),
|
||||
m_inlet(NULL),
|
||||
m_texType(0), m_texNum(0),
|
||||
m_texCoords(NULL),
|
||||
m_lighting(false)
|
||||
{
|
||||
if (m_size == 0.f)m_size = 1.f;
|
||||
|
||||
// the size inlet
|
||||
m_inlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, &s_float, gensym("ft1"));
|
||||
|
||||
initialize_drawtypes(m_drawTypes);
|
||||
}
|
||||
GemShape :: GemShape()
|
||||
: m_linewidth(1.0f), m_size(1.0f), m_drawType(GL_DEFAULT_GEM), m_blend(0),
|
||||
m_inlet(NULL),
|
||||
m_texType(0), m_texNum(0),
|
||||
m_texCoords(NULL),
|
||||
m_lighting(false)
|
||||
{
|
||||
// no size inlet
|
||||
initialize_drawtypes(m_drawTypes);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemShape :: ~GemShape()
|
||||
{
|
||||
if(m_inlet)inlet_free(m_inlet);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// SetVertex
|
||||
// set up the texture-coordinates
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: SetVertex(GemState* state,float x, float y, float z, float tx, float ty,int curCoord)
|
||||
{
|
||||
int i;
|
||||
|
||||
TexCoord*texcoords=NULL;
|
||||
int numCoords = 0;
|
||||
int numUnits = 0;
|
||||
|
||||
state->get(GemState::_GL_TEX_NUMCOORDS, numCoords);
|
||||
state->get(GemState::_GL_TEX_UNITS, numUnits);
|
||||
|
||||
|
||||
if (numCoords) {
|
||||
tx=state->texCoordX(curCoord);
|
||||
ty=state->texCoordY(curCoord);
|
||||
}
|
||||
|
||||
if (numUnits) {
|
||||
for( i=0; i<numUnits; i++) {
|
||||
glMultiTexCoord2fARB(GL_TEXTURE0+i, tx, ty);
|
||||
}
|
||||
} else { // no multitexturing!
|
||||
glTexCoord2f(tx, ty);
|
||||
}
|
||||
glVertex3f( x, y, z );
|
||||
}
|
||||
|
||||
void GemShape :: SetVertex(GemState* state,float x, float y, float z,
|
||||
float s, float t, float r, float q,
|
||||
int curCoord)
|
||||
{
|
||||
int i;
|
||||
int numCoords = 0;
|
||||
int numUnits = 0;
|
||||
|
||||
state->get(GemState::_GL_TEX_NUMCOORDS, numCoords);
|
||||
state->get(GemState::_GL_TEX_UNITS, numUnits);
|
||||
|
||||
|
||||
|
||||
if (numCoords) {
|
||||
s*=state->texCoordX(curCoord);
|
||||
t*=state->texCoordY(curCoord);
|
||||
}
|
||||
|
||||
if (numUnits) {
|
||||
for( i=0; i<numUnits; i++)
|
||||
glMultiTexCoord4fARB(GL_TEXTURE0+i, s, t, r, q);
|
||||
} else { // no multitexturing!
|
||||
glTexCoord4f(s, t, r, q);
|
||||
}
|
||||
|
||||
glVertex3f( x, y, z );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// linewidthMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: linewidthMess(float linewidth)
|
||||
{
|
||||
m_linewidth = (linewidth < 0.0f) ? 0.0f : linewidth;
|
||||
setModified();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// sizeMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: sizeMess(float size)
|
||||
{
|
||||
m_size = size;
|
||||
setModified();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// typeMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: typeMess(t_symbol *type)
|
||||
{
|
||||
if(0==m_drawTypes.size()) {
|
||||
error("unable to change drawstyle");
|
||||
}
|
||||
|
||||
std::string name=type->s_name;
|
||||
std::transform(name.begin(), name.end(), name.begin(), mytolower);
|
||||
|
||||
std::map<std::string, GLenum>::iterator it=m_drawTypes.find(name);
|
||||
if(m_drawTypes.end() == it) {
|
||||
error ("unknown draw style '%s'... possible values are:", name.c_str());
|
||||
it=m_drawTypes.begin();
|
||||
while(m_drawTypes.end() != it) {
|
||||
error("\t %s", it->first.c_str());
|
||||
it++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_drawType=it->second;
|
||||
setModified();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// blendMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: blendMess(float blend)
|
||||
{
|
||||
m_blend = (blend>0);
|
||||
setModified();
|
||||
}
|
||||
|
||||
void GemShape :: render(GemState *state)
|
||||
{
|
||||
if (m_drawType == GL_LINE_LOOP || m_drawType == GL_LINE_STRIP || m_drawType == GL_LINES)
|
||||
glLineWidth(m_linewidth);
|
||||
|
||||
if (m_blend) {
|
||||
glEnable(GL_POLYGON_SMOOTH);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
glHint(GL_POLYGON_SMOOTH_HINT,GL_DONT_CARE);
|
||||
}
|
||||
|
||||
m_texType=0;
|
||||
m_texNum =0;
|
||||
m_texCoords=NULL;
|
||||
m_lighting=false;
|
||||
|
||||
state->get(GemState::_GL_TEX_COORDS, m_texCoords);
|
||||
state->get(GemState::_GL_TEX_TYPE, m_texType);
|
||||
state->get(GemState::_GL_TEX_NUMCOORDS, m_texNum);
|
||||
state->get(GemState::_GL_LIGHTING, m_lighting);
|
||||
|
||||
renderShape(state);
|
||||
|
||||
// LATER try to restore the original state
|
||||
if (m_blend) {
|
||||
glDisable(GL_POLYGON_SMOOTH);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (m_drawType == GL_LINE_LOOP || m_drawType == GL_LINE_STRIP || m_drawType == GL_LINES)
|
||||
glLineWidth(1.0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member functions
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemShape :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG1(classPtr, "width", linewidthMess, float);
|
||||
CPPEXTERN_MSG1(classPtr, "draw", typeMess, t_symbol*);
|
||||
CPPEXTERN_MSG1(classPtr, "blend", blendMess, float);
|
||||
CPPEXTERN_MSG1(classPtr, "ft1", sizeMess, float);
|
||||
}
|
||||
141
Gem/src/Base/GemShape.h
Normal file
141
Gem/src/Base/GemShape.h
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Base class for shapes
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMSHAPE_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMSHAPE_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
#include <map>
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemShape
|
||||
|
||||
Base class for shapes
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Inlet for a float - "ft1"
|
||||
|
||||
"ft1" - the size of the shape
|
||||
"draw" - the drawing style
|
||||
"width" - the line width when drawing with lines
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class TexCoord;
|
||||
class GEM_EXTERN GemShape : public GemBase
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
// [in] size - A size of 0. means to just use the default (ie, 1.)
|
||||
GemShape(t_floatarg size);
|
||||
GemShape();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemShape();
|
||||
|
||||
//-----------------------------------
|
||||
// GROUP: Access functions
|
||||
//-----------------------------------
|
||||
|
||||
//////////
|
||||
// The width of the lines in line draw mode
|
||||
void linewidthMess(float linewidth);
|
||||
|
||||
//////////
|
||||
// The size of the object
|
||||
void sizeMess(float size);
|
||||
|
||||
//////////
|
||||
// How the object should be drawn
|
||||
virtual void typeMess(t_symbol *type);
|
||||
|
||||
//-----------------------------------
|
||||
// GROUP: Utility functions
|
||||
//-----------------------------------
|
||||
|
||||
void SetVertex(GemState* state,float x, float y, float z,
|
||||
float tx, float ty,
|
||||
int curCoord);
|
||||
|
||||
void SetVertex(GemState* state,float x, float y, float z,
|
||||
float s, float t, float r, float q,
|
||||
int curCoord);
|
||||
|
||||
//-----------------------------------
|
||||
// GROUP: Member variables
|
||||
//-----------------------------------
|
||||
|
||||
//////////
|
||||
// The line width for GL_LINE mode
|
||||
GLfloat m_linewidth;
|
||||
|
||||
//////////
|
||||
// The size of the object
|
||||
GLfloat m_size;
|
||||
|
||||
//////////
|
||||
// The drawing style (GL_LINE, GL_POLYGON, etc)
|
||||
GLenum m_drawType;
|
||||
|
||||
//////////
|
||||
// do we want blending?
|
||||
GLboolean m_blend;
|
||||
void blendMess(float blend);
|
||||
|
||||
|
||||
////////
|
||||
// override this memberfunction to automatically enable softblended rendering,...
|
||||
virtual void renderShape(GemState *state) {;}
|
||||
|
||||
// OR
|
||||
// override this memberfunction if you don't want softblending
|
||||
virtual void render(GemState *state);
|
||||
|
||||
|
||||
//////////
|
||||
// The size inlet
|
||||
t_inlet *m_inlet;
|
||||
|
||||
//-----------------------------------
|
||||
// GROUP: Setup functions
|
||||
//-----------------------------------
|
||||
|
||||
//////////
|
||||
// creation callback
|
||||
static void real_obj_setupCallback(t_class *classPtr)
|
||||
{ GemBase::real_obj_setupCallback(classPtr); GemShape::obj_setupCallback(classPtr); }
|
||||
|
||||
private:
|
||||
|
||||
static inline GemShape *GetMyClass(void *data) {return((GemShape *)((Obj_header *)data)->data);}
|
||||
|
||||
//////////
|
||||
// static member functions
|
||||
static void obj_setupCallback(t_class *classPtr);
|
||||
|
||||
protected:
|
||||
int m_texType, m_texNum;
|
||||
TexCoord*m_texCoords;
|
||||
bool m_lighting;
|
||||
|
||||
std::map<std::string, GLenum>m_drawTypes;
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
48
Gem/src/Base/GemVertex.cpp
Normal file
48
Gem/src/Base/GemVertex.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "GemVertex.h"
|
||||
#include "Gem/Cache.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemVertex
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemVertex :: GemVertex()
|
||||
{}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemVertex :: ~GemVertex()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setModified
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void GemVertex :: setModified()
|
||||
{
|
||||
GemBase::setModified();
|
||||
if(m_cache)m_cache->vertexDirty = 1;
|
||||
}
|
||||
37
Gem/src/Base/GemVertex.h
Normal file
37
Gem/src/Base/GemVertex.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
include file for VertexArrays
|
||||
|
||||
Copyright (c) 2004-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMVERTEX_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMVERTEX_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
class GEM_EXTERN GemVertex : public GemBase {
|
||||
protected:
|
||||
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemVertex();
|
||||
|
||||
~GemVertex();
|
||||
|
||||
//////////
|
||||
// If anything in the object has changed
|
||||
// especially, if the vertex-array has changed
|
||||
virtual void setModified();
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE__GEM_BASE_GEMVERTEX_H_ */
|
||||
228
Gem/src/Base/GemWinCreate.h
Normal file
228
Gem/src/Base/GemWinCreate.h
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
/*-----------------------------------------------------------------
|
||||
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
create a window
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMWINCREATE_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMWINCREATE_H_
|
||||
#include "Gem/GemConfig.h"
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
#if defined _WIN32
|
||||
# include <windows.h>
|
||||
#elif defined __APPLE__
|
||||
# import <AGL/agl.h>
|
||||
#elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
# ifdef HAVE_LIBXXF86VM
|
||||
# include <X11/extensions/xf86vmode.h>
|
||||
# endif
|
||||
#else
|
||||
# error Define OS specific window creation
|
||||
#endif
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
// I hate Microsoft...I shouldn't have to do this!
|
||||
#ifdef _WIN32
|
||||
# pragma warning( disable : 4244 )
|
||||
# pragma warning( disable : 4305 )
|
||||
# pragma warning( disable : 4091 )
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
WindowInfo
|
||||
|
||||
All of the relavent information about an OpenGL window
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN WindowInfo
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
WindowInfo() :
|
||||
fs(0),
|
||||
#if defined _WIN32
|
||||
win(NULL), dc(NULL), context(NULL),
|
||||
#elif defined __APPLE__
|
||||
pWind(NULL), context(NULL), offscreen(NULL), pixelSize(32),
|
||||
pixMap(NULL), rowBytes(0), baseAddr(NULL),
|
||||
#elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
dpy(NULL), win(0), screen(0), cmap(0), context(NULL), delete_atom(0), have_border(false),
|
||||
#else
|
||||
#endif
|
||||
have_constContext(0)
|
||||
{}
|
||||
int fs; // FullScreen
|
||||
|
||||
#if defined _WIN32
|
||||
|
||||
HWND win; // Window handle
|
||||
HDC dc; // Device context handle
|
||||
HGLRC context; // OpenGL context
|
||||
|
||||
#elif defined __APPLE__
|
||||
|
||||
WindowPtr pWind; // GEM window reference for gemwin
|
||||
AGLContext context; // OpenGL context
|
||||
GWorldPtr offscreen; // Macintosh offscreen buffer
|
||||
long pixelSize; //
|
||||
Rect r; //
|
||||
PixMapHandle pixMap; // PixMap Handle
|
||||
long rowBytes; //
|
||||
void *baseAddr; //
|
||||
short fontList; // Font
|
||||
|
||||
#elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
|
||||
Display *dpy; // X Display
|
||||
Window win; // X Window
|
||||
int screen; // X Screen
|
||||
Colormap cmap; // X color map
|
||||
GLXContext context; // OpenGL context
|
||||
Atom delete_atom;
|
||||
|
||||
bool have_border;
|
||||
|
||||
# ifdef HAVE_LIBXXF86VM
|
||||
XF86VidModeModeInfo deskMode; // originale ModeLine of the Desktop
|
||||
# endif
|
||||
|
||||
|
||||
#else
|
||||
# error Define OS specific window data
|
||||
#endif
|
||||
int have_constContext; // 1 if we have a constant context
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
WindowHints
|
||||
|
||||
Hints for window creation
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN WindowHints
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Should the window be realized
|
||||
int actuallyDisplay;
|
||||
|
||||
//////////
|
||||
// Single or double buffered
|
||||
int buffer;
|
||||
|
||||
//////////
|
||||
// The width/x of the window
|
||||
int width;
|
||||
//////////
|
||||
// The height/y of the window
|
||||
int height;
|
||||
|
||||
//////////
|
||||
// the real width/height of the window (set by createGemWindow())
|
||||
int real_w, real_h;
|
||||
|
||||
//////////
|
||||
// The offset/x of the window (likely tobe overridden by the window-manager)
|
||||
int x_offset;
|
||||
//////////
|
||||
// The offset/y of the window (likely tobe overridden by the window-manager)
|
||||
int y_offset;
|
||||
|
||||
//////////
|
||||
// Should we do fullscreen ?
|
||||
int fullscreen;
|
||||
|
||||
//////////
|
||||
// Is there a second screen ?
|
||||
int secondscreen;
|
||||
|
||||
//////////
|
||||
// Should there be a window border?
|
||||
int border;
|
||||
|
||||
//////////
|
||||
// mode for full-screen antialiasing
|
||||
int fsaa;
|
||||
|
||||
///// if we can use a different display , this has its meaning under X
|
||||
char* display;
|
||||
|
||||
//////////////
|
||||
// display some title....
|
||||
char* title;
|
||||
|
||||
//////////
|
||||
// The GLXcontext to share rendering with
|
||||
#if defined _WIN32
|
||||
HGLRC shared;
|
||||
#elif defined __APPLE__
|
||||
AGLContext shared;
|
||||
#elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
GLXContext shared;
|
||||
#else
|
||||
#error Define OS specific OpenGL context
|
||||
#endif
|
||||
};
|
||||
|
||||
//////////
|
||||
// Create a new window
|
||||
GEM_EXTERN extern int createGemWindow(WindowInfo &info, WindowHints &hints);
|
||||
|
||||
//////////
|
||||
// Destroy a window
|
||||
GEM_EXTERN extern void destroyGemWindow(WindowInfo &info);
|
||||
|
||||
//////////
|
||||
// Set the cursor
|
||||
GEM_EXTERN extern int cursorGemWindow(WindowInfo &info, int state);
|
||||
|
||||
//////////
|
||||
// Set the topmost position
|
||||
GEM_EXTERN extern int topmostGemWindow(WindowInfo &info, int state);
|
||||
|
||||
//////////
|
||||
// swap the buffers (get's called in double-buffered mode)
|
||||
GEM_EXTERN extern void gemWinSwapBuffers(WindowInfo &nfo);
|
||||
/////////
|
||||
// reestablish a context
|
||||
GEM_EXTERN extern void gemWinMakeCurrent(WindowInfo &nfo);
|
||||
|
||||
/////////
|
||||
// init OS-specific stuff
|
||||
GEM_EXTERN extern bool initGemWin(void);
|
||||
|
||||
/////////
|
||||
// prepare a WindowInfo for context-sharing
|
||||
GEM_EXTERN void initWin_sharedContext(WindowInfo &info, WindowHints &hints);
|
||||
|
||||
|
||||
|
||||
/////////
|
||||
//
|
||||
GEM_EXTERN extern void dispatchGemWindowMessages(WindowInfo &nfo);
|
||||
|
||||
|
||||
|
||||
#endif // for header file
|
||||
1649
Gem/src/Base/GemWinCreateMac.cpp
Normal file
1649
Gem/src/Base/GemWinCreateMac.cpp
Normal file
File diff suppressed because it is too large
Load diff
423
Gem/src/Base/GemWinCreateNT.cpp
Normal file
423
Gem/src/Base/GemWinCreateNT.cpp
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#include "Gem/GemConfig.h"
|
||||
#ifdef _WIN32
|
||||
|
||||
# include "GemWinCreate.h"
|
||||
|
||||
# include <stdlib.h>
|
||||
|
||||
# include "Gem/Event.h"
|
||||
# include "Gem/GemGL.h"
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
GEM_EXTERN void gemAbortRendering();
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// bSetupPixelFormat
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
BOOL bSetupPixelFormat(HDC hdc, const WindowHints &hints)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
// clean out the descriptor
|
||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
if (hints.buffer == 2)
|
||||
pfd.dwFlags = pfd.dwFlags | PFD_DOUBLEBUFFER;
|
||||
pfd.dwLayerMask = PFD_MAIN_PLANE;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cDepthBits = 16;
|
||||
pfd.cAccumBits = 0;
|
||||
pfd.cStencilBits = 8;
|
||||
|
||||
int pixelformat;
|
||||
if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 )
|
||||
{
|
||||
post("GEM: ChoosePixelFormat failed");
|
||||
return(FALSE);
|
||||
}
|
||||
if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE)
|
||||
{
|
||||
post("GEM: SetPixelFormat failed");
|
||||
return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// MainWndProc
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static RECT rcClient;
|
||||
static int ctrlKeyDown = 0;
|
||||
|
||||
// assume that we handle the message
|
||||
long lRet = 0;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
// mouse motion
|
||||
case WM_MOUSEMOVE:
|
||||
triggerMotionEvent(LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// left button up
|
||||
case WM_LBUTTONUP:
|
||||
triggerButtonEvent(0, 0, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// left button down
|
||||
case WM_LBUTTONDOWN:
|
||||
triggerButtonEvent(0, 1, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// middle button up
|
||||
case WM_MBUTTONUP:
|
||||
triggerButtonEvent(1, 0, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// middle button down
|
||||
case WM_MBUTTONDOWN:
|
||||
triggerButtonEvent(1, 1, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// right button up
|
||||
case WM_RBUTTONUP:
|
||||
triggerButtonEvent(2, 0, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
// right button down
|
||||
case WM_RBUTTONDOWN:
|
||||
triggerButtonEvent(2, 1, LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
// keyboard action
|
||||
case WM_KEYUP:
|
||||
if ((int)wParam == VK_CONTROL)
|
||||
ctrlKeyDown = 0;
|
||||
|
||||
triggerKeyboardEvent((char*)&wParam, (int)wParam, 1);
|
||||
break;
|
||||
|
||||
// keyboard action
|
||||
case WM_KEYDOWN:
|
||||
if ((int)wParam == VK_CONTROL)
|
||||
ctrlKeyDown = 1;
|
||||
else if (ctrlKeyDown && (int)wParam == 'R')
|
||||
gemAbortRendering();
|
||||
else
|
||||
triggerKeyboardEvent((char*)&wParam, (int)wParam, 0);
|
||||
break;
|
||||
|
||||
// resize event
|
||||
case WM_SIZE:
|
||||
triggerResizeEvent(LOWORD(lParam), HIWORD(lParam));
|
||||
GetClientRect(hWnd, &rcClient);
|
||||
break;
|
||||
|
||||
// we want to override these messages
|
||||
// and not do anything
|
||||
case WM_DESTROY:
|
||||
case WM_CLOSE:
|
||||
break;
|
||||
case WM_CREATE:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
// pass all unhandled messages to DefWindowProc
|
||||
default:
|
||||
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
return(lRet);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// createGemWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN int createGemWindow(WindowInfo &info, WindowHints &hints)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
|
||||
// Register the frame class
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
if (!hInstance)
|
||||
{
|
||||
error("GEM: Unable to get module instance");
|
||||
return(0);
|
||||
}
|
||||
if (firstTime)
|
||||
{
|
||||
WNDCLASS wndclass;
|
||||
wndclass.style = 0;
|
||||
wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = hInstance;
|
||||
wndclass.hCursor = LoadCursor(NULL, IDC_CROSS);
|
||||
wndclass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
||||
wndclass.hbrBackground = NULL;
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = "GEM";
|
||||
|
||||
if (!RegisterClass(&wndclass) )
|
||||
{
|
||||
error("GEM: Unable to register window class");
|
||||
return(0);
|
||||
}
|
||||
firstTime = 0;
|
||||
}
|
||||
|
||||
DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
|
||||
hints.real_w = hints.width;
|
||||
hints.real_h = hints.height;
|
||||
|
||||
int x = hints.x_offset;
|
||||
int y = hints.y_offset;
|
||||
|
||||
bool fullscreen=(hints.fullscreen!=0);
|
||||
if (fullscreen){
|
||||
DEVMODE dmScreenSettings; // Device Mode
|
||||
|
||||
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dmScreenSettings)){
|
||||
error("GEM: couldn't get screen capabilities!");
|
||||
}
|
||||
int w = dmScreenSettings.dmPelsWidth;
|
||||
int h = dmScreenSettings.dmPelsHeight;
|
||||
|
||||
x=y=0;
|
||||
|
||||
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
|
||||
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
|
||||
dmScreenSettings.dmPelsWidth = hints.width; // Selected Screen Width
|
||||
dmScreenSettings.dmPelsHeight = hints.height; // Selected Screen Height
|
||||
dmScreenSettings.dmBitsPerPel = 32; // Selected Bits Per Pixel
|
||||
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
|
||||
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
|
||||
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {
|
||||
dmScreenSettings.dmPelsWidth = w;
|
||||
dmScreenSettings.dmPelsHeight = h;
|
||||
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {
|
||||
error("GEM: couldn't switch to fullscreen");
|
||||
fullscreen=false;
|
||||
} else {
|
||||
hints.real_h=h;
|
||||
hints.real_w=w;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fullscreen){
|
||||
dwExStyle = WS_EX_APPWINDOW;
|
||||
style |= WS_POPUP;
|
||||
} else {
|
||||
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
if (hints.border)
|
||||
style |= WS_OVERLAPPEDWINDOW;
|
||||
else
|
||||
style |= WS_POPUP;
|
||||
}
|
||||
|
||||
info.fs = fullscreen;//hints.fullscreen;
|
||||
|
||||
// Since Windows uses some of the window for the border, etc,
|
||||
// we have to ask how big the window should really be
|
||||
RECT newSize;
|
||||
newSize.left = x;
|
||||
newSize.top = y;
|
||||
newSize.right = hints.real_w+x;
|
||||
newSize.bottom = hints.real_h+y;
|
||||
|
||||
AdjustWindowRectEx(&newSize, style, FALSE, dwExStyle); // no menu
|
||||
|
||||
if (newSize.left<0 && x>=0){
|
||||
newSize.right-=newSize.left;
|
||||
newSize.left=0;
|
||||
}
|
||||
if (newSize.top<0 && y>=0){
|
||||
newSize.bottom-=newSize.top;
|
||||
newSize.top=0;
|
||||
}
|
||||
|
||||
// Create the window
|
||||
info.win = CreateWindowEx (
|
||||
dwExStyle,
|
||||
"GEM",
|
||||
hints.title,
|
||||
style,
|
||||
newSize.left,
|
||||
newSize.top,
|
||||
newSize.right - newSize.left,
|
||||
newSize.bottom - newSize.top,
|
||||
NULL,
|
||||
NULL,
|
||||
hInstance,
|
||||
NULL);
|
||||
|
||||
if (!info.win) {
|
||||
error("GEM: Unable to create window");
|
||||
return(0);
|
||||
}
|
||||
|
||||
// create the device context
|
||||
info.dc = GetDC(info.win);
|
||||
if (!info.dc) {
|
||||
error("GEM: Unable to create device context");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// set the pixel format for the window
|
||||
if (!bSetupPixelFormat(info.dc, hints)) {
|
||||
error("GEM: Unable to set window pixel format");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// create the OpenGL context
|
||||
info.context = wglCreateContext(info.dc);
|
||||
if (!info.context) {
|
||||
error("GEM: Unable to create OpenGL context");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// do we share display lists?
|
||||
if (hints.shared) wglShareLists(hints.shared, info.context);
|
||||
|
||||
// make the context the current rendering context
|
||||
if (!wglMakeCurrent(info.dc, info.context)) {
|
||||
error("GEM: Unable to make OpenGL context current");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!hints.actuallyDisplay) return(1);
|
||||
|
||||
// show and update main window
|
||||
if (fullscreen){
|
||||
ShowWindow(info.win,SW_SHOW); // Show The Window
|
||||
SetForegroundWindow(info.win); // Slightly Higher Priority
|
||||
SetFocus(info.win);
|
||||
} else ShowWindow(info.win, SW_SHOWNORMAL);
|
||||
|
||||
UpdateWindow(info.win);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// destroyGemWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void destroyGemWindow(WindowInfo &info)
|
||||
{
|
||||
if (info.fs) ChangeDisplaySettings(NULL,0); // Switch Back To The Desktop
|
||||
|
||||
if (info.win) {
|
||||
if (info.dc) {
|
||||
if (info.context) {
|
||||
wglDeleteContext(info.context);
|
||||
}
|
||||
ReleaseDC(info.win, info.dc);
|
||||
}
|
||||
DestroyWindow(info.win);
|
||||
}
|
||||
info.dc = NULL;
|
||||
info.win = NULL;
|
||||
info.dc = NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// switch cursor on/off
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
int cursorGemWindow(WindowInfo &info, int state)
|
||||
{
|
||||
static int cursor_state = 1;
|
||||
state=!(!state);
|
||||
if (cursor_state != state){
|
||||
cursor_state=ShowCursor(state)+1;
|
||||
}
|
||||
|
||||
return cursor_state;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// set topmost position on/off
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
int topmostGemWindow(WindowInfo &info, int state)
|
||||
{
|
||||
static int topmost_state = 0;
|
||||
state=!(!state);
|
||||
if (state)
|
||||
SetWindowPos(info.win, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
||||
else
|
||||
SetWindowPos(info.win, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
||||
topmost_state = state;
|
||||
return topmost_state;
|
||||
}
|
||||
|
||||
|
||||
void gemWinSwapBuffers(WindowInfo&nfo)
|
||||
{
|
||||
SwapBuffers(nfo.dc);
|
||||
}
|
||||
|
||||
void gemWinMakeCurrent(WindowInfo&nfo)
|
||||
{
|
||||
if (!nfo.dc && !nfo.context)return; // do not crash ??
|
||||
wglMakeCurrent(nfo.dc, nfo.context);
|
||||
}
|
||||
|
||||
bool initGemWin(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
GEM_EXTERN void initWin_sharedContext(WindowInfo &info, WindowHints &hints)
|
||||
{
|
||||
// myHints.shared = constInfo.context;
|
||||
hints.shared = NULL;
|
||||
}
|
||||
|
||||
|
||||
GEM_EXTERN void dispatchGemWindowMessages(WindowInfo &win)
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
511
Gem/src/Base/GemWinCreateXWin.cpp
Normal file
511
Gem/src/Base/GemWinCreateXWin.cpp
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#include "Gem/GemConfig.h"
|
||||
#if defined __linux__ || defined HAVE_GL_GLX_H
|
||||
|
||||
|
||||
#include "Gem/Event.h"
|
||||
#include "Gem/Manager.h"
|
||||
|
||||
#include "GemWinCreate.h"
|
||||
|
||||
#include <m_pd.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define EVENT_MASK \
|
||||
ExposureMask|StructureNotifyMask|PointerMotionMask|ButtonMotionMask | \
|
||||
ButtonReleaseMask | ButtonPressMask | KeyPressMask | KeyReleaseMask | ResizeRedirectMask | DestroyNotify
|
||||
|
||||
|
||||
// window creation variables
|
||||
static int snglBuf24[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_STENCIL_SIZE, 8,
|
||||
GLX_ACCUM_RED_SIZE, 8,
|
||||
GLX_ACCUM_GREEN_SIZE, 8,
|
||||
GLX_ACCUM_BLUE_SIZE, 8,
|
||||
None};
|
||||
static int snglBuf24Stereo[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_STENCIL_SIZE, 8,
|
||||
GLX_ACCUM_RED_SIZE, 8,
|
||||
GLX_ACCUM_GREEN_SIZE, 8,
|
||||
GLX_ACCUM_BLUE_SIZE, 8,
|
||||
GLX_STEREO,
|
||||
None};
|
||||
static int dblBuf24[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 4,
|
||||
GLX_GREEN_SIZE, 4,
|
||||
GLX_BLUE_SIZE, 4,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_STENCIL_SIZE, 8,
|
||||
GLX_ACCUM_RED_SIZE, 8,
|
||||
GLX_ACCUM_GREEN_SIZE, 8,
|
||||
GLX_ACCUM_BLUE_SIZE, 8,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None};
|
||||
static int dblBuf24Stereo[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 4,
|
||||
GLX_GREEN_SIZE, 4,
|
||||
GLX_BLUE_SIZE, 4,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_STENCIL_SIZE, 8,
|
||||
GLX_ACCUM_RED_SIZE, 8,
|
||||
GLX_ACCUM_GREEN_SIZE, 8,
|
||||
GLX_ACCUM_BLUE_SIZE, 8,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_STEREO,
|
||||
None};
|
||||
static int snglBuf8[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 3,
|
||||
GLX_GREEN_SIZE, 3,
|
||||
GLX_BLUE_SIZE, 2,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
None};
|
||||
static int snglBuf8Stereo[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 3,
|
||||
GLX_GREEN_SIZE, 3,
|
||||
GLX_BLUE_SIZE, 2,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_STEREO,
|
||||
None};
|
||||
static int dblBuf8[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 2,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None};
|
||||
|
||||
static int dblBuf8Stereo[] = {GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 2,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_STEREO,
|
||||
None};
|
||||
|
||||
static int xerr=0;
|
||||
int ErrorHandler (Display *dpy, XErrorEvent *event)
|
||||
{
|
||||
// we don't really care about the error
|
||||
// let's hope for the best
|
||||
if(event)
|
||||
xerr=event->error_code;
|
||||
|
||||
if ( event->error_code != BadWindow ) {
|
||||
char buf[256];
|
||||
XGetErrorText (dpy, event->error_code, buf, sizeof(buf));
|
||||
error("GEM-Xwin: %s\n", buf);
|
||||
} else
|
||||
error("GEM-Xwin: BadWindow (%d)\n", xerr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
Bool WaitForNotify(Display *, XEvent *e, char *arg)
|
||||
{
|
||||
return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
|
||||
}
|
||||
|
||||
int createGemWindow(WindowInfo &info, WindowHints &hints)
|
||||
{
|
||||
#ifdef HAVE_LIBXXF86VM
|
||||
XF86VidModeModeInfo **modes;
|
||||
#endif
|
||||
int modeNum=4;
|
||||
int bestMode=0;
|
||||
int fullscreen=hints.fullscreen;
|
||||
|
||||
char svalue[3];
|
||||
int fsaa=(int)hints.fsaa;
|
||||
sprintf(svalue, "%d", fsaa);
|
||||
if (fsaa!=0) setenv("__GL_FSAA_MODE", svalue, 1); // this works only for NVIDIA-cards
|
||||
|
||||
XSetErrorHandler (ErrorHandler);
|
||||
|
||||
if ( (info.dpy = XOpenDisplay(hints.display)) == NULL)
|
||||
{
|
||||
error("GEM: Could not open display %s",hints.display);
|
||||
return(0);
|
||||
}
|
||||
|
||||
info.screen = DefaultScreen(info.dpy);
|
||||
|
||||
/* this used to be in GemMan::createContext()
|
||||
* and produced a number of XDisplays that were not closed
|
||||
* i really think that it fits better in here;
|
||||
* however, i have currently no way to test what really happens
|
||||
* if the X-server has no glx extension
|
||||
*/
|
||||
if ( !glXQueryExtension(info.dpy, NULL, NULL) )
|
||||
{
|
||||
error("GEM: X server has no OpenGL GLX extension");
|
||||
destroyGemWindow(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fullscreen){
|
||||
if (hints.display){
|
||||
error("GEM: fullscreen not available on remote display");
|
||||
fullscreen=0;
|
||||
} else {
|
||||
#ifdef HAVE_LIBXXF86VM
|
||||
XF86VidModeGetAllModeLines(info.dpy, info.screen, &modeNum, &modes);
|
||||
info.deskMode = *modes[0];
|
||||
#else
|
||||
error("GEM: no xxf86vm-support: cannot switch to fullscreen");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
XVisualInfo *vi;
|
||||
// the user wants double buffer
|
||||
if (hints.buffer == 2) {
|
||||
// try for a double-buffered on 24bit machine (try stereo first)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, dblBuf24Stereo);
|
||||
if (vi == NULL)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, dblBuf24);
|
||||
if (vi == NULL) {
|
||||
// try for a double buffered on a 8bit machine (try stereo first)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, dblBuf8Stereo);
|
||||
if(vi == NULL)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, dblBuf8);
|
||||
if (vi == NULL) {
|
||||
error("GEM: Unable to create double buffer window");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
post("GEM: Only using 8 color bits");
|
||||
}
|
||||
}
|
||||
// the user wants single buffer
|
||||
else {
|
||||
// try for a single buffered on a 24bit machine (try stereo first)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, snglBuf24Stereo);
|
||||
if (vi == NULL)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, snglBuf24);
|
||||
if (vi == NULL) {
|
||||
// try for a single buffered on a 8bit machine (try stereo first)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, snglBuf8Stereo);
|
||||
if (vi == NULL)
|
||||
vi = glXChooseVisual(info.dpy, info.screen, snglBuf8);
|
||||
if (vi == NULL) {
|
||||
error("GEM: Unable to create single buffer window");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
post("GEM: Only using 8 color bits");
|
||||
}
|
||||
hints.buffer = 1;
|
||||
}
|
||||
|
||||
if (vi->c_class != TrueColor && vi->c_class != DirectColor) {
|
||||
error("GEM: TrueColor visual required for this program (got %d)", vi->c_class);
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
// create the rendering context
|
||||
try {
|
||||
info.context = glXCreateContext(info.dpy, vi, hints.shared, GL_TRUE);
|
||||
} catch(void*e){
|
||||
info.context=NULL;
|
||||
}
|
||||
if (info.context == NULL) {
|
||||
error("GEM: Could not create rendering context");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
// create the X color map
|
||||
info.cmap = XCreateColormap(info.dpy, RootWindow(info.dpy, vi->screen),
|
||||
vi->visual, AllocNone);
|
||||
if (!info.cmap) {
|
||||
error("GEM: Could not create X colormap");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.colormap = info.cmap;
|
||||
swa.border_pixel = 0;
|
||||
// event_mask creates signal that window has been created
|
||||
swa.event_mask = EVENT_MASK;
|
||||
|
||||
hints.real_w = hints.width;
|
||||
hints.real_h = hints.height;
|
||||
|
||||
int flags;
|
||||
int x = hints.x_offset;
|
||||
int y = hints.y_offset;
|
||||
#ifdef HAVE_LIBXXF86VM
|
||||
if (fullscreen){
|
||||
/* look for mode with requested resolution */
|
||||
for (int i = 0; i < modeNum; i++) {
|
||||
if ((modes[i]->hdisplay == hints.width) && (modes[i]->vdisplay == hints.height)) {
|
||||
bestMode = i;
|
||||
}
|
||||
}
|
||||
|
||||
XF86VidModeSwitchToMode(info.dpy, info.screen, modes[bestMode]);
|
||||
XF86VidModeSetViewPort(info.dpy, info.screen, 0, 0);
|
||||
hints.real_w = modes[bestMode]->hdisplay;
|
||||
hints.real_h = modes[bestMode]->vdisplay;
|
||||
XFree(modes);
|
||||
|
||||
swa.override_redirect = True;
|
||||
flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect;
|
||||
x=y=0;
|
||||
} else
|
||||
#endif
|
||||
{ // !fullscren
|
||||
info.have_border = hints.border;
|
||||
if (hints.border){
|
||||
swa.override_redirect = False;
|
||||
flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect;
|
||||
} else {
|
||||
swa.override_redirect = True;
|
||||
flags=CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect;
|
||||
}
|
||||
}
|
||||
|
||||
info.fs = fullscreen;
|
||||
info.win = XCreateWindow(info.dpy, RootWindow(info.dpy, vi->screen),
|
||||
x, y, hints.real_w, hints.real_h,
|
||||
0, vi->depth, InputOutput,
|
||||
vi->visual, flags, &swa);
|
||||
if (!info.win)
|
||||
{
|
||||
error("GEM: Could not create X window");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
XSelectInput(info.dpy, info.win, EVENT_MASK);
|
||||
|
||||
/* found a bit at
|
||||
* http://biology.ncsa.uiuc.edu/library/SGI_bookshelves/SGI_Developer/books/OpenGL_Porting/sgi_html/apf.html
|
||||
* LATER think about reacting on this event...
|
||||
*/
|
||||
info.delete_atom = XInternAtom(info.dpy, "WM_DELETE_WINDOW", True);
|
||||
if (info.delete_atom != None)
|
||||
XSetWMProtocols(info.dpy, info.win, &info.delete_atom,1);
|
||||
|
||||
XSetStandardProperties(info.dpy, info.win,
|
||||
hints.title, "gem",
|
||||
None, 0, 0, NULL);
|
||||
try{
|
||||
xerr=0;
|
||||
glXMakeCurrent(info.dpy, info.win, info.context);
|
||||
|
||||
/* seems like the error-handler was called; so something did not work the way it should
|
||||
* should we really prevent window-creation in this case?
|
||||
* LATER re-think the entire dual-context thing
|
||||
*/
|
||||
if(xerr!=0) {
|
||||
error("GEM: problems making glX-context current: refusing to continue");
|
||||
error("GEM: try setting the environment variable GEM_SINGLE_CONTEXT=1");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
}catch(void*e){
|
||||
error("GEM: Could not make glX-context current");
|
||||
destroyGemWindow(info);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!hints.actuallyDisplay) return(1);
|
||||
XMapRaised(info.dpy, info.win);
|
||||
// XMapWindow(info.dpy, info.win);
|
||||
XEvent report;
|
||||
XIfEvent(info.dpy, &report, WaitForNotify, (char*)info.win);
|
||||
if (glXIsDirect(info.dpy, info.context))post("GEM: Direct Rendering enabled!");
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int cursorGemWindow(WindowInfo &info, int state)
|
||||
{
|
||||
if (!state) {
|
||||
static char data[1] = {0};
|
||||
|
||||
Cursor cursor;
|
||||
Pixmap blank;
|
||||
XColor dummy;
|
||||
|
||||
blank = XCreateBitmapFromData(info.dpy, info.win,
|
||||
data, 1, 1);
|
||||
|
||||
cursor = XCreatePixmapCursor(info.dpy, blank, blank,
|
||||
&dummy, &dummy, 0, 0);
|
||||
XFreePixmap(info.dpy, blank);
|
||||
XDefineCursor(info.dpy, info.win,cursor);
|
||||
}
|
||||
else
|
||||
XUndefineCursor(info.dpy, info.win);
|
||||
return 0; //?
|
||||
}
|
||||
|
||||
int topmostGemWindow(WindowInfo &info, int state){
|
||||
/* we don't give a warning to not be annoying */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroyGemWindow(WindowInfo &info)
|
||||
{
|
||||
/* both glXMakeCurrent() and XCloseDisplay() will crash the application
|
||||
* if the handler of the display (info.dpy) is invalid, e.g. because
|
||||
* somebody closed the Gem-window with xkill or by clicking on the "x" of the window
|
||||
*/
|
||||
if (info.dpy)
|
||||
{
|
||||
int err=0;
|
||||
/* patch by cesare marilungo to prevent the crash "on my laptop" */
|
||||
glXMakeCurrent(info.dpy, None, NULL); /* this crashes if no window is there! */
|
||||
|
||||
if (info.win)
|
||||
err=XDestroyWindow(info.dpy, info.win);
|
||||
if (info.have_constContext && info.context) {
|
||||
// this crashes sometimes on my laptop:
|
||||
glXDestroyContext(info.dpy, info.context);
|
||||
}
|
||||
if (info.cmap)
|
||||
err=XFreeColormap(info.dpy, info.cmap);
|
||||
|
||||
#ifdef HAVE_LIBXXF86VM
|
||||
if (info.fs){
|
||||
XF86VidModeSwitchToMode(info.dpy, info.screen, &info.deskMode);
|
||||
XF86VidModeSetViewPort(info.dpy, info.screen, 0, 0);
|
||||
info.fs=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
err=XCloseDisplay(info.dpy); /* this crashes if no window is there */
|
||||
}
|
||||
info.dpy = NULL;
|
||||
info.win = 0;
|
||||
info.cmap = 0;
|
||||
info.context = NULL;
|
||||
if(info.delete_atom)info.delete_atom=0; /* not very sophisticated destruction...*/
|
||||
}
|
||||
|
||||
void gemWinSwapBuffers(WindowInfo&nfo)
|
||||
{
|
||||
glXSwapBuffers(nfo.dpy, nfo.win);
|
||||
}
|
||||
|
||||
void gemWinMakeCurrent(WindowInfo&nfo)
|
||||
{
|
||||
if (!nfo.dpy && !nfo.win && !nfo.context)return; // do not crash
|
||||
glXMakeCurrent(nfo.dpy, nfo.win, nfo.context);
|
||||
}
|
||||
|
||||
|
||||
bool initGemWin(void) {
|
||||
/* nothing to be done here... */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
GEM_EXTERN void initWin_sharedContext(WindowInfo &info, WindowHints &hints)
|
||||
{
|
||||
// myHints.shared = constInfo.context;
|
||||
hints.shared = NULL;
|
||||
}
|
||||
|
||||
|
||||
GEM_EXTERN void dispatchGemWindowMessages(WindowInfo &win)
|
||||
{
|
||||
XEvent event;
|
||||
XButtonEvent* eb = (XButtonEvent*)&event;
|
||||
XKeyEvent* kb = (XKeyEvent*)&event;
|
||||
XResizeRequestEvent *res = (XResizeRequestEvent*)&event;
|
||||
char keystring[2];
|
||||
KeySym keysym_return;
|
||||
|
||||
while (XCheckWindowEvent(win.dpy,win.win,
|
||||
ResizeRedirectMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
PointerMotionMask |
|
||||
ButtonMotionMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask,
|
||||
&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case ButtonPress:
|
||||
triggerButtonEvent(eb->button-1, 1, eb->x, eb->y);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
triggerButtonEvent(eb->button-1, 0, eb->x, eb->y);
|
||||
break;
|
||||
case MotionNotify:
|
||||
triggerMotionEvent(eb->x, eb->y);
|
||||
if(!win.have_border) {
|
||||
int err=XSetInputFocus(win.dpy, win.win, RevertToParent, CurrentTime);
|
||||
err=0;
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
if (XLookupString(kb,keystring,2,&keysym_return,NULL)==0) {
|
||||
//modifier key:use keysym
|
||||
//triggerKeyboardEvent(XKeysymToString(keysym_return), kb->keycode, 1);
|
||||
}
|
||||
if ( (keysym_return & 0xff00)== 0xff00 ) {
|
||||
//non alphanumeric key: use keysym
|
||||
triggerKeyboardEvent(XKeysymToString(keysym_return), kb->keycode, 1);
|
||||
} else {
|
||||
triggerKeyboardEvent(keystring, kb->keycode, 1);
|
||||
}
|
||||
break;
|
||||
case KeyRelease:
|
||||
if (XLookupString(kb,keystring,2,&keysym_return,NULL)==0) {
|
||||
//modifier key:use keysym
|
||||
triggerKeyboardEvent(XKeysymToString(keysym_return), kb->keycode, 0);
|
||||
}
|
||||
|
||||
if ( (keysym_return & 0xff00)== 0xff00 ) {
|
||||
//non alphanumeric key: use keysym
|
||||
triggerKeyboardEvent(XKeysymToString(keysym_return), kb->keycode, 0);
|
||||
} else {
|
||||
triggerKeyboardEvent(keystring, kb->keycode, 0);
|
||||
}
|
||||
break;
|
||||
case ResizeRequest:
|
||||
triggerResizeEvent(res->width, res->height);
|
||||
XResizeWindow(win.dpy, win.win, res->width, res->height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (XCheckTypedEvent(win.dpy, ClientMessage, &event)) {
|
||||
GemMan::destroyWindowSoon();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // unix
|
||||
376
Gem/src/Base/GemWindow.cpp
Normal file
376
Gem/src/Base/GemWindow.cpp
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#include "GemWindow.h"
|
||||
#include "Gem/Manager.h"
|
||||
#include "RTE/MessageCallbacks.h"
|
||||
|
||||
#include "Gem/Settings.h"
|
||||
#include "GemContext.h"
|
||||
#include "Gem/Exception.h"
|
||||
|
||||
class GemWindow::PIMPL {
|
||||
public:
|
||||
PIMPL(GemWindow*gc) : parent(gc),
|
||||
mycontext(NULL),
|
||||
infoOut(NULL),
|
||||
dispatchClock(NULL),
|
||||
dispatchTime(10.),
|
||||
qClock(NULL)
|
||||
{
|
||||
qClock=clock_new(this, reinterpret_cast<t_method>(qCallBack));
|
||||
dispatchClock=clock_new(this, reinterpret_cast<t_method>(dispatchCallBack));
|
||||
}
|
||||
~PIMPL(void) {
|
||||
if(qClock) clock_free (qClock); qClock=NULL;
|
||||
if(dispatchClock) clock_free (dispatchClock); dispatchClock=NULL;
|
||||
if(infoOut)outlet_free(infoOut); infoOut=NULL;
|
||||
}
|
||||
|
||||
GemWindow*parent;
|
||||
gem::Context*mycontext;
|
||||
|
||||
t_outlet*infoOut;
|
||||
|
||||
t_clock*dispatchClock;
|
||||
double dispatchTime;
|
||||
void dispatch(void) {
|
||||
parent->dispatch();
|
||||
clock_delay(dispatchClock, dispatchTime);
|
||||
}
|
||||
static void dispatchCallBack(PIMPL*x) {
|
||||
x->dispatch();
|
||||
}
|
||||
void undispatch(void) {
|
||||
clock_unset(dispatchClock);
|
||||
}
|
||||
|
||||
std::vector<std::vector<t_atom> >qQueue;
|
||||
t_clock*qClock;
|
||||
|
||||
void queue(std::vector<t_atom>alist) {
|
||||
if(alist.size()>0)
|
||||
qQueue.push_back(alist);
|
||||
|
||||
requeue();
|
||||
}
|
||||
|
||||
void queue(t_symbol*s,int argc, t_atom*argv) {
|
||||
std::vector<t_atom>alist;
|
||||
t_atom at[1];
|
||||
SETSYMBOL(at, s);
|
||||
alist.push_back(at[0]);
|
||||
while(argc-->0) {
|
||||
alist.push_back(*argv++);
|
||||
}
|
||||
queue(alist);
|
||||
}
|
||||
|
||||
void sendInfo(std::vector<t_atom>alist) {
|
||||
int argc=alist.size();
|
||||
t_atom*ap=NULL;
|
||||
t_atom*argv=NULL;
|
||||
#if 0
|
||||
argv=alist.data();
|
||||
#else
|
||||
int i=0;
|
||||
ap=new t_atom[argc];
|
||||
argv=ap;
|
||||
for(i=0; i<argc; i++) {
|
||||
argv[i]=alist[i];
|
||||
}
|
||||
#endif
|
||||
outlet_anything(infoOut, atom_getsymbol(argv), argc-1, argv+1);
|
||||
if(ap)
|
||||
delete[]ap;
|
||||
}
|
||||
void dequeue(void) {
|
||||
unsigned int i=0;
|
||||
for(i=0; i<qQueue.size(); i++) {
|
||||
sendInfo(qQueue[i]);
|
||||
}
|
||||
qQueue.clear();
|
||||
}
|
||||
|
||||
/* qClock callback for dequeueing */
|
||||
static void qCallBack(PIMPL*x) {
|
||||
x->dequeue();
|
||||
}
|
||||
|
||||
/* start the clock again */
|
||||
void requeue(void) {
|
||||
clock_delay(qClock, 0);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemWindow :: GemWindow()
|
||||
: m_pimpl(new PIMPL(this)),
|
||||
m_width(500), m_height(500),
|
||||
m_xoffset(0), m_yoffset(0),
|
||||
m_border(true), m_fullscreen(false),
|
||||
m_buffer(2),
|
||||
m_title("Gem"),
|
||||
m_cursor(true),
|
||||
m_fsaa(0),
|
||||
m_context(NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
i=m_width; gem::Settings::get("window.width" , i), m_width =i;
|
||||
i=m_height; gem::Settings::get("window.height", i), m_height=i;
|
||||
m_pimpl->infoOut = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemWindow :: ~GemWindow()
|
||||
{
|
||||
if(m_pimpl) {
|
||||
m_pimpl->mycontext=destroyContext(m_pimpl->mycontext);
|
||||
delete m_pimpl; m_pimpl=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GemWindow::info(std::vector<t_atom>l) {
|
||||
m_pimpl->queue(l);
|
||||
}
|
||||
|
||||
void GemWindow::info(t_symbol*s, int argc, t_atom*argv) {
|
||||
m_pimpl->queue(s, argc, argv);
|
||||
}
|
||||
void GemWindow::info(std::string s) {
|
||||
info(gensym(s.c_str()), 0, NULL);
|
||||
}
|
||||
void GemWindow::info(std::string s, int i) {
|
||||
info(s, (t_float)i);
|
||||
}
|
||||
|
||||
void GemWindow :: info(std::string s, t_float value)
|
||||
{
|
||||
t_atom atom;
|
||||
SETFLOAT(&atom, value);
|
||||
info(gensym(s.c_str()), 1, &atom);
|
||||
}
|
||||
void GemWindow :: info(std::string s, std::string value)
|
||||
{
|
||||
t_atom atom;
|
||||
SETSYMBOL(&atom, gensym(value.c_str()));
|
||||
info(gensym(s.c_str()), 1, &atom);
|
||||
}
|
||||
|
||||
void GemWindow :: bang(void)
|
||||
{
|
||||
outlet_bang(m_pimpl->infoOut);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* mouse movement */
|
||||
void GemWindow::motion(int x, int y)
|
||||
{
|
||||
t_atom ap[3];
|
||||
SETSYMBOL(ap+0, gensym("motion"));
|
||||
SETFLOAT (ap+1, x);
|
||||
SETFLOAT (ap+2, y);
|
||||
|
||||
info(gensym("mouse"), 3, ap);
|
||||
}
|
||||
/* mouse buttons */
|
||||
void GemWindow::button(int id, int state)
|
||||
{
|
||||
t_atom ap[3];
|
||||
SETSYMBOL(ap+0, gensym("button"));
|
||||
SETFLOAT (ap+1, id);
|
||||
SETFLOAT (ap+2, state);
|
||||
|
||||
info(gensym("mouse"), 3, ap);
|
||||
}
|
||||
|
||||
/* keyboard buttons */
|
||||
void GemWindow::key(std::string sid, int iid, int state) {
|
||||
t_atom ap[3];
|
||||
SETSYMBOL(ap+0, gensym("key"));
|
||||
SETFLOAT (ap+1, iid);
|
||||
SETFLOAT (ap+2, state);
|
||||
|
||||
info(gensym("keyboard"), 3, ap);
|
||||
|
||||
SETSYMBOL(ap+0, gensym("keyname"));
|
||||
SETSYMBOL(ap+1, gensym(sid.c_str()));
|
||||
// SETFLOAT (ap+2, state);
|
||||
|
||||
info(gensym("keyboard"), 3, ap);
|
||||
}
|
||||
|
||||
void GemWindow::dimension(unsigned int w, unsigned int h) {
|
||||
t_atom ap[2];
|
||||
SETFLOAT (ap+0, w);
|
||||
SETFLOAT (ap+1, h);
|
||||
|
||||
info(gensym("dimen"), 2, ap);
|
||||
}
|
||||
|
||||
void GemWindow::position(int x, int y) {
|
||||
t_atom ap[2];
|
||||
SETFLOAT (ap+0, x);
|
||||
SETFLOAT (ap+1, y);
|
||||
|
||||
info(gensym("offset"), 2, ap);
|
||||
}
|
||||
|
||||
void GemWindow::dispatch() {
|
||||
// LATER setup a clock that calls dispatch() every so often
|
||||
}
|
||||
|
||||
gem::Context*GemWindow::createContext(void){
|
||||
return new gem::Context();
|
||||
}
|
||||
gem::Context*GemWindow::destroyContext(gem::Context*ctx){
|
||||
if(ctx)delete ctx;
|
||||
ctx=NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
bool GemWindow::createGemWindow(void){
|
||||
if(!m_context) {
|
||||
try {
|
||||
m_pimpl->mycontext = new gem::Context();
|
||||
} catch (GemException&x) {
|
||||
m_context=NULL;
|
||||
error("%s", x.what());
|
||||
return false;
|
||||
}
|
||||
m_context=m_pimpl->mycontext;
|
||||
} else {
|
||||
m_pimpl->mycontext = NULL;
|
||||
}
|
||||
|
||||
m_pimpl->dispatch();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GemWindow::destroyGemWindow(void){
|
||||
m_pimpl->mycontext=destroyContext(m_pimpl->mycontext);
|
||||
m_pimpl->undispatch();
|
||||
}
|
||||
|
||||
bool GemWindow::pushContext(void){
|
||||
if(!m_context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_context->push())
|
||||
return false;
|
||||
|
||||
dispatch();
|
||||
return true;
|
||||
}
|
||||
bool GemWindow::popContext(void){
|
||||
return (m_context && m_context->pop());
|
||||
}
|
||||
|
||||
void GemWindow::render(void){
|
||||
if(!makeCurrent()) {
|
||||
error("unable to switch to current window (do you have one?), cannot render!");
|
||||
return;
|
||||
}
|
||||
if(!pushContext()) {
|
||||
error("unable to switch to current context, cannot render!");
|
||||
return;
|
||||
}
|
||||
bang();
|
||||
if(m_buffer==2)
|
||||
swapBuffers();
|
||||
|
||||
popContext();
|
||||
}
|
||||
|
||||
void GemWindow:: bufferMess(int buf) {
|
||||
switch(buf) {
|
||||
case 1: case 2:
|
||||
m_buffer=buf;
|
||||
break;
|
||||
default:
|
||||
error("buffer can only be '1' (single) or '2' (double) buffered");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void GemWindow:: fsaaMess(int value) {
|
||||
m_fsaa=value;
|
||||
}
|
||||
|
||||
void GemWindow::titleMess(std::string s) {
|
||||
m_title=s;
|
||||
}
|
||||
void GemWindow::borderMess(bool on) {
|
||||
m_border=on;
|
||||
}
|
||||
|
||||
void GemWindow:: fullscreenMess(int on) {
|
||||
m_fullscreen=on;
|
||||
}
|
||||
void GemWindow:: offsetMess(int x, int y) {
|
||||
m_xoffset=x;
|
||||
m_yoffset=y;
|
||||
}
|
||||
|
||||
void GemWindow:: createMess(std::string) {
|
||||
create();
|
||||
}
|
||||
void GemWindow:: destroyMess(void) {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void GemWindow:: cursorMess(bool on) {
|
||||
m_cursor=on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GemWindow:: printMess(void) {
|
||||
// nada
|
||||
}
|
||||
|
||||
void GemWindow :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG0(classPtr, "bang", render);
|
||||
CPPEXTERN_MSG1(classPtr, "create", createMess, std::string);
|
||||
CPPEXTERN_MSG0(classPtr, "destroy", destroyMess);
|
||||
|
||||
CPPEXTERN_MSG1(classPtr, "buffer", bufferMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "FSAA", fsaaMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "title", titleMess, std::string);
|
||||
CPPEXTERN_MSG2(classPtr, "dimen", dimensionsMess, unsigned int, unsigned int);
|
||||
CPPEXTERN_MSG2(classPtr, "offset", offsetMess, int, int);
|
||||
CPPEXTERN_MSG1(classPtr, "fullscreen", fullscreenMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "border", borderMess, bool);
|
||||
CPPEXTERN_MSG1(classPtr, "cursor", cursorMess, bool);
|
||||
|
||||
// CPPEXTERN_MSG0(classPtr, "print", printMess);
|
||||
}
|
||||
208
Gem/src/Base/GemWindow.h
Normal file
208
Gem/src/Base/GemWindow.h
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
a window class to render to
|
||||
|
||||
Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_GEMWINDOW_H_
|
||||
#define _INCLUDE__GEM_BASE_GEMWINDOW_H_
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
#include <vector>
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemWindow
|
||||
|
||||
a window
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
namespace gem {
|
||||
class Context;
|
||||
};
|
||||
|
||||
class GEM_EXTERN GemWindow : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(GemWindow, CPPExtern);
|
||||
|
||||
private:
|
||||
class PIMPL;
|
||||
PIMPL*m_pimpl;
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemWindow(void);
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemWindow(void);
|
||||
|
||||
public:
|
||||
/* OUTPUT */
|
||||
|
||||
/* an outlet to propagate information to the patch... mainly callbacks from the context */
|
||||
/* LATER think about detaching the output from the stack, so we can e.g. destroy a window from a mouse-callback */
|
||||
void info(std::vector<t_atom>);
|
||||
void info(t_symbol*s, int, t_atom*);
|
||||
void info(std::string);
|
||||
void info(std::string, t_float);
|
||||
void info(std::string, int i);
|
||||
void info(std::string, std::string);
|
||||
|
||||
/* tell downstream objects to render */
|
||||
void bang(void);
|
||||
|
||||
/* mouse movement */
|
||||
void motion(int x, int y);
|
||||
/* mouse buttons */
|
||||
void button(int id, int state);
|
||||
/* keyboard buttons */
|
||||
// void key(std::string id, int state);
|
||||
//void key(int id, int state);
|
||||
void key(std::string, int, int state);
|
||||
|
||||
/* window resize/move */
|
||||
void dimension(unsigned int, unsigned int);
|
||||
void position (int, int);
|
||||
|
||||
/* INPUT */
|
||||
|
||||
/* create a new context */
|
||||
static gem::Context*createContext(void);
|
||||
/* destroy a given context;
|
||||
* @returns NULL
|
||||
*/
|
||||
static gem::Context*destroyContext(gem::Context*);
|
||||
|
||||
/* this MUST be called from the derived classes
|
||||
* as it will eventually establish a new GemContext (if m_context is non-NULL)
|
||||
* if you want to share GemContext's you MUST call
|
||||
* GemWindow::createContext() yourself and set m_context to the result
|
||||
*
|
||||
* if <tt>false</tt> is returned, you should not continue
|
||||
*/
|
||||
bool createGemWindow(void);
|
||||
/* create a new window
|
||||
* make sure that this calls the parent's createContext() method
|
||||
*/
|
||||
virtual bool create(void) = 0;
|
||||
|
||||
/* destroy an established context+infrastructuure *
|
||||
* make sure that this get's called from your destroy() implementation
|
||||
*/
|
||||
void destroyGemWindow();
|
||||
/* create the current window
|
||||
* make sure to call GemWindow::destroyGemWindow()
|
||||
*/
|
||||
virtual void destroy(void) = 0;
|
||||
|
||||
/* make the object's context (window,...) the current context
|
||||
* this is virtual, so objects can add their own code
|
||||
* note however, that they should also call this (parent's) function within
|
||||
* typically implementations look like this:
|
||||
* bool <mywindow>::makeCurrent(void) {
|
||||
* // do your own stuff
|
||||
*
|
||||
* is <tt>false</tt> is returned, do not attempt to use it (e.g. draw into it)
|
||||
*/
|
||||
virtual bool makeCurrent(void) = 0;
|
||||
|
||||
/*
|
||||
* make the GemWindow current (reset stacks), switch multiContext
|
||||
*/
|
||||
bool pushContext(void);
|
||||
/*
|
||||
* make uncurrent
|
||||
*/
|
||||
bool popContext (void);
|
||||
|
||||
/* swap back/front buffer
|
||||
*/
|
||||
virtual void swapBuffers(void) = 0;
|
||||
|
||||
/* dispatch messages from the window
|
||||
* this might get called more often than the render-cycle
|
||||
* it might also be called automatically as soon as the window
|
||||
* is create()ed (and until the window is destroy()ed)
|
||||
*/
|
||||
virtual void dispatch(void);
|
||||
|
||||
/* render to this window
|
||||
* the default implementation calls:
|
||||
* if(!makeCurrent())return;
|
||||
* if(!pushContext())return;
|
||||
* bang();
|
||||
* if(m_buffer==2)swap();
|
||||
* popContext();
|
||||
* but you can override this, if you want to
|
||||
*/
|
||||
virtual void render(void);
|
||||
|
||||
/* set/get the dimension of the context
|
||||
* setting is done by supplying arguments to the method;
|
||||
* querying is done by supplying NO arguments
|
||||
* this should be kept throughout
|
||||
*/
|
||||
virtual void dimensionsMess(unsigned int width, unsigned int height) = 0;
|
||||
|
||||
|
||||
// common property setters
|
||||
// by default they will simply set the corresponding values (below in the protected section)
|
||||
// to whatever argument is given them
|
||||
// so you can use these values when creating the window
|
||||
// however, if you need to take immediate action (e.g. because you can), you ought to override these functions
|
||||
|
||||
/* render context (pre creation) */
|
||||
virtual void bufferMess(int buf);
|
||||
virtual void fsaaMess(int value);
|
||||
|
||||
/* window decoration (pre creation) */
|
||||
virtual void titleMess(std::string);
|
||||
virtual void borderMess(bool on);
|
||||
|
||||
virtual void fullscreenMess(int on);
|
||||
virtual void offsetMess(int x, int y);
|
||||
|
||||
/* creation/destruction */
|
||||
virtual void createMess(std::string);
|
||||
virtual void destroyMess(void);
|
||||
|
||||
/* post creation */
|
||||
virtual void cursorMess(bool on);
|
||||
|
||||
/* print some info */
|
||||
virtual void printMess(void);
|
||||
|
||||
protected:
|
||||
unsigned int m_width, m_height;
|
||||
|
||||
// common properties of GemWindow's
|
||||
// you can safely ignore these, if they mean nothing to you
|
||||
// however, if they do mean something to you, it would be good if you used these
|
||||
int m_xoffset, m_yoffset;
|
||||
bool m_border;
|
||||
int m_fullscreen;
|
||||
|
||||
unsigned int m_buffer;
|
||||
std::string m_title;
|
||||
bool m_cursor;
|
||||
int m_fsaa;
|
||||
|
||||
gem::Context* m_context;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // for header file
|
||||
80
Gem/src/Base/Makefile.am
Normal file
80
Gem/src/Base/Makefile.am
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#####################################################################
|
||||
# Gem/Base Base-classes for Pd-objectclasses
|
||||
#####################################################################
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src @GEM_CPPFLAGS@
|
||||
include ../check-sources.mk
|
||||
|
||||
noinst_LTLIBRARIES = libBase.la
|
||||
|
||||
libBase_la_CXXFLAGS =
|
||||
libBase_la_LIBADD =
|
||||
libBase_la_LDFLAGS =
|
||||
|
||||
# RTE flags
|
||||
libBase_la_CXXFLAGS += @GEM_RTE_CFLAGS@ @GEM_ARCH_CXXFLAGS@
|
||||
libBase_la_LIBADD += @GEM_RTE_LIBS@
|
||||
libBase_la_LDFLAGS += @GEM_ARCH_LDFLAGS@
|
||||
|
||||
# X
|
||||
libBase_la_CXXFLAGS += $(X_CFLAGS)
|
||||
libBase_la_LIBADD += $(X_PRE_LIBS) $(X_LIBS) $(X_EXTRA_LIBS)
|
||||
|
||||
# openGL
|
||||
libBase_la_CXXFLAGS += @GLX_CFLAGS@
|
||||
libBase_la_LIBADD += @GLX_LIBS@
|
||||
|
||||
# GLEW
|
||||
libBase_la_CXXFLAGS += @GEM_LIB_GLEW_CFLAGS@
|
||||
libBase_la_LIBADD += @GEM_LIB_GLEW_LIBS@
|
||||
|
||||
# FTGL
|
||||
libBase_la_CXXFLAGS += @GEM_LIB_FTGL_CFLAGS@
|
||||
libBase_la_LIBADD += @GEM_LIB_FTGL_LIBS@
|
||||
|
||||
libBase_la_includedir = $(includedir)/Gem/Base
|
||||
libBase_la_include_HEADERS= \
|
||||
CPPExtern.h \
|
||||
GemBase.h \
|
||||
GemGLBase.h \
|
||||
GemGluObj.h \
|
||||
GemPathBase.h \
|
||||
GemPixObj.h \
|
||||
GemPixDualObj.h \
|
||||
GemShape.h \
|
||||
TextBase.h
|
||||
|
||||
libBase_la_include_HEADERS+= \
|
||||
GemWindow.h \
|
||||
GemContext.h
|
||||
|
||||
libBase_la_SOURCES= \
|
||||
CPPExtern.cpp \
|
||||
CPPExtern.h \
|
||||
GemBase.cpp \
|
||||
GemBase.h \
|
||||
GemGLBase.h \
|
||||
GemContext.cpp \
|
||||
GemContext.h \
|
||||
GemGluObj.cpp \
|
||||
GemGluObj.h \
|
||||
GemPathBase.cpp \
|
||||
GemPathBase.h \
|
||||
GemPixDualObj.cpp \
|
||||
GemPixDualObj.h \
|
||||
GemPixObj.cpp \
|
||||
GemPixObj.h \
|
||||
GemShape.cpp \
|
||||
GemShape.h \
|
||||
GemVertex.cpp \
|
||||
GemVertex.h \
|
||||
GemWinCreate.h \
|
||||
GemWinCreateMac.cpp \
|
||||
GemWinCreateNT.cpp \
|
||||
GemWinCreateXWin.cpp \
|
||||
GemWindow.cpp \
|
||||
GemWindow.h \
|
||||
TextBase.cpp \
|
||||
TextBase.h
|
||||
|
||||
21
Gem/src/Base/Makefile.am.template
Normal file
21
Gem/src/Base/Makefile.am.template
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)
|
||||
|
||||
noinst_LTLIBRARIES = libBase.la
|
||||
|
||||
libBase_la_CXXFLAGS =
|
||||
libBase_la_LIBADD =
|
||||
|
||||
# RTE flags
|
||||
libBase_la_CXXFLAGS += @GEM_RTE_CFLAGS@
|
||||
libBase_la_LIBADD += @GEM_RTE_LIBS@
|
||||
|
||||
# GLEW
|
||||
libBase_la_CXXFLAGS += @GEM_LIB_GLEW_CFLAGS@
|
||||
libBase_la_LIBADD += @GEM_LIB_GLEW_LIBS@
|
||||
|
||||
# FTGL
|
||||
libBase_la_CXXFLAGS += @GEM_LIB_FTGL_CFLAGS@
|
||||
libBase_la_LIBADD += @GEM_LIB_FTGL_LIBS@
|
||||
|
||||
libBase_la_SOURCES= @SOURCES@
|
||||
536
Gem/src/Base/TextBase.cpp
Normal file
536
Gem/src/Base/TextBase.cpp
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-2000 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2005 Georg Holzmann <grh@mur.at>
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* FIXXME: check how font handling behaves with multiple contexts
|
||||
*/
|
||||
|
||||
#include "TextBase.h"
|
||||
#include "Gem/Settings.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# define close _close
|
||||
typedef unsigned __int8 uint8_t;
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Utils/GemString.h"
|
||||
|
||||
std::string TextBase::DEFAULT_FONT = "vera.ttf";
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// TextBase
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef FTGL
|
||||
TextBase :: TextBase(int argc, t_atom *argv)
|
||||
:
|
||||
m_dist(1), m_valid(0), m_fontSize(20), m_fontDepth(20), m_precision(1.f),
|
||||
m_widthJus(CENTER), m_heightJus(MIDDLE), m_depthJus(HALFWAY),
|
||||
m_inlet(NULL),
|
||||
m_font(NULL), m_fontname(NULL)
|
||||
{
|
||||
// initial text
|
||||
gem::Settings::get("font.face", DEFAULT_FONT);
|
||||
gem::Settings::get("font.size", m_fontSize);
|
||||
|
||||
|
||||
m_theText.push_back(L"gem");
|
||||
makeLineDist();
|
||||
if(argc)textMess(argc, argv);
|
||||
|
||||
m_inlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("ft1"));
|
||||
}
|
||||
|
||||
void TextBase :: startRendering(void) {
|
||||
if(NULL==m_font) {
|
||||
if(m_fontname)
|
||||
fontNameMess(m_fontname->s_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// render
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: renderLine(const char*line, float dist) {
|
||||
float x1=0, y1=0, z1=0, x2=0, y2=0, z2=0;
|
||||
#if 0
|
||||
startpost("renderline: "); {
|
||||
const char*c=line;
|
||||
while(c) {
|
||||
startpost("%c (%x)", c, c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_font->BBox(line, x1, y1, z1, x2, y2, z2); // FTGL
|
||||
|
||||
glPushMatrix();
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
justifyFont(x1, y1, z1, x2, y2, z2, dist);
|
||||
m_font->Render(line);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void TextBase :: renderLine(const wchar_t*line, float dist) {
|
||||
float x1=0, y1=0, z1=0, x2=0, y2=0, z2=0;
|
||||
m_font->BBox(line, x1, y1, z1, x2, y2, z2); // FTGL
|
||||
|
||||
glPushMatrix();
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
justifyFont(x1, y1, z1, x2, y2, z2, dist);
|
||||
m_font->Render(line);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void TextBase :: render(GemState *)
|
||||
{
|
||||
unsigned int i=0;
|
||||
if (m_theText.empty() || !m_font)return;
|
||||
// step through the lines
|
||||
for(i=0; i<m_theText.size(); i++)
|
||||
{
|
||||
renderLine(m_theText[i].c_str(), m_lineDist[i]*m_fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// setFontSize
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
void TextBase :: setFontSize(float size){
|
||||
m_fontSize = size;
|
||||
if (!m_font)return;
|
||||
if (! m_font->FaceSize(static_cast<int>(m_fontSize)) ) {
|
||||
error("unable to set fontsize !");
|
||||
}
|
||||
setModified();
|
||||
}
|
||||
////////////////////////////////////////////////////////
|
||||
// setPrecision
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
void TextBase :: setPrecision(float prec)
|
||||
{
|
||||
m_precision = prec;
|
||||
error("no settable precision for FTGL !");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// fontNameMess
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
void TextBase :: fontNameMess(const std::string filename){
|
||||
m_valid = 0;
|
||||
const char *bufptr=NULL;
|
||||
int fd=-1;
|
||||
|
||||
if(filename.empty()){
|
||||
error("no font-file specified");
|
||||
return;
|
||||
}
|
||||
std::string fn = findFile(filename);
|
||||
bufptr=fn.c_str();
|
||||
|
||||
/* try to open the file */
|
||||
FILE*file = fopen(bufptr, "r");
|
||||
if (!file) {
|
||||
error("cannot find font-file '%s'", bufptr);
|
||||
return;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
/* now read font */
|
||||
if(m_font)delete m_font; m_font=NULL;
|
||||
if (makeFont(bufptr)==NULL){
|
||||
error("unable to open font '%s'", bufptr);
|
||||
return;
|
||||
}
|
||||
m_fontname=gensym(filename.c_str());
|
||||
|
||||
setFontSize(m_fontSize);
|
||||
m_font->Depth(m_fontDepth);
|
||||
m_font->CharMap(ft_encoding_unicode);
|
||||
|
||||
setModified();
|
||||
}
|
||||
|
||||
#else /* !FTGL */
|
||||
|
||||
TextBase :: TextBase(int argc, t_atom *argv){
|
||||
static bool first_time=true;
|
||||
if (first_time){
|
||||
post("Gem has been compiled without FONT-support !");
|
||||
first_time=false;
|
||||
}
|
||||
m_inlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("float"), gensym("ft1"));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setFontSize
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: setFontSize(float size)
|
||||
{}
|
||||
/////////////////////////////////////////////////////////
|
||||
// setPrecision
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: setPrecision(float prec)
|
||||
{}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fontNameMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: fontNameMess(const std::string s)
|
||||
{}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// render
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: render(GemState*)
|
||||
{/* a no-op */ }
|
||||
|
||||
#endif /* FTGL */
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
TextBase :: ~TextBase(){
|
||||
/* textbase deletion */
|
||||
if(m_inlet)inlet_free(m_inlet);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setJustification
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: setFontSize(){
|
||||
setFontSize(m_fontSize);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setJustification
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: setJustification(JustifyWidth wType, JustifyHeight hType, JustifyDepth dType){
|
||||
m_widthJus = wType;
|
||||
m_heightJus = hType;
|
||||
m_depthJus = dType;
|
||||
|
||||
makeLineDist();
|
||||
}
|
||||
void TextBase :: setJustification(JustifyWidth wType, JustifyHeight hType)
|
||||
{
|
||||
m_widthJus = wType;
|
||||
m_heightJus = hType;
|
||||
|
||||
makeLineDist();
|
||||
}
|
||||
void TextBase :: setJustification(JustifyWidth wType)
|
||||
{
|
||||
m_widthJus = wType;
|
||||
}
|
||||
|
||||
void TextBase :: justifyFont(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2, float y_offset)
|
||||
{
|
||||
float width = 0.f;
|
||||
float height = 0.f;
|
||||
float depth = 0.f;
|
||||
|
||||
// Get ascender height (= height of the text)
|
||||
#ifdef FTGL
|
||||
float ascender = m_font->Ascender();
|
||||
#else
|
||||
// we don't have any ascender when not using FTGL
|
||||
float ascender = m_fontSize;
|
||||
#endif
|
||||
|
||||
if (m_widthJus == LEFT) width = x1;
|
||||
else if (m_widthJus == RIGHT) width = x2-x1;
|
||||
else if (m_widthJus == CENTER)width = x2 / 2.f;
|
||||
else if (m_widthJus == BASEW) width = 0;
|
||||
|
||||
// if (m_heightJus == BOTTOM) height = y1;
|
||||
// else if (m_heightJus == TOP) height = y2-y1;
|
||||
// else if (m_heightJus == MIDDLE)height = y2 / 2.f;
|
||||
// else if (m_heightJus == BASEH) height = 0;
|
||||
|
||||
if (m_heightJus == BOTTOM || m_heightJus == BASEH)
|
||||
height = y_offset;
|
||||
else if (m_heightJus == TOP) height = ascender + y_offset;
|
||||
else if (m_heightJus == MIDDLE)height = (ascender/2.f) + y_offset;
|
||||
|
||||
if (m_depthJus == FRONT) depth = z1;
|
||||
else if (m_depthJus == BACK) depth = z2-z1;
|
||||
else if (m_depthJus == HALFWAY)depth = z2 / 2.f;
|
||||
else if (m_depthJus == BASED) depth = 0;
|
||||
|
||||
glScalef(FONT_SCALE, FONT_SCALE, FONT_SCALE);
|
||||
glTranslatef(-width, -height, -depth);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// textMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: breakLine(wstring line)
|
||||
{
|
||||
// split the string wherever there is a '\n'
|
||||
while(line.length()>0){
|
||||
size_t pos=line.find('\n');
|
||||
|
||||
// if not found, we're done
|
||||
if(wstring::npos == pos)break;
|
||||
wstring lin=line.substr(0,pos);
|
||||
|
||||
m_theText.push_back(gem::string::getVisualLine(lin));
|
||||
line=line.erase(0,pos+1);
|
||||
}
|
||||
|
||||
// if there is still a text append it
|
||||
if(line.length()) {
|
||||
//m_theText.push_back(line);
|
||||
m_theText.push_back(gem::string::getVisualLine(line));
|
||||
}
|
||||
makeLineDist();
|
||||
setModified();
|
||||
}
|
||||
|
||||
void TextBase :: textMess(int argc, t_atom *argv)
|
||||
{
|
||||
m_theText.clear();
|
||||
if ( argc < 1 ) {return; }
|
||||
|
||||
wstring line = L"";
|
||||
int i=0;
|
||||
|
||||
// convert the atom-list into 1 string
|
||||
for (i = 0; i < argc; ++i)
|
||||
{
|
||||
string newtext;
|
||||
if (A_FLOAT == argv[i].a_type) {
|
||||
char str[MAXPDSTRING];
|
||||
char*sp=str;
|
||||
|
||||
atom_string(&argv[i], str, MAXPDSTRING);
|
||||
while(*sp) {
|
||||
unsigned char c=*sp++;
|
||||
line+=c;
|
||||
}
|
||||
} else {
|
||||
char*sp=atom_getsymbol(&argv[i])->s_name;
|
||||
try {
|
||||
std::wstring ws=gem::string::toWstring(sp);
|
||||
line+=ws;
|
||||
} catch (int i) {
|
||||
i=0;
|
||||
while(*sp) {
|
||||
unsigned char c=*sp++;
|
||||
line+=c;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(argc-1>i)line += L' ';
|
||||
}
|
||||
|
||||
breakLine(line);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// line distance, the offset
|
||||
// of the individual lines
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: makeLineDist()
|
||||
{
|
||||
unsigned int i=0;
|
||||
m_lineDist.clear();
|
||||
if (m_heightJus == BOTTOM || m_heightJus == BASEH)
|
||||
{
|
||||
// so the offset will be a simple
|
||||
// [0 1 2 3 ... n] sequence
|
||||
for(i=0; i<m_theText.size(); i++)
|
||||
m_lineDist.push_back(i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_heightJus == TOP)
|
||||
{
|
||||
// now in the other direction:
|
||||
// [-n ... -2 -1 0]
|
||||
signed long j;
|
||||
for(j=m_theText.size()-1; j>=0; j--){
|
||||
m_lineDist.push_back(-j);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// else:
|
||||
// calculate the y offset of each line, so
|
||||
// that the text will be centered:
|
||||
/*lines y-offset calculation
|
||||
1: 0 = 0- 0
|
||||
2: -0.5 0.5 = [0 1] - 0.5
|
||||
3: -1 0 1 = [0 1 2] - 1
|
||||
4: -1.5 -0.5 0.5 1.5 = [0 1 2 3] - 1.5
|
||||
5: -2 -1 0 1 2 = [0 1 2 3 4] - 2
|
||||
...
|
||||
*/
|
||||
|
||||
float diff = (m_theText.size()-1)*0.5;
|
||||
for(i=0; i<m_theText.size(); i++)
|
||||
m_lineDist.push_back((i-diff)*m_dist);
|
||||
}
|
||||
|
||||
|
||||
//-- moocow: modified version of "textMess" for float lists
|
||||
// this can be used with moocow's pd-string external
|
||||
// available at http://www.ling.uni-potsdam.de/~moocow/projects/pd/#externs
|
||||
// it works like this: a string is represented as a list of ASCII-values
|
||||
/////////////////////////////////////////////////////////
|
||||
// stringMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: stringMess(int argc, t_atom *argv)
|
||||
{
|
||||
m_theText.clear();
|
||||
|
||||
if ( argc < 1 ) { return; }
|
||||
|
||||
int i;
|
||||
wstring line = L"";
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
int v=atom_getint(argv+i);
|
||||
/*
|
||||
* i experienced crashes in FTGL with indices>65535;
|
||||
* since TrueType fonts cannot hold more than 65536 entries
|
||||
* we just clamp it...
|
||||
* note: at least wikipedia claims that TTF can only hold 2^16 glyphs
|
||||
* i have seen ttf-fonts with (seemingly) more
|
||||
*/
|
||||
if(v<0||v>65535) {
|
||||
verbose(1, "invalid character %d: using ' ' instead", v);
|
||||
v=32;
|
||||
}
|
||||
line += static_cast<wchar_t>(v);
|
||||
}
|
||||
//line += L'\0';
|
||||
|
||||
breakLine(line);
|
||||
}
|
||||
//-- /moocow
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void TextBase :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG(classPtr, "list", textMess);
|
||||
CPPEXTERN_MSG(classPtr, "text", textMess);
|
||||
|
||||
//-- moocow
|
||||
CPPEXTERN_MSG(classPtr, "string", stringMess);
|
||||
//-- /moocow
|
||||
|
||||
CPPEXTERN_MSG1(classPtr, "font", fontNameMess, std::string);
|
||||
CPPEXTERN_MSG1(classPtr, "ft1", setFontSize, float);
|
||||
CPPEXTERN_MSG1(classPtr, "precision", setPrecision, float);
|
||||
CPPEXTERN_MSG1(classPtr, "linedist", linedistMess, float);
|
||||
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&TextBase::justifyMessCallback),
|
||||
gensym("justify"), A_GIMME, A_NULL);
|
||||
}
|
||||
|
||||
void TextBase :: justifyMessCallback(void *data, t_symbol *s, int argc, t_atom*argv)
|
||||
{
|
||||
JustifyWidth wType=CENTER;
|
||||
JustifyHeight hType=MIDDLE;
|
||||
JustifyDepth dType=HALFWAY;
|
||||
char c;
|
||||
|
||||
switch(argc){
|
||||
case 3:
|
||||
c=atom_getsymbol(argv+2)->s_name[2];
|
||||
switch (c){
|
||||
case 'o': case 'O': dType = FRONT; break;
|
||||
case 'c': case 'C': dType = BACK; break;
|
||||
case 's': case 'S': dType = BASED; break;
|
||||
case 'l': case 'L': case 'n': case 'N': dType = HALFWAY; break;
|
||||
default:
|
||||
GetMyClass(data)->error("invalid depth justification: %s (must be: front|back|halfway|base)",
|
||||
atom_getsymbol(argv+2)->s_name);
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
c=atom_getsymbol(argv+1)->s_name[2];
|
||||
switch (c){
|
||||
case 't': case 'T': hType = BOTTOM; break;
|
||||
case 'p': case 'P': hType = TOP; break;
|
||||
case 'd': case 'D': case 'n': case 'N': hType = MIDDLE; break;
|
||||
case 's': case 'S': hType = BASEH; break;
|
||||
default:
|
||||
GetMyClass(data)->error("invalid height justification: %s (must be bottom|top|middle|base)",
|
||||
atom_getsymbol(argv+1)->s_name);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
c=atom_getsymbol(argv)->s_name[2];
|
||||
switch (c){
|
||||
case 'f': case 'F': wType = LEFT; break;
|
||||
case 'g': case 'G': wType = RIGHT; break;
|
||||
case 'n': case 'N': wType = CENTER; break;
|
||||
case 's': case 'S': wType = BASEW; break;
|
||||
default:
|
||||
GetMyClass(data)->error("invalid width justification: %s (must be left|right|center|base)",
|
||||
atom_getsymbol(argv+0)->s_name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("justification most be \"width [height [depth]]\"");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(argc){
|
||||
case 1: GetMyClass(data)->setJustification(wType); break;
|
||||
case 2: GetMyClass(data)->setJustification(wType, hType); break;
|
||||
case 3: GetMyClass(data)->setJustification(wType, hType, dType); break;
|
||||
}
|
||||
}
|
||||
void TextBase :: linedistMess(float dist)
|
||||
{
|
||||
m_dist = dist;
|
||||
makeLineDist();
|
||||
}
|
||||
227
Gem/src/Base/TextBase.h
Normal file
227
Gem/src/Base/TextBase.h
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
A text
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
Copyright (c) 2005 Georg Holzmann <grh@mur.at>
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_BASE_TEXTBASE_H_
|
||||
#define _INCLUDE__GEM_BASE_TEXTBASE_H_
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning( disable : 4786 )
|
||||
# pragma warning( disable : 4788 )
|
||||
#endif
|
||||
|
||||
#include "Gem/GemConfig.h"
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifdef FTGL
|
||||
# define FONT_SCALE 0.2/3.0
|
||||
# ifdef HAVE_FTGL_FTGL_H
|
||||
# include "FTGL/ftgl.h"
|
||||
# else
|
||||
# include "FTFont.h"
|
||||
# endif
|
||||
#else
|
||||
# define FONT_SCALE 1.0
|
||||
#endif
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
TextBase
|
||||
|
||||
Base class for text objects
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"ft1" - The font size
|
||||
"text" - The text to draw
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN TextBase : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(TextBase, GemBase);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor with args
|
||||
TextBase(int argc, t_atom *argv);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~TextBase();
|
||||
|
||||
//////////
|
||||
// Do the rendering
|
||||
virtual void render(GemState*);
|
||||
|
||||
//////////
|
||||
// break a string according to '\n'
|
||||
virtual void breakLine(wstring line);
|
||||
|
||||
//-- moocow
|
||||
//////////
|
||||
// Set the text string from an ASCII list
|
||||
virtual void stringMess(int argc, t_atom *argv);
|
||||
void stringMess(t_symbol*, int argc, t_atom*argv) { stringMess(argc, argv); }
|
||||
//-- /moocow
|
||||
|
||||
//////////
|
||||
// Set the text string
|
||||
virtual void textMess(int argc, t_atom *argv);
|
||||
void textMess(t_symbol*, int argc, t_atom*argv) { textMess(argc, argv); }
|
||||
|
||||
//////////
|
||||
// The font to use
|
||||
virtual void fontNameMess(const std::string filename);
|
||||
|
||||
//////////
|
||||
// set line distance
|
||||
virtual void linedistMess(float dist);
|
||||
|
||||
//////////
|
||||
// Set the font size
|
||||
virtual void setFontSize(float size);
|
||||
virtual void setFontSize();
|
||||
|
||||
//////////
|
||||
// Set the precision for rendering
|
||||
virtual void setPrecision(float prec);
|
||||
|
||||
//////////
|
||||
// The different types of justification
|
||||
enum JustifyWidth { LEFT, RIGHT, CENTER, BASEW };
|
||||
enum JustifyHeight { BOTTOM, TOP, MIDDLE, BASEH };
|
||||
enum JustifyDepth { FRONT, BACK, HALFWAY, BASED };
|
||||
|
||||
//////////
|
||||
// Set the justification
|
||||
virtual void setJustification(JustifyWidth wType);
|
||||
virtual void setJustification(JustifyWidth wType, JustifyHeight hType);
|
||||
virtual void setJustification(JustifyWidth wType, JustifyHeight hType, JustifyDepth dType);
|
||||
|
||||
//////////
|
||||
// do the justification
|
||||
// x1,...,z2 just defines the bounding box of the rendered string.
|
||||
// y_offset is the offset of the current line
|
||||
virtual void justifyFont(float x1, float y1, float z1,
|
||||
float x2, float y2, float z2, float y_offset=0);
|
||||
|
||||
|
||||
//-----------------------------------
|
||||
// GROUP: Member variables
|
||||
//-----------------------------------
|
||||
|
||||
//////////
|
||||
// The text to display
|
||||
// (one entry for each line)
|
||||
vector<wstring> m_theText;
|
||||
|
||||
//////////
|
||||
// distance between the lines
|
||||
// (1 = 1 line, 0.5 = 0.5 lines, ...)
|
||||
float m_dist;
|
||||
|
||||
///////////
|
||||
// vector with the offset
|
||||
// of the individual lines
|
||||
vector<float> m_lineDist;
|
||||
|
||||
//////////
|
||||
// Do we have a valid font?
|
||||
int m_valid;
|
||||
|
||||
//////////
|
||||
// The font fize
|
||||
float m_fontSize;
|
||||
|
||||
//////////
|
||||
// The font depth (only for extruded fonts)
|
||||
float m_fontDepth;
|
||||
|
||||
//////////
|
||||
// The rendering precision
|
||||
float m_precision;
|
||||
|
||||
//////////
|
||||
// The width justification
|
||||
JustifyWidth m_widthJus;
|
||||
|
||||
//////////
|
||||
// The height justification
|
||||
JustifyHeight m_heightJus;
|
||||
|
||||
//////////
|
||||
// The depth justification
|
||||
JustifyDepth m_depthJus;
|
||||
|
||||
//////////
|
||||
// The inlet
|
||||
t_inlet *m_inlet;
|
||||
|
||||
|
||||
//////////
|
||||
// The default font name
|
||||
static std::string DEFAULT_FONT;
|
||||
|
||||
//////////
|
||||
// The font structure
|
||||
#ifdef FTGL
|
||||
FTFont *m_font;
|
||||
/* this should delete (m_font) if it is notnull and recreate it.
|
||||
* a pointer to the new structure is returned (and is set to m_font).
|
||||
* if creation fails, the font is cleaned-up and NULL is returned
|
||||
*/
|
||||
virtual FTFont* makeFont(const char*fontname)=0;
|
||||
|
||||
/* this is just handy to reload a font */
|
||||
t_symbol* m_fontname;
|
||||
/* on starting to render, we reload the font, to make sure it is there
|
||||
* this rids us of having to reload the font by hand every time the rendering is restarted
|
||||
*/
|
||||
virtual void startRendering(void);
|
||||
|
||||
/* render one line of the text */
|
||||
virtual void renderLine(const char*line,float dist);
|
||||
virtual void renderLine(const wchar_t*line,float dist);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
///////////
|
||||
// helpers:
|
||||
|
||||
///////////
|
||||
// helper to make the
|
||||
// line distance vector
|
||||
void makeLineDist();
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void justifyMessCallback(void *data, t_symbol *, int, t_atom*);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
43
Gem/src/Controls/Makefile.am
Normal file
43
Gem/src/Controls/Makefile.am
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#####################################################################
|
||||
# Gem/Controls: objectclasses that control rendering
|
||||
#####################################################################
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src @GEM_CPPFLAGS@
|
||||
include ../check-sources.mk
|
||||
|
||||
noinst_LTLIBRARIES = libControls.la
|
||||
|
||||
libControls_la_CXXFLAGS =
|
||||
libControls_la_LIBADD =
|
||||
libControls_la_LDFLAGS =
|
||||
|
||||
# RTE flags
|
||||
libControls_la_CXXFLAGS += @GEM_RTE_CFLAGS@ @GEM_ARCH_CXXFLAGS@
|
||||
libControls_la_LIBADD += @GEM_RTE_LIBS@
|
||||
libControls_la_LDFLAGS += @GEM_ARCH_LDFLAGS@
|
||||
|
||||
libControls_la_SOURCES= \
|
||||
gemframebuffer.cpp \
|
||||
gemframebuffer.h \
|
||||
gemhead.cpp \
|
||||
gemhead.h \
|
||||
gemkeyboard.cpp \
|
||||
gemkeyboard.h \
|
||||
gemkeyname.cpp \
|
||||
gemkeyname.h \
|
||||
gemlist.cpp \
|
||||
gemlist.h \
|
||||
gemlist_info.cpp \
|
||||
gemlist_info.h \
|
||||
gemlist_matrix.cpp \
|
||||
gemlist_matrix.h \
|
||||
gemmouse.cpp \
|
||||
gemmouse.h \
|
||||
gemreceive.cpp \
|
||||
gemreceive.h \
|
||||
gemwin.cpp \
|
||||
gemwin.h \
|
||||
render_trigger.cpp \
|
||||
render_trigger.h
|
||||
|
||||
15
Gem/src/Controls/Makefile.am.template
Normal file
15
Gem/src/Controls/Makefile.am.template
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)
|
||||
|
||||
noinst_LTLIBRARIES = libControls.la
|
||||
|
||||
libControls_la_CXXFLAGS =
|
||||
libControls_la_LIBADD =
|
||||
|
||||
# RTE flags
|
||||
libControls_la_CXXFLAGS += @GEM_RTE_CFLAGS@
|
||||
libControls_la_LIBADD += @GEM_RTE_LIBS@
|
||||
|
||||
libControls_la_SOURCES= @SOURCES@
|
||||
|
||||
548
Gem/src/Controls/gemframebuffer.cpp
Normal file
548
Gem/src/Controls/gemframebuffer.cpp
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// tigital AT mac DOT com
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2005-2006 James Tittle II, tigital At mac DoT com
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemframebuffer.h"
|
||||
#include <string.h>
|
||||
#include "Gem/State.h"
|
||||
#include "Gem/GLStack.h"
|
||||
|
||||
CPPEXTERN_NEW_WITH_TWO_ARGS(gemframebuffer, t_symbol *, A_DEFSYMBOL, t_symbol *, A_DEFSYMBOL);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemframebuffer
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemframebuffer :: gemframebuffer(t_symbol *format, t_symbol *type)
|
||||
: m_haveinit(false), m_wantinit(false), m_frameBufferIndex(0), m_depthBufferIndex(0),
|
||||
m_offScreenID(0), m_texTarget(GL_TEXTURE_2D), m_texunit(0),
|
||||
m_width(256), m_height(256),
|
||||
m_rectangle(false),
|
||||
m_internalformat(GL_RGB8), m_format(GL_RGB), m_wantFormat(GL_RGB),
|
||||
m_type(GL_UNSIGNED_BYTE),
|
||||
m_outTexInfo(NULL)
|
||||
{
|
||||
// create an outlet to send out texture info:
|
||||
// - ID
|
||||
// - width & height
|
||||
// - format/type (ie. GL_TEXTURE_RECTANGLE or GL_TEXTURE_2D)
|
||||
// - anything else?
|
||||
if(!m_outTexInfo)
|
||||
m_outTexInfo = outlet_new(this->x_obj, 0);
|
||||
|
||||
m_FBOcolor[0] = 0.f;
|
||||
m_FBOcolor[1] = 0.f;
|
||||
m_FBOcolor[2] = 0.f;
|
||||
m_FBOcolor[3] = 0.f;
|
||||
|
||||
m_perspect[0] = -1.f;
|
||||
m_perspect[1] = 1.f;
|
||||
m_perspect[2] = -1.f;
|
||||
m_perspect[3] = 1.f;
|
||||
m_perspect[4] = 1.f;
|
||||
m_perspect[5] = 20.f;
|
||||
|
||||
|
||||
if(format && format->s_name && format!=gensym(""))
|
||||
formatMess(format->s_name);
|
||||
if(type && type->s_name && type !=gensym(""))
|
||||
typeMess(type->s_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemframebuffer :: ~gemframebuffer()
|
||||
{
|
||||
destroyFBO();
|
||||
outlet_free(m_outTexInfo);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// extension check
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool gemframebuffer :: isRunnable() {
|
||||
if(!GLEW_VERSION_1_3) {
|
||||
error("openGL version 1.3 needed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(GLEW_EXT_framebuffer_object) {
|
||||
m_wantinit=true;
|
||||
|
||||
/* check rectangle possibilities */
|
||||
m_canRectangle=GL_TEXTURE_2D;
|
||||
if(GLEW_ARB_texture_rectangle)
|
||||
m_canRectangle=GL_TEXTURE_RECTANGLE_ARB;
|
||||
else if (GLEW_EXT_texture_rectangle)
|
||||
m_canRectangle=GL_TEXTURE_RECTANGLE_EXT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
error("openGL framebuffer extension is not supported by this system");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// renderGL
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: render(GemState *state)
|
||||
{
|
||||
gem::GLStack*stacks=NULL;
|
||||
if(state) {
|
||||
state->get(GemState::_GL_STACKS, stacks);
|
||||
}
|
||||
|
||||
if(!m_width || !m_height) {
|
||||
error("width and height must be present!");
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0_ARB + m_texunit);
|
||||
|
||||
if (m_wantinit)
|
||||
initFBO();
|
||||
|
||||
// store the window viewport dimensions so we can reset them,
|
||||
// and set the viewport to the dimensions of our texture
|
||||
glGetIntegerv(GL_VIEWPORT, m_vp);
|
||||
glGetFloatv( GL_COLOR_CLEAR_VALUE, m_color );
|
||||
|
||||
glBindTexture( m_texTarget, 0 );
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_frameBufferIndex);
|
||||
// Bind the texture to the frame buffer.
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
m_texTarget, m_offScreenID, 0);
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, m_depthBufferIndex);
|
||||
|
||||
// debug yellow color
|
||||
// glClearColor( 1,1,0,0);
|
||||
glClearColor( m_FBOcolor[0], m_FBOcolor[1], m_FBOcolor[2], m_FBOcolor[3] );
|
||||
|
||||
// Clear the buffers and reset the model view matrix.
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// We need a one-to-one mapping of pixels to texels in order to
|
||||
// ensure every element of our texture is processed. By setting our
|
||||
// viewport to the dimensions of our destination texture and drawing
|
||||
// a screen-sized quad (see below), we ensure that every pixel of our
|
||||
// texel is generated and processed in the fragment program.
|
||||
glViewport(0,0, m_width, m_height);
|
||||
|
||||
if(stacks) stacks->push(gem::GLStack::PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum( m_perspect[0], m_perspect[1], m_perspect[2], m_perspect[3], m_perspect[4], m_perspect[5]);
|
||||
|
||||
if(stacks) stacks->push(gem::GLStack::MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// postRender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: postrender(GemState *state)
|
||||
{
|
||||
t_float w, h;
|
||||
gem::GLStack*stacks=NULL;
|
||||
if(state) {
|
||||
state->get(GemState::_GL_STACKS, stacks);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0_ARB + m_texunit);
|
||||
|
||||
if(m_texTarget== GL_TEXTURE_2D) {
|
||||
w=1.f;
|
||||
h=1.f;
|
||||
} else {
|
||||
w=static_cast<t_float>(m_width);
|
||||
h=static_cast<t_float>(m_height);
|
||||
}
|
||||
|
||||
// GPGPU CONCEPT 4: Viewport-Sized Quad = Data Stream Generator.
|
||||
// In order to execute fragment programs, we need to generate pixels.
|
||||
// Drawing a quad the size of our viewport (see above) generates a
|
||||
// fragment for every pixel of our destination texture. Each fragment
|
||||
// is processed identically by the fragment program. Notice that in
|
||||
// the reshape() function, below, we have set the frustum to
|
||||
// orthographic, and the frustum dimensions to [-1,1]. Thus, our
|
||||
// viewport-sized quad vertices are at [-1,-1], [1,-1], [1,1], and
|
||||
// [-1,1]: the corners of the viewport.
|
||||
|
||||
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
|
||||
glBindTexture( m_texTarget, m_offScreenID );
|
||||
|
||||
if(stacks) stacks->pop(gem::GLStack::PROJECTION);
|
||||
if(stacks) stacks->pop(gem::GLStack::MODELVIEW);
|
||||
|
||||
// reset to visible window's clear color
|
||||
glClearColor( m_color[0], m_color[1], m_color[2], m_color[3] );
|
||||
// reset to original viewport dimensions
|
||||
glViewport( m_vp[0], m_vp[1], m_vp[2], m_vp[3] );
|
||||
// now that the render is done,
|
||||
|
||||
// send textureID, w, h, textureTarget to outlet
|
||||
t_atom ap[5];
|
||||
SETFLOAT(ap+0, static_cast<t_float>(m_offScreenID));
|
||||
SETFLOAT(ap+1, w);
|
||||
SETFLOAT(ap+2, h);
|
||||
SETFLOAT(ap+3, m_texTarget);
|
||||
SETFLOAT(ap+4, static_cast<t_float>(0.));
|
||||
outlet_list(m_outTexInfo, 0, 5, ap);
|
||||
}
|
||||
|
||||
void gemframebuffer :: printInfo()
|
||||
{
|
||||
std::string format, internalformat;
|
||||
switch(m_format) {
|
||||
case GL_YUV422_GEM: format="YUV"; break;
|
||||
case GL_RGB: format="RGB"; break;
|
||||
case GL_RGBA: format="RGBA"; break;
|
||||
case GL_BGRA: format="BGRA"; break;
|
||||
case GL_RGB_FLOAT32_ATI: format="RGB32"; break;
|
||||
default: format="<unknown>";
|
||||
}
|
||||
switch(m_internalformat) {
|
||||
case GL_YUV422_GEM: internalformat="YUV"; break;
|
||||
case GL_RGB: internalformat="RGB"; break;
|
||||
case GL_RGBA: internalformat="RGBA"; break;
|
||||
case GL_BGRA: internalformat="BGRA"; break;
|
||||
case GL_RGB_FLOAT32_ATI: internalformat="RGB32"; break;
|
||||
default: internalformat="<unknown>";
|
||||
}
|
||||
std::string rectangle;
|
||||
int rect=(m_rectangle?m_canRectangle:GL_TEXTURE_2D);
|
||||
if(GL_TEXTURE_2D==rect) rectangle="2D";
|
||||
else if(GL_TEXTURE_RECTANGLE_ARB==rect)rectangle="RECTANGLE(ARB)";
|
||||
else if(GL_TEXTURE_RECTANGLE_EXT==rect)rectangle="RECTANGLE(EXT)";
|
||||
|
||||
|
||||
std::string type;
|
||||
switch(m_type) {
|
||||
case GL_UNSIGNED_BYTE: type="BYTE"; break;
|
||||
case GL_FLOAT : type="FLOAT"; break;
|
||||
default : type="unknown";
|
||||
}
|
||||
|
||||
verbose(0, "size: %dx%d", m_width, m_height);
|
||||
verbose(0, "rectangle: %d -> %s", m_rectangle, rectangle.c_str());
|
||||
verbose(0, "format: %s/%s [%d/%d]", format.c_str(), internalformat.c_str(), m_format, m_internalformat);
|
||||
verbose(0, "type: %s [%d]", type.c_str(), m_type);
|
||||
verbose(0, "texunit: %d", m_texunit);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// initFBO
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: initFBO()
|
||||
{
|
||||
// clean up any existing FBO before creating a new one
|
||||
if(m_haveinit)
|
||||
destroyFBO();
|
||||
|
||||
m_texTarget = (m_rectangle?m_canRectangle:GL_TEXTURE_2D);
|
||||
/* check supported formats */
|
||||
fixFormat(m_wantFormat);
|
||||
|
||||
// Generate frame buffer object then bind it.
|
||||
glGenFramebuffersEXT(1, &m_frameBufferIndex);
|
||||
glGenRenderbuffersEXT(1, &m_depthBufferIndex);
|
||||
|
||||
// Create the texture we will be using to render to.
|
||||
glGenTextures(1, &m_offScreenID);
|
||||
glBindTexture(m_texTarget, m_offScreenID);
|
||||
|
||||
glTexImage2D( m_texTarget, 0, m_internalformat, m_width, m_height, 0, m_format, m_type, NULL );
|
||||
// 2.13.2006
|
||||
// GL_LINEAR causes fallback to software shader
|
||||
// so switching back to GL_NEAREST
|
||||
glTexParameteri(m_texTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(m_texTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
GLuint wrapmode = (GLEW_EXT_texture_edge_clamp)?GL_CLAMP_TO_EDGE:GL_CLAMP;
|
||||
|
||||
glTexParameterf(m_texTarget, GL_TEXTURE_WRAP_S, wrapmode);
|
||||
glTexParameterf(m_texTarget, GL_TEXTURE_WRAP_T, wrapmode);
|
||||
|
||||
// Initialize the render buffer.
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBufferIndex);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height);
|
||||
|
||||
// Make sure we have not errors.
|
||||
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT) ;
|
||||
if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
|
||||
{
|
||||
switch(status) {
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
|
||||
error("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
error("GL_FRAMEBUFFER_UNSUPPORTED_EXT");
|
||||
break;
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
|
||||
error("GL_INVALID_FRAMEBUFFER_OPERATION_EXT");
|
||||
break;
|
||||
default:
|
||||
error("Unknown ERROR %d", status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Return out of the frame buffer.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
m_haveinit = true;
|
||||
m_wantinit = false;
|
||||
|
||||
printInfo();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// destroyFBO
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: destroyFBO()
|
||||
{
|
||||
if(!GLEW_EXT_framebuffer_object)
|
||||
return;
|
||||
// Release all resources.
|
||||
if(m_depthBufferIndex) glDeleteRenderbuffersEXT(1, &m_depthBufferIndex);
|
||||
if(m_frameBufferIndex) glDeleteFramebuffersEXT(1, &m_frameBufferIndex);
|
||||
if(m_offScreenID) glDeleteTextures(1, &m_offScreenID);
|
||||
|
||||
m_haveinit = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// bangMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: bangMess()
|
||||
{
|
||||
error("'bang' message not implemented");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// startRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: startRendering()
|
||||
{
|
||||
m_wantinit = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// stopRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: stopRendering()
|
||||
{
|
||||
destroyFBO();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// dimMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: dimMess(int width, int height)
|
||||
{
|
||||
if (width != m_width || height != m_height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
setModified();
|
||||
}
|
||||
}
|
||||
|
||||
void gemframebuffer :: colorMess(t_symbol*s,int argc, t_atom*argv)
|
||||
{
|
||||
float red=1., green=1., blue=1., alpha=1.;
|
||||
switch(argc) {
|
||||
case (4):
|
||||
alpha=atom_getfloat(argv+3);
|
||||
case (3):
|
||||
red =atom_getfloat(argv+0);
|
||||
green=atom_getfloat(argv+1);
|
||||
blue =atom_getfloat(argv+2);
|
||||
break;
|
||||
default:
|
||||
error("'color' message takes 3 (RGB) or 4 (RGBA) values");
|
||||
return;
|
||||
}
|
||||
|
||||
m_FBOcolor[0] = red;
|
||||
m_FBOcolor[1] = green;
|
||||
m_FBOcolor[2] = blue;
|
||||
m_FBOcolor[3] = alpha;
|
||||
|
||||
// setModified();
|
||||
}
|
||||
|
||||
void gemframebuffer :: perspectiveMess(t_symbol*s,int argc, t_atom*argv)
|
||||
{
|
||||
switch(argc){
|
||||
case 6:
|
||||
m_perspect[0]=atom_getfloat(argv);
|
||||
m_perspect[1]=atom_getfloat(argv+1);
|
||||
m_perspect[2]=atom_getfloat(argv+2);
|
||||
m_perspect[3]=atom_getfloat(argv+3);
|
||||
m_perspect[4]=atom_getfloat(argv+4);
|
||||
m_perspect[5]=atom_getfloat(argv+5);
|
||||
|
||||
// setModified();
|
||||
break;
|
||||
default:
|
||||
error("\"perspec\" expects 6 values for frustum - left, right, bottom, top, near, far");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* needs to be called with a valid context */
|
||||
void gemframebuffer :: fixFormat(GLenum wantFormat)
|
||||
{
|
||||
m_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
if(wantFormat == GL_RGB_FLOAT32_ATI && !GLEW_ATI_texture_float) {
|
||||
wantFormat = GL_RGB;
|
||||
}
|
||||
|
||||
switch(wantFormat) {
|
||||
default:
|
||||
verbose(1,"using default format");
|
||||
case GL_RGB:
|
||||
m_internalformat=m_format=GL_RGB;
|
||||
break;
|
||||
case GL_RGB_FLOAT32_ATI:
|
||||
m_internalformat = GL_RGB_FLOAT32_ATI;
|
||||
m_format = GL_RGB;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
m_internalformat = GL_RGBA;
|
||||
m_format = GL_RGBA;
|
||||
break;
|
||||
case GL_YUV422_GEM:
|
||||
m_format=GL_YUV422_GEM;
|
||||
m_internalformat=GL_RGB8;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
switch(wantFormat) {
|
||||
case GL_RGB_FLOAT32_ATI:
|
||||
m_format = GL_BGR;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
m_format = GL_BGRA;
|
||||
break;
|
||||
case GL_YUV422_GEM:
|
||||
m_type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void gemframebuffer :: formatMess(std::string format)
|
||||
{
|
||||
GLenum tmp_format=0;
|
||||
if("YUV"==format) {
|
||||
tmp_format = GL_YUV422_GEM;
|
||||
} else if ("RGB"==format) {
|
||||
tmp_format = GL_RGB;
|
||||
} else if ("RGBA"==format) {
|
||||
tmp_format = GL_RGBA;
|
||||
} else if ("RGB32"==format) {
|
||||
tmp_format = GL_RGB_FLOAT32_ATI;
|
||||
}
|
||||
|
||||
if(tmp_format)
|
||||
m_wantFormat=tmp_format;
|
||||
setModified();
|
||||
}
|
||||
|
||||
void gemframebuffer :: typeMess(std::string type)
|
||||
{
|
||||
if("FLOAT"==type) {
|
||||
m_type = GL_FLOAT;
|
||||
} else {
|
||||
type="BYTE";
|
||||
m_type=GL_UNSIGNED_BYTE;
|
||||
}
|
||||
// changed type, so we need to rebuild the FBO
|
||||
setModified();
|
||||
}
|
||||
|
||||
void gemframebuffer :: rectangleMess(bool rectangle)
|
||||
{
|
||||
m_rectangle=rectangle;
|
||||
setModified();
|
||||
}
|
||||
void gemframebuffer :: texunitMess(int unit) {
|
||||
m_texunit=static_cast<GLuint>(unit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
void gemframebuffer :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG0(classPtr, "bang", bangMess);
|
||||
CPPEXTERN_MSG (classPtr, "color", colorMess);
|
||||
CPPEXTERN_MSG (classPtr, "perspec", perspectiveMess);
|
||||
CPPEXTERN_MSG2(classPtr, "dimen", dimMess, int, int);
|
||||
CPPEXTERN_MSG1(classPtr, "format", formatMess, std::string);
|
||||
CPPEXTERN_MSG1(classPtr, "type", typeMess, std::string);
|
||||
CPPEXTERN_MSG1(classPtr, "rectangle", rectangleMess, bool);
|
||||
CPPEXTERN_MSG1(classPtr, "texunit", texunitMess, int);
|
||||
|
||||
/* legacy */
|
||||
CPPEXTERN_MSG2(classPtr, "dim", dimMess, int, int);
|
||||
CPPEXTERN_MSG1(classPtr, "mode", rectangleMess, bool);
|
||||
}
|
||||
107
Gem/src/Controls/gemframebuffer.h
Normal file
107
Gem/src/Controls/gemframebuffer.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
render to offscreen buffer and make texture
|
||||
|
||||
created 11/27/2005
|
||||
|
||||
Copyright (c) 2005-2006 James Tittle II, tigital AT mac DOT com
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMFRAMEBUFFER_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMFRAMEBUFFER_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
#include <iostream>
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemframebuffer
|
||||
|
||||
render to offscreen buffer and make texture
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"bang" - sends out a state list
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemframebuffer : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(gemframebuffer, GemBase);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemframebuffer(t_symbol *format, t_symbol *type);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
~gemframebuffer(void);
|
||||
|
||||
//////////
|
||||
// A render message
|
||||
void render(GemState *state);
|
||||
void postrender(GemState *state);
|
||||
void initFBO(void);
|
||||
void destroyFBO(void);
|
||||
|
||||
//////////
|
||||
// Set up the modifying flags
|
||||
void startRendering(void);
|
||||
//////////
|
||||
// Clean up the modifying flags
|
||||
void stopRendering(void);
|
||||
|
||||
// extension checks
|
||||
virtual bool isRunnable(void);
|
||||
|
||||
//////////
|
||||
// change the size dimensions
|
||||
void dimMess(int width, int height);
|
||||
|
||||
//////////
|
||||
// format-message
|
||||
virtual void formatMess(std::string);
|
||||
virtual void typeMess(std::string);
|
||||
|
||||
virtual void colorMess(t_symbol*,int argc, t_atom*argv);
|
||||
virtual void perspectiveMess(t_symbol*,int argc, t_atom*argv);
|
||||
|
||||
virtual void rectangleMess(bool mode);
|
||||
virtual void texunitMess(int mode);
|
||||
|
||||
virtual void fixFormat(GLenum wantedFormat);
|
||||
virtual void printInfo(void);
|
||||
|
||||
private:
|
||||
GLboolean m_haveinit, m_wantinit;
|
||||
GLuint m_frameBufferIndex;
|
||||
GLuint m_depthBufferIndex;
|
||||
GLuint m_offScreenID;
|
||||
GLuint m_texTarget;
|
||||
GLuint m_texunit;
|
||||
int m_width, m_height;
|
||||
bool m_rectangle; // 1=TEXTURE_RECTANGLE_EXT, 0=TEXTURE_2D
|
||||
GLenum m_canRectangle; // whichever rectangle formats are supported
|
||||
int m_internalformat;
|
||||
int m_format;
|
||||
GLenum m_wantFormat;
|
||||
int m_type;
|
||||
GLint m_vp[4];
|
||||
GLfloat m_color[4];
|
||||
GLfloat m_FBOcolor[4];
|
||||
t_outlet *m_outTexInfo;
|
||||
GLfloat m_perspect[6];
|
||||
|
||||
void bangMess(void);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
284
Gem/src/Controls/gemhead.cpp
Normal file
284
Gem/src/Controls/gemhead.cpp
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemhead.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include "Gem/Manager.h"
|
||||
#include "Gem/State.h"
|
||||
#include "Gem/Cache.h"
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
#include "Gem/GLStack.h"
|
||||
#include "Gem/Exception.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _MSC_VER /* This is only for Microsoft's compiler, not cygwin, e.g. */
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
CPPEXTERN_NEW_WITH_GIMME(gemhead);
|
||||
|
||||
|
||||
static std::string float2str(t_float v) {
|
||||
std::string s;
|
||||
char buf[1000];
|
||||
snprintf(buf, 1000, "%g", v);
|
||||
s=buf;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemhead
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemhead :: gemhead(int argc, t_atom*argv) :
|
||||
gemreceive(gensym("__gem_render")),
|
||||
m_cache(new GemCache(this)), m_renderOn(1)
|
||||
{
|
||||
if(m_fltin)inlet_free(m_fltin); m_fltin=NULL;
|
||||
|
||||
m_basename=m_name->s_name;
|
||||
float priority=50.;
|
||||
#if 1
|
||||
switch(argc) {
|
||||
case 2:
|
||||
if(argv[0].a_type == A_FLOAT && argv[1].a_type == A_SYMBOL) {
|
||||
priority=atom_getfloat(argv+0);
|
||||
m_basename+=atom_getsymbol(argv+1)->s_name;
|
||||
} else if(argv[1].a_type == A_FLOAT && argv[0].a_type == A_SYMBOL) {
|
||||
priority=atom_getfloat(argv+1);
|
||||
m_basename+=atom_getsymbol(argv+0)->s_name;
|
||||
} else if(argv[1].a_type == A_FLOAT && argv[0].a_type == A_FLOAT) {
|
||||
priority=atom_getfloat(argv+0);
|
||||
m_basename+=::float2str(atom_getfloat (argv+1));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(argv[0].a_type == A_FLOAT) {
|
||||
priority=atom_getfloat(argv+0);
|
||||
} else if(argv[0].a_type == A_SYMBOL) {
|
||||
m_basename+=atom_getsymbol(argv+0)->s_name;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
priority=50.f;
|
||||
break;
|
||||
default:
|
||||
throw(GemException("invalid arguments: 'gemhead [<priority> [<basereceivename>]]'"));
|
||||
}
|
||||
#else
|
||||
if(argc==0)
|
||||
priority=50.;
|
||||
else if(argv[0].a_type == A_FLOAT) {
|
||||
priority=atom_getfloat(argv);
|
||||
} else
|
||||
throw(GemException("invalid arguments: 'gemhead [<priority>]'"));
|
||||
#endif
|
||||
m_priority=priority+1;
|
||||
setMess(priority);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemhead :: ~gemhead()
|
||||
{
|
||||
if (m_cache)
|
||||
stopRendering();
|
||||
if(m_cache)delete m_cache;
|
||||
m_cache=NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// renderGL
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: renderGL(GemState *state)
|
||||
{
|
||||
static const GLfloat a_color[]={0.2,0.2,0.2,1};
|
||||
static const GLfloat d_color[]={0.8,0.8,0.8,1};
|
||||
static const GLfloat e_color[]={0.0,0.0,0.0,1};
|
||||
static const GLfloat s_color[]={0.0,0.0,0.0,1};
|
||||
static const GLfloat shininess[]={0.0};
|
||||
|
||||
if (!m_cache || !m_renderOn) return;
|
||||
|
||||
// set the default color and transformation matrix
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, a_color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, d_color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, e_color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, s_color);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
|
||||
|
||||
gem::GLStack*stacks=NULL;
|
||||
if(state)
|
||||
{
|
||||
state->reset();
|
||||
// set the state dirty flag
|
||||
state->set(GemState::_DIRTY, m_cache->dirty);
|
||||
state->VertexDirty=m_cache->vertexDirty;
|
||||
|
||||
state->get(GemState::_GL_STACKS, stacks);
|
||||
if(stacks)stacks->push();
|
||||
}
|
||||
|
||||
// are we profiling and need to send new images?
|
||||
if (GemMan::getProfileLevel() >= 2)
|
||||
m_cache->resendImage = 1;
|
||||
|
||||
t_atom ap[2];
|
||||
ap->a_type=A_POINTER;
|
||||
ap->a_w.w_gpointer=reinterpret_cast<t_gpointer*>(m_cache); // the cache ?
|
||||
(ap+1)->a_type=A_POINTER;
|
||||
(ap+1)->a_w.w_gpointer=reinterpret_cast<t_gpointer*>(state);
|
||||
outlet_anything(this->m_outlet, gensym("gem_state"), 2, ap);
|
||||
|
||||
m_cache->dirty = false;
|
||||
m_cache->vertexDirty=false;
|
||||
state->get(GemState::_GL_STACKS, stacks);
|
||||
if(stacks)stacks->pop();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// bangMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: bangMess()
|
||||
{
|
||||
int renderon = m_renderOn;
|
||||
// make sure that the window and the cache exist
|
||||
if ( !GemMan::windowExists() || !m_cache )
|
||||
return;
|
||||
|
||||
// make a dummy GemState
|
||||
GemState tempState;
|
||||
GemMan::fillGemState(tempState);
|
||||
|
||||
m_renderOn = 1;
|
||||
renderGL(&tempState);
|
||||
m_renderOn = renderon;
|
||||
glFlush();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// renderOnOff
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: renderOnOff(int state)
|
||||
{
|
||||
m_renderOn = state;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// setPriority
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: setMess(t_float priority)
|
||||
{
|
||||
if (0.==priority)priority=50.;
|
||||
|
||||
if(priority==m_priority)
|
||||
return;
|
||||
|
||||
m_priority=priority;
|
||||
|
||||
std::string rcv=m_basename;
|
||||
if(priority<0.f)
|
||||
rcv=m_basename+"_osd";
|
||||
|
||||
gemreceive::priorityMess(priority);
|
||||
gemreceive::nameMess(rcv);
|
||||
}
|
||||
|
||||
void gemhead :: receive(t_symbol*s, int argc, t_atom*argv) {
|
||||
if(m_renderOn && gensym("gem_state")==s) {
|
||||
if(1==argc && A_FLOAT==argv->a_type) {
|
||||
int i=atom_getint(argv);
|
||||
switch(i) {
|
||||
case 0:
|
||||
stopRendering();
|
||||
break;
|
||||
default:
|
||||
startRendering();
|
||||
}
|
||||
} else if (2==argc && A_POINTER==argv[0].a_type && A_POINTER==argv[1].a_type) {
|
||||
GemCache*cache=reinterpret_cast<GemCache*>(argv[0].a_w.w_gpointer);
|
||||
GemState*state=reinterpret_cast<GemState*>(argv[1].a_w.w_gpointer);
|
||||
renderGL(state);
|
||||
}
|
||||
} else {
|
||||
// not for us...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// outputRenderOnOff
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: outputRenderOnOff(int state)
|
||||
{
|
||||
// continue sending out the cache message
|
||||
t_atom ap[1];
|
||||
SETFLOAT(ap, state);
|
||||
outlet_anything(this->m_outlet, gensym("gem_state"), 1, ap);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// startRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: startRendering()
|
||||
{
|
||||
if (m_cache) m_cache->reset(this);
|
||||
else m_cache = new GemCache(this);
|
||||
|
||||
outputRenderOnOff(1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// stopRendering
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: stopRendering()
|
||||
{
|
||||
outputRenderOnOff(0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemhead :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG0(classPtr, "bang", bangMess);
|
||||
CPPEXTERN_MSG1(classPtr, "float", renderOnOff, int);
|
||||
CPPEXTERN_MSG1(classPtr, "set", setMess, int);
|
||||
}
|
||||
87
Gem/src/Controls/gemhead.h
Normal file
87
Gem/src/Controls/gemhead.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The starting point for all graphics trees
|
||||
|
||||
Copyright (c) 1997-1998 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMHEAD_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMHEAD_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
#include "gemreceive.h"
|
||||
|
||||
class GemState;
|
||||
class GemCache;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemhead
|
||||
|
||||
The starting point for all graphics trees
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"bang" - sends out a state list
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemhead : public gemreceive
|
||||
{
|
||||
CPPEXTERN_HEADER(gemhead, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemhead(int, t_atom*);
|
||||
|
||||
//////////
|
||||
// A render message
|
||||
void renderGL(GemState *state);
|
||||
|
||||
//////////
|
||||
// Set up the modifying flags
|
||||
virtual void startRendering();
|
||||
|
||||
//////////
|
||||
// Clean up the modifying flags
|
||||
virtual void stopRendering();
|
||||
|
||||
|
||||
//////////
|
||||
// change the priority
|
||||
void setMess(t_float priority);
|
||||
|
||||
virtual void receive(t_symbol*s, int argc, t_atom*argv);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemhead();
|
||||
|
||||
std::string m_basename;
|
||||
|
||||
private:
|
||||
|
||||
t_outlet *m_out1;
|
||||
|
||||
GemCache *m_cache; // The cache information
|
||||
|
||||
void outputRenderOnOff(int state);
|
||||
|
||||
void renderOnOff(int state); // Turn rendering on and off
|
||||
int m_renderOn;
|
||||
|
||||
void bangMess();
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
71
Gem/src/Controls/gemkeyboard.cpp
Normal file
71
Gem/src/Controls/gemkeyboard.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemkeyboard.h"
|
||||
|
||||
#include "Gem/Event.h"
|
||||
|
||||
CPPEXTERN_NEW(gemkeyboard);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemkeyboard
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemkeyboard :: gemkeyboard()
|
||||
{
|
||||
m_outKeyVal = outlet_new(this->x_obj, 0);
|
||||
|
||||
// register event callback
|
||||
setKeyboardCallback(&gemkeyboard::keyboardCallback, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemkeyboard :: ~gemkeyboard()
|
||||
{
|
||||
// remove event callback
|
||||
removeKeyboardCallback(&gemkeyboard::keyboardCallback, this);
|
||||
|
||||
outlet_free(m_outKeyVal);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// KeyBoardPressed
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemkeyboard :: KeyBoardPressed(int val, int state)
|
||||
{
|
||||
if (state==0)return;
|
||||
outlet_float(m_outKeyVal, static_cast<t_float>(val));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemkeyboard :: obj_setupCallback(t_class *)
|
||||
{ }
|
||||
void gemkeyboard :: keyboardCallback(char* w, int x, int y, void *data)
|
||||
{
|
||||
(reinterpret_cast<gemkeyboard*>(data))->KeyBoardPressed(x, y);
|
||||
}
|
||||
61
Gem/src/Controls/gemkeyboard.h
Normal file
61
Gem/src/Controls/gemkeyboard.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Respond to mouse events
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMKEYBOARD_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMKEYBOARD_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemkeyboard
|
||||
|
||||
Respond to keyboard events
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemkeyboard : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(gemkeyboard, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemkeyboard();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemkeyboard();
|
||||
|
||||
//////////
|
||||
// keyboard-button
|
||||
void KeyBoardPressed(int val, int state);
|
||||
|
||||
//////////
|
||||
// The key-val outlet
|
||||
t_outlet *m_outKeyVal;
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void keyboardCallback(char *w, int x, int y, void *data);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
73
Gem/src/Controls/gemkeyname.cpp
Normal file
73
Gem/src/Controls/gemkeyname.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemkeyname.h"
|
||||
|
||||
#include "Gem/Event.h"
|
||||
|
||||
CPPEXTERN_NEW(gemkeyname);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemkeyname
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemkeyname :: gemkeyname()
|
||||
{
|
||||
m_outKeyState = outlet_new(this->x_obj, 0);
|
||||
m_outKeyVal = outlet_new(this->x_obj, 0);
|
||||
|
||||
// register event callback
|
||||
setKeyboardCallback(&gemkeyname::keynameCallback, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemkeyname :: ~gemkeyname()
|
||||
{
|
||||
// remove event callback
|
||||
removeKeyboardCallback(&gemkeyname::keynameCallback, this);
|
||||
|
||||
outlet_free(m_outKeyState);
|
||||
outlet_free(m_outKeyVal);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// mouseMotion
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemkeyname :: KeyNamePressed(char *string, int val, int state)
|
||||
{
|
||||
outlet_symbol(m_outKeyVal, gensym(string));
|
||||
outlet_float(m_outKeyState, static_cast<t_float>(state));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemkeyname :: obj_setupCallback(t_class *)
|
||||
{ }
|
||||
void gemkeyname :: keynameCallback(char *x, int y, int z, void *data)
|
||||
{
|
||||
(reinterpret_cast<gemkeyname*>(data))->KeyNamePressed(x,y, z);
|
||||
}
|
||||
66
Gem/src/Controls/gemkeyname.h
Normal file
66
Gem/src/Controls/gemkeyname.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Respond to mouse events
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMKEYNAME_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMKEYNAME_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemkeyname
|
||||
|
||||
Respond to keyboard events
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemkeyname : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(gemkeyname, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemkeyname();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemkeyname();
|
||||
|
||||
//////////
|
||||
// keyname-button
|
||||
void KeyNamePressed(char* string, int val, int state);
|
||||
|
||||
//////////
|
||||
// The key-val outlet
|
||||
t_outlet *m_outKeyVal;
|
||||
|
||||
//////////
|
||||
// The key-state outlet
|
||||
t_outlet *m_outKeyState;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void keynameCallback(char* x, int y, int z, void *data);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
199
Gem/src/Controls/gemlist.cpp
Normal file
199
Gem/src/Controls/gemlist.cpp
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// ch@chdh.net
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemlist.h"
|
||||
|
||||
#include "Gem/Cache.h"
|
||||
#include "Gem/Manager.h"
|
||||
|
||||
CPPEXTERN_NEW(gemlist);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemlist
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemlist :: gemlist(void)
|
||||
: m_validState(false),
|
||||
m_tickTime(-1.f),
|
||||
m_lightState(false),
|
||||
m_drawType(0),
|
||||
m_mycache(new GemCache(NULL)),
|
||||
m_inlet(NULL)
|
||||
{
|
||||
// create the cold inlet
|
||||
m_inlet = inlet_new(this->x_obj, &this->x_obj->ob_pd, gensym("gem_state"), gensym("gem_right"));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemlist :: ~gemlist()
|
||||
{
|
||||
if(m_mycache)delete m_mycache; m_mycache=NULL;
|
||||
if(m_inlet)inlet_free(m_inlet); m_inlet=NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// render
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemlist :: render(GemState *state)
|
||||
{
|
||||
m_state=*state; //copy current state for later use
|
||||
m_validState=true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// postrender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemlist :: postrender(GemState *)
|
||||
{
|
||||
// m_validState=false;
|
||||
|
||||
// this is to early to reset the m_validState
|
||||
// when should we call this???
|
||||
// TODO : fix this.
|
||||
}
|
||||
|
||||
void gemlist :: sendCacheState(GemCache *cache, GemState*state)
|
||||
{
|
||||
if ( !GemMan::windowExists() ) {
|
||||
// LATER: shouldn't this test for a valid context rather than an existing window??
|
||||
// error("you should not bang the gemlist now");
|
||||
return;
|
||||
}
|
||||
|
||||
if(state) {
|
||||
t_atom ap[2];
|
||||
|
||||
if(!cache)
|
||||
cache=m_mycache;
|
||||
|
||||
ap->a_type=A_POINTER;
|
||||
ap->a_w.w_gpointer=reinterpret_cast<t_gpointer*>(cache);
|
||||
(ap+1)->a_type=A_POINTER;
|
||||
(ap+1)->a_w.w_gpointer=reinterpret_cast<t_gpointer*>(state);
|
||||
outlet_anything(m_out1, gensym("gem_state"), 2, ap);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// bang
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemlist :: trigger()
|
||||
{
|
||||
if(m_validState) {
|
||||
// outlet the current state when banged
|
||||
sendCacheState(m_cache, &m_state);
|
||||
} else {
|
||||
// GemMan::fillGemState(state);
|
||||
sendCacheState(NULL, &m_mystate);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// here come some messages for setting up a manual GemState
|
||||
void gemlist :: ticktimeMess(t_float ticktime)
|
||||
{
|
||||
m_tickTime=ticktime;
|
||||
m_mystate.set(GemState::_TIMING_TICK, m_tickTime);
|
||||
|
||||
}
|
||||
void gemlist :: lightingMess(bool light)
|
||||
{
|
||||
m_lightState=light;
|
||||
m_mystate.set(GemState::_GL_LIGHTING, m_lightState);
|
||||
m_mystate.set(GemState::_GL_SMOOTH, m_lightState);
|
||||
}
|
||||
void gemlist :: drawMess(t_atom&arg)
|
||||
{
|
||||
if(A_SYMBOL==arg.a_type) {
|
||||
t_symbol*type=atom_getsymbol(&arg);
|
||||
char c=*type->s_name;
|
||||
switch (c){
|
||||
case 'D': case 'd': // default
|
||||
m_drawType = GL_DEFAULT_GEM;
|
||||
break;
|
||||
case 'L': case 'l': // line
|
||||
m_drawType = GL_LINE;
|
||||
break;
|
||||
case 'F': case 'f': // fill
|
||||
m_drawType = GL_FILL;
|
||||
break;
|
||||
case 'P': case 'p': // point
|
||||
m_drawType = GL_POINT;
|
||||
break;
|
||||
default:
|
||||
m_drawType = static_cast<GLenum>(getGLdefine(&arg));
|
||||
}
|
||||
}
|
||||
else m_drawType=atom_getint(&arg);
|
||||
m_mystate.set(GemState::_GL_DRAWTYPE, m_drawType);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// rightRender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemlist :: rightRender(GemCache*cache, GemState *state)
|
||||
{
|
||||
if(state) {
|
||||
m_state=*state;
|
||||
m_validState=true;
|
||||
// get the current state on the right inlet
|
||||
} else {
|
||||
m_validState=false;
|
||||
}
|
||||
m_cache=cache;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemlist :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG0(classPtr, "bang", trigger);
|
||||
|
||||
CPPEXTERN_MSG (classPtr, "gem_right", rightMess);
|
||||
CPPEXTERN_MSG1(classPtr, "ticktime", ticktimeMess, float);
|
||||
CPPEXTERN_MSG1(classPtr, "lighting", lightingMess, bool);
|
||||
CPPEXTERN_MSG (classPtr, "draw", drawMess);
|
||||
}
|
||||
void gemlist :: drawMess(t_symbol*s, int argc, t_atom*argv)
|
||||
{
|
||||
if(argc==1)
|
||||
drawMess(argv[0]);
|
||||
}
|
||||
void gemlist::rightMess(t_symbol *s, int argc, t_atom *argv)
|
||||
{
|
||||
GemCache*cache=NULL;
|
||||
GemState*state=NULL;
|
||||
if (argc==1 && argv->a_type==A_FLOAT){
|
||||
rightRender(cache, state);
|
||||
} else if (argc==2 && argv->a_type==A_POINTER && (argv+1)->a_type==A_POINTER){
|
||||
cache=reinterpret_cast<GemCache*>(argv->a_w.w_gpointer);
|
||||
state=reinterpret_cast<GemState*>((argv+1)->a_w.w_gpointer);
|
||||
rightRender( cache, state );
|
||||
} else error("wrong righthand arguments....");
|
||||
}
|
||||
89
Gem/src/Controls/gemlist.h
Normal file
89
Gem/src/Controls/gemlist.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
this object work with gemlist exactly like pd [float] work with float
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMLIST_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMLIST_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
#include "Gem/State.h"
|
||||
|
||||
class GemCache;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemlist
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"gemlist" - send the curent gemlist when banged.
|
||||
The curent gemlist can be set via the hot or cold inlet
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemlist : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(gemlist, GemBase);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemlist(void);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemlist(void);
|
||||
|
||||
//////////
|
||||
// Push the current state
|
||||
virtual void render(GemState *state);
|
||||
|
||||
//////////
|
||||
virtual void postrender(GemState *state);
|
||||
|
||||
//////////
|
||||
// send a valid state to the outlet
|
||||
void sendCacheState(GemCache*cache, GemState*state);
|
||||
|
||||
//////////
|
||||
void trigger(void);
|
||||
virtual void rightRender(GemCache*cache, GemState *state);
|
||||
void rightMess(t_symbol *s, int argc, t_atom *argv);
|
||||
|
||||
virtual void ticktimeMess(t_float ticktime);
|
||||
virtual void lightingMess(bool state);
|
||||
virtual void drawMess(t_atom&arg);
|
||||
virtual void drawMess(t_symbol*s, int argc, t_atom*argv);
|
||||
|
||||
|
||||
//////////
|
||||
// curent state
|
||||
GemState m_state;
|
||||
bool m_validState;
|
||||
|
||||
|
||||
float m_tickTime;
|
||||
bool m_lightState;
|
||||
GLenum m_drawType;
|
||||
|
||||
GemState m_mystate;
|
||||
GemCache* m_mycache;
|
||||
|
||||
|
||||
t_inlet *m_inlet;
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
163
Gem/src/Controls/gemlist_info.cpp
Normal file
163
Gem/src/Controls/gemlist_info.cpp
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2002-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER
|
||||
// * OF ALL WARRANTIES, see the file, "GEM.LICENSE.TERMS"
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemlist_info.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
#ifdef __ppc__
|
||||
#include "Utils/Functions.h"
|
||||
#undef sqrt
|
||||
#define sqrt fast_sqrtf
|
||||
#endif
|
||||
|
||||
#define rad2deg -57.2957795132
|
||||
|
||||
|
||||
CPPEXTERN_NEW_WITH_ONE_ARG ( gemlist_info , t_floatarg, A_DEFFLOAT );
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemlist_info
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
gemlist_info :: gemlist_info (t_floatarg arg0=0) {
|
||||
m_outletRotation = outlet_new(this->x_obj, 0);
|
||||
m_outletShear = outlet_new(this->x_obj, 0);
|
||||
m_outletScale = outlet_new(this->x_obj, 0);
|
||||
m_outletPosition = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
gemlist_info :: ~gemlist_info () {
|
||||
outlet_free(m_outletScale);
|
||||
outlet_free(m_outletPosition);
|
||||
outlet_free(m_outletRotation);
|
||||
outlet_free(m_outletShear);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// extension check
|
||||
//
|
||||
bool gemlist_info :: isRunnable() {
|
||||
if(GLEW_VERSION_1_1)
|
||||
return true;
|
||||
|
||||
error("your system does not support openGL-1.0 needed for operation");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Render
|
||||
//
|
||||
void gemlist_info :: render(GemState *state) {
|
||||
float mi[16]={0};
|
||||
t_atom alist[12];
|
||||
|
||||
|
||||
float X, Y, Z, ScaleX, ScaleY, ScaleZ, shearYX, shearZX, shearZY;
|
||||
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX,mi);
|
||||
|
||||
// test de syngularité a effectuer
|
||||
|
||||
// normalisation
|
||||
// for (i=0; i<16; i++) mi[i] /= mi[15];
|
||||
// not usefull because I never saw mi[15]!=1; if this change, un-comment this normalisation procedure
|
||||
ScaleX = sqrt (mi[0] * mi[0] + mi[4] * mi[4] + mi[8] * mi[8]);
|
||||
mi[0] /= ScaleX; // Normalise X
|
||||
mi[4] /= ScaleX;
|
||||
mi[8] /= ScaleX;
|
||||
|
||||
shearYX = mi[0]*mi[1] + mi[4]*mi[5] + mi[8]*mi[9];
|
||||
|
||||
mi[1] -= shearYX * mi[0]; //make X and Y orthogonal
|
||||
mi[5] -= shearYX * mi[4];
|
||||
mi[9] -= shearYX * mi[8];
|
||||
|
||||
ScaleY = sqrt (mi[1] * mi[1] + mi[5] * mi[5] + mi[9] * mi[9]);
|
||||
|
||||
mi[1] /= ScaleY; // Normalise Y
|
||||
mi[5] /= ScaleY;
|
||||
mi[9] /= ScaleY;
|
||||
shearYX /= ScaleY;
|
||||
|
||||
shearZX = mi[0]*mi[2] + mi[4]*mi[6] + mi[8]*mi[10];
|
||||
|
||||
mi[2] -= shearZX * mi[0]; //make X and Z orthogonal
|
||||
mi[6] -= shearZX * mi[4];
|
||||
mi[10] -= shearZX * mi[8];
|
||||
|
||||
shearZY = mi[1]*mi[2] + mi[5]*mi[6] + mi[9]*mi[10];
|
||||
|
||||
mi[2] -= shearZY * mi[1]; //make X and Z orthogonal
|
||||
mi[6] -= shearZY * mi[5];
|
||||
mi[10] -= shearZY * mi[9];
|
||||
|
||||
ScaleZ = sqrt (mi[2] * mi[2] + mi[6] * mi[6] + mi[10] * mi[10]);
|
||||
|
||||
mi[2] /= ScaleZ; // Normalise Y
|
||||
mi[6] /= ScaleZ;
|
||||
mi[10] /= ScaleZ;
|
||||
shearZX /= ScaleZ;
|
||||
shearZY /= ScaleZ;
|
||||
|
||||
// maybee some test could be inserted here.
|
||||
// The matrix can only be decomposed if it's determinent is not 0.
|
||||
|
||||
Y = asin(-mi[8]);
|
||||
if ( cos(Y) != 0 ) {
|
||||
X = atan2(mi[9], mi[10]);
|
||||
Z = atan2(mi[4], mi[0]);
|
||||
} else {
|
||||
X = atan2(mi[1], mi[5]);
|
||||
Z = 0;
|
||||
}
|
||||
|
||||
X *= rad2deg;
|
||||
Y *= rad2deg;
|
||||
Z *= rad2deg;
|
||||
|
||||
SETFLOAT(alist+0, ScaleX);
|
||||
SETFLOAT(alist+1, ScaleY);
|
||||
SETFLOAT(alist+2, ScaleZ);
|
||||
|
||||
SETFLOAT(alist+3, X);
|
||||
SETFLOAT(alist+4, Y);
|
||||
SETFLOAT(alist+5, Z);
|
||||
|
||||
SETFLOAT(alist+6, mi[12]);
|
||||
SETFLOAT(alist+7, mi[13]);
|
||||
SETFLOAT(alist+8, mi[14]);
|
||||
|
||||
SETFLOAT(alist+9, shearYX);
|
||||
SETFLOAT(alist+10, shearZX);
|
||||
SETFLOAT(alist+11, shearZY);
|
||||
|
||||
outlet_list (m_outletPosition, &s_list, 3, alist+6);
|
||||
outlet_list (m_outletScale, &s_list, 3, alist+0);
|
||||
outlet_list (m_outletShear, &s_list, 3, alist+9);
|
||||
outlet_list (m_outletRotation, &s_list, 3, alist+3);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member functions
|
||||
//
|
||||
void gemlist_info :: obj_setupCallback(t_class *classPtr) {
|
||||
}
|
||||
49
Gem/src/Controls/gemlist_info.h
Normal file
49
Gem/src/Controls/gemlist_info.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* ------------------------------------------------------------------
|
||||
* GEM - Graphics Environment for Multimedia
|
||||
*
|
||||
* Copyright (c) 2002-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
* zmoelnig@iem.kug.ac.at
|
||||
* For information on usage and redistribution, and for a DISCLAIMER
|
||||
* OF ALL WARRANTIES, see the file, "GEM.LICENSE.TERMS"
|
||||
*
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMLIST_INFO_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMLIST_INFO_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
/*
|
||||
CLASS
|
||||
gemlist_info
|
||||
KEYWORDS
|
||||
openGL 0
|
||||
DESCRIPTION
|
||||
get information (scale, shear, rotation, translation) about a gemlist
|
||||
*/
|
||||
|
||||
class GEM_EXTERN gemlist_info : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(gemlist_info, GemBase);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
gemlist_info (t_floatarg); // CON
|
||||
protected:
|
||||
// Destructor
|
||||
virtual ~gemlist_info ();
|
||||
// Do the rendering
|
||||
virtual void render (GemState *state);
|
||||
|
||||
// extension checks
|
||||
virtual bool isRunnable();
|
||||
|
||||
private:
|
||||
// The outlets
|
||||
t_outlet *m_outletScale;
|
||||
t_outlet *m_outletRotation;
|
||||
t_outlet *m_outletPosition;
|
||||
t_outlet *m_outletShear;
|
||||
};
|
||||
#endif // for header file
|
||||
81
Gem/src/Controls/gemlist_matrix.cpp
Normal file
81
Gem/src/Controls/gemlist_matrix.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2002-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER
|
||||
// * OF ALL WARRANTIES, see the file, "GEM.LICENSE.TERMS"
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemlist_matrix.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
#ifdef __ppc__
|
||||
#include "Utils/Functions.h"
|
||||
#undef sqrt
|
||||
#define sqrt fast_sqrtf
|
||||
#endif
|
||||
|
||||
#define rad2deg -57.2957795132
|
||||
|
||||
|
||||
CPPEXTERN_NEW_WITH_ONE_ARG ( gemlist_matrix , t_floatarg, A_DEFFLOAT );
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemlist_matrix
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
gemlist_matrix :: gemlist_matrix (t_floatarg arg0=0) {
|
||||
m_outletMatrice = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
gemlist_matrix :: ~gemlist_matrix () {
|
||||
outlet_free(m_outletMatrice);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// extension check
|
||||
//
|
||||
bool gemlist_matrix :: isRunnable() {
|
||||
if(GLEW_VERSION_1_1)
|
||||
return true;
|
||||
|
||||
error("your system does not support openGL-1.0 needed for operation");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Render
|
||||
//
|
||||
void gemlist_matrix :: render(GemState *state) {
|
||||
float mi[16]={0};
|
||||
int i;
|
||||
t_atom alist[16];
|
||||
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX,mi);
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
{
|
||||
SETFLOAT(alist+i, mi[i]);
|
||||
}
|
||||
outlet_list (m_outletMatrice, &s_list, 16, alist);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member functions
|
||||
//
|
||||
void gemlist_matrix :: obj_setupCallback(t_class *classPtr) {
|
||||
}
|
||||
45
Gem/src/Controls/gemlist_matrix.h
Normal file
45
Gem/src/Controls/gemlist_matrix.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* ------------------------------------------------------------------
|
||||
* GEM - Graphics Environment for Multimedia
|
||||
*
|
||||
* Copyright (c) 2002-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
* zmoelnig@iem.kug.ac.at
|
||||
* For information on usage and redistribution, and for a DISCLAIMER
|
||||
* OF ALL WARRANTIES, see the file, "GEM.LICENSE.TERMS"
|
||||
*
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMLIST_MATRIX_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMLIST_MATRIX_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
/*
|
||||
CLASS
|
||||
gemlist_matrix
|
||||
KEYWORDS
|
||||
openGL 0
|
||||
DESCRIPTION
|
||||
get information (scale, shear, rotation, translation) about a gemlist
|
||||
*/
|
||||
|
||||
class GEM_EXTERN gemlist_matrix : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(gemlist_matrix, GemBase);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
gemlist_matrix (t_floatarg); // CON
|
||||
protected:
|
||||
// Destructor
|
||||
virtual ~gemlist_matrix ();
|
||||
// Do the rendering
|
||||
virtual void render (GemState *state);
|
||||
// extension checks
|
||||
virtual bool isRunnable();
|
||||
|
||||
private:
|
||||
// The outlets
|
||||
t_outlet *m_outletMatrice;
|
||||
};
|
||||
#endif // for header file
|
||||
152
Gem/src/Controls/gemmouse.cpp
Normal file
152
Gem/src/Controls/gemmouse.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define GEM_CLASSFLAGS CLASS_NOINLET
|
||||
|
||||
#include "gemmouse.h"
|
||||
|
||||
#include "Gem/Event.h"
|
||||
#include "Gem/Manager.h"
|
||||
|
||||
CPPEXTERN_NEW_WITH_GIMME(gemmouse);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemmouse
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemmouse :: gemmouse(int argc, t_atom*argv) :
|
||||
m_scaleX(1.0), m_scaleY(1.0), m_scaleMode(NONE)
|
||||
{
|
||||
m_outXPos = outlet_new(this->x_obj, 0);
|
||||
m_outYPos = outlet_new(this->x_obj, 0);
|
||||
m_outLBut = outlet_new(this->x_obj, 0);
|
||||
m_outMBut = outlet_new(this->x_obj, 0);
|
||||
m_outRBut = outlet_new(this->x_obj, 0);
|
||||
|
||||
switch(argc){
|
||||
case 0:
|
||||
m_scaleX = m_scaleY = 0.f;
|
||||
break;
|
||||
case 1:
|
||||
m_scaleX = m_scaleY = atom_getfloat(argv);
|
||||
m_scaleMode =HEIGHT;
|
||||
break;
|
||||
default:
|
||||
m_scaleX=atom_getfloat(argv);
|
||||
m_scaleY=atom_getfloat(argv+1);
|
||||
m_scaleMode =BOTH;
|
||||
}
|
||||
|
||||
// register event callback
|
||||
setMotionCallback(&gemmouse::mouseMotionCallback, this);
|
||||
setButtonCallback(&gemmouse::mouseButtonCallback, this);
|
||||
setWheelCallback(&gemmouse::mouseWheelCallback, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemmouse :: ~gemmouse()
|
||||
{
|
||||
// remove event callback
|
||||
removeMotionCallback(&gemmouse::mouseMotionCallback, this);
|
||||
removeButtonCallback(&gemmouse::mouseButtonCallback, this);
|
||||
removeWheelCallback(&gemmouse::mouseWheelCallback, this);
|
||||
|
||||
outlet_free(m_outXPos);
|
||||
outlet_free(m_outYPos);
|
||||
outlet_free(m_outLBut);
|
||||
outlet_free(m_outMBut);
|
||||
outlet_free(m_outRBut);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// mouseMotion
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemmouse :: mouseMotion(int x, int y)
|
||||
{
|
||||
t_float scalex = 1., scaley=1.;
|
||||
|
||||
int width, height;
|
||||
GemMan::getRealDimen(&width, &height);
|
||||
|
||||
switch(m_scaleMode) {
|
||||
case NONE:
|
||||
break;
|
||||
case BOTH:
|
||||
scalex=m_scaleX/width;
|
||||
scaley=m_scaleY/height;
|
||||
break;
|
||||
case WIDTH:
|
||||
scalex=m_scaleX/width;
|
||||
scaley=scalex;
|
||||
break;
|
||||
case HEIGHT:
|
||||
scaley=m_scaleY/height;
|
||||
scalex=scaley;
|
||||
break;
|
||||
}
|
||||
|
||||
outlet_float(m_outYPos, static_cast<t_float>(y*scaley));
|
||||
outlet_float(m_outXPos, static_cast<t_float>(x*scalex));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// mouseButton
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemmouse :: mouseButton(int which, int state, int x, int y)
|
||||
{
|
||||
switch (which){
|
||||
case 0: outlet_float(m_outLBut, static_cast<t_float>(state)); break;
|
||||
case 1: outlet_float(m_outMBut, static_cast<t_float>(state)); break;
|
||||
case 2: outlet_float(m_outRBut, static_cast<t_float>(state)); break;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// mouseButton
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemmouse :: mouseWheel(int axis, int value)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemmouse :: obj_setupCallback(t_class *)
|
||||
{ }
|
||||
void gemmouse :: mouseMotionCallback(int x, int y, void *data)
|
||||
{
|
||||
(reinterpret_cast<gemmouse*>(data))->mouseMotion(x, y);
|
||||
}
|
||||
void gemmouse :: mouseButtonCallback(int which, int state, int x, int y, void *data)
|
||||
{
|
||||
(reinterpret_cast<gemmouse*>(data))->mouseButton(which, state, x, y);
|
||||
}
|
||||
void gemmouse :: mouseWheelCallback(int axis, int value, void *data)
|
||||
{
|
||||
(reinterpret_cast<gemmouse*>(data))->mouseWheel(axis, value);
|
||||
}
|
||||
101
Gem/src/Controls/gemmouse.h
Normal file
101
Gem/src/Controls/gemmouse.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Respond to mouse events
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMMOUSE_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMMOUSE_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemmouse
|
||||
|
||||
Respond to mouse events
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
enum t_mousescale { NONE, WIDTH, HEIGHT, BOTH };
|
||||
|
||||
class GEM_EXTERN gemmouse : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(gemmouse, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemmouse(int,t_atom*);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemmouse();
|
||||
|
||||
//////////
|
||||
// mouse motion
|
||||
void mouseMotion(int x, int y);
|
||||
|
||||
//////////
|
||||
// mouse button
|
||||
void mouseButton(int which, int state, int x, int y);
|
||||
|
||||
//////////
|
||||
// mouse button
|
||||
void mouseWheel(int axis, int value);
|
||||
|
||||
//////////
|
||||
// The xpos outlet
|
||||
t_outlet *m_outXPos;
|
||||
|
||||
//////////
|
||||
// The ypos outlet
|
||||
t_outlet *m_outYPos;
|
||||
|
||||
//////////
|
||||
// The left button outlet
|
||||
t_outlet *m_outLBut;
|
||||
|
||||
//////////
|
||||
// The middle outlet
|
||||
t_outlet *m_outMBut;
|
||||
|
||||
//////////
|
||||
// The right outlet
|
||||
t_outlet *m_outRBut;
|
||||
|
||||
//////////
|
||||
// coordinate-scales
|
||||
// if !=0, the mouse-coordinate is scaled to 0..m_scale
|
||||
// if ==0, the mouse-coordinate is scaled to 0..windowsize
|
||||
t_float m_scaleX, m_scaleY;
|
||||
|
||||
//////////
|
||||
// should Y we scaled separately or like X ?
|
||||
t_mousescale m_scaleMode;
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void mouseMotionCallback(int x, int y, void *data);
|
||||
static void mouseButtonCallback(int which, int state, int x, int y, void *data);
|
||||
static void mouseWheelCallback(int axis, int value, void *data);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
287
Gem/src/Controls/gemreceive.cpp
Normal file
287
Gem/src/Controls/gemreceive.cpp
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2008-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "gemreceive.h"
|
||||
|
||||
#if 0
|
||||
# define debug_post ::post
|
||||
#else
|
||||
# define debug_post
|
||||
#endif
|
||||
|
||||
static t_class *gemreceive_proxy_class;
|
||||
|
||||
struct _bind_element {
|
||||
gemreceive *object;
|
||||
t_float priority;
|
||||
struct _bind_element*next;
|
||||
};
|
||||
|
||||
struct _gemreceive_proxy {
|
||||
t_object p_obj;
|
||||
|
||||
t_symbol*key;
|
||||
t_bind_element*elements;
|
||||
struct _gemreceive_proxy*next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
t_gemreceive_proxy*gemreceive :: proxy_list = NULL;
|
||||
|
||||
t_gemreceive_proxy* gemreceive::find_key(t_symbol*key)
|
||||
{
|
||||
t_gemreceive_proxy*binding=0;
|
||||
|
||||
for(binding=proxy_list; binding; binding=binding->next) {
|
||||
if(binding->key == key)
|
||||
return binding;
|
||||
}
|
||||
/* not found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_gemreceive_proxy*gemreceive::add_key(t_symbol*key)
|
||||
{
|
||||
t_gemreceive_proxy*bind_list=0;
|
||||
bind_list=reinterpret_cast<t_gemreceive_proxy*>(pd_new(gemreceive_proxy_class));
|
||||
bind_list->key=key;
|
||||
bind_list->elements=0;
|
||||
bind_list->next=0;
|
||||
|
||||
debug_post("binding %x to %s", bind_list, key->s_name);
|
||||
pd_bind(&bind_list->p_obj.ob_pd, key);
|
||||
|
||||
t_gemreceive_proxy*last=proxy_list;
|
||||
|
||||
if(last) {
|
||||
while(last->next) {
|
||||
last=last->next;
|
||||
}
|
||||
last->next = bind_list;
|
||||
} else {
|
||||
proxy_list = bind_list;
|
||||
}
|
||||
|
||||
return bind_list;
|
||||
}
|
||||
|
||||
void gemreceive::add_element(t_gemreceive_proxy*bind_list, t_bind_element*element)
|
||||
{
|
||||
/* insert the object according to it's priority
|
||||
* this is already the right queue
|
||||
*/
|
||||
t_float priority=element->priority;
|
||||
t_bind_element*elements=bind_list->elements, *last=0;
|
||||
debug_post("priority insert of %x:%g", element, priority);
|
||||
|
||||
if(!elements || elements->priority >= priority) {
|
||||
bind_list->elements = element;
|
||||
element->next = elements;
|
||||
debug_post("inserting in the beginngin");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
debug_post("trying %x:%g", elements, elements->priority);
|
||||
while(elements && elements->priority < priority) {
|
||||
debug_post("skipping %x:%g to %x", elements, elements->priority, elements->next);
|
||||
last=elements;
|
||||
elements=elements->next;
|
||||
}
|
||||
|
||||
debug_post("inserting after %x:%g", last, (last ? (last->priority):0));
|
||||
debug_post("inserting befor %x:%g", elements, (elements?(elements->priority):0));
|
||||
|
||||
element->next=elements;
|
||||
if(last) {
|
||||
last->next = element;
|
||||
} else {
|
||||
bug("\nlast object invalid when inserting prioritized receiver\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gemreceive::bind(gemreceive*x, t_symbol*key, t_float priority) {
|
||||
t_gemreceive_proxy*bind_list=0;
|
||||
t_bind_element*element=0;
|
||||
debug_post("trying to bind 0x%X:: '%s':%g via %x", x, key->s_name, priority, proxy_list);
|
||||
|
||||
bind_list=find_key(key);
|
||||
if(!bind_list)
|
||||
bind_list=add_key(key);
|
||||
if(!bind_list)return;
|
||||
|
||||
element=(t_bind_element*)getbytes(sizeof(t_bind_element));
|
||||
|
||||
element->object=x;
|
||||
|
||||
element->priority=priority;
|
||||
element->next=0;
|
||||
|
||||
add_element(bind_list, element);
|
||||
}
|
||||
|
||||
|
||||
void gemreceive::unbind(gemreceive*x, t_symbol*key) {
|
||||
t_gemreceive_proxy*list=0, *last=0;
|
||||
t_bind_element*elements=0, *lastlmn=0;
|
||||
|
||||
debug_post("trying to unbind 0x%X:: '%s' from %x", x, key->s_name, proxy_list);
|
||||
|
||||
for(list=proxy_list; list && list->key!=key; list=list->next){
|
||||
last=list;
|
||||
}
|
||||
if(!list)return;
|
||||
|
||||
for(elements=list->elements; elements && elements->object != x; elements=elements->next) {
|
||||
lastlmn=elements;
|
||||
}
|
||||
|
||||
if(elements) {
|
||||
/* found it, now remove it */
|
||||
if(lastlmn) {
|
||||
lastlmn->next=elements->next;
|
||||
} else {
|
||||
list->elements=elements->next;
|
||||
}
|
||||
|
||||
elements->object=0;
|
||||
elements->priority=0;
|
||||
elements->next=0;
|
||||
|
||||
freebytes(elements, sizeof(elements));
|
||||
} else {
|
||||
// not here...
|
||||
}
|
||||
|
||||
if(0==list->elements) {
|
||||
// should we unbind ??
|
||||
if(last) {
|
||||
last->next=list->next;
|
||||
} else {
|
||||
proxy_list=list->next;
|
||||
}
|
||||
|
||||
pd_unbind(&list->p_obj.ob_pd, list->key);
|
||||
list->next=0;
|
||||
list->key=0;
|
||||
|
||||
pd_free(&list->p_obj.ob_pd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CPPEXTERN_NEW_WITH_TWO_ARGS(gemreceive, t_symbol*, A_DEFSYMBOL, t_floatarg, A_DEFFLOAT);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemreceive
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemreceive :: gemreceive(t_symbol*s,t_floatarg f) :
|
||||
m_name(s), m_priority(f),
|
||||
m_outlet(NULL), m_fltin(NULL)
|
||||
{
|
||||
debug_post("hi, i am gemreceive 0x%X", this);
|
||||
|
||||
|
||||
m_fltin = inlet_new(this->x_obj, &this->x_obj->ob_pd, &s_float, gensym(""));
|
||||
m_outlet = outlet_new(this->x_obj, 0);
|
||||
|
||||
bind(this, m_name, m_priority);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemreceive :: ~gemreceive()
|
||||
{
|
||||
unbind(this, m_name);
|
||||
|
||||
if(m_fltin)inlet_free(m_fltin);m_fltin=NULL;
|
||||
if(m_outlet)outlet_free(m_outlet);m_outlet=NULL;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// receiving
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemreceive :: receive(t_symbol*s, int argc, t_atom*argv)
|
||||
{
|
||||
debug_post("receiveing....%x", m_outlet);
|
||||
outlet_anything(m_outlet, s, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
void gemreceive :: nameMess(std::string s) {
|
||||
if(m_name) {
|
||||
unbind(this, m_name);
|
||||
}
|
||||
m_name=gensym(s.c_str());
|
||||
bind(this, m_name, m_priority);
|
||||
}
|
||||
|
||||
void gemreceive :: priorityMess(t_float f) {
|
||||
m_priority=f;
|
||||
if(m_name) {
|
||||
unbind(this, m_name);
|
||||
bind(this, m_name, m_priority);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemreceive :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG1(classPtr, "symbol", nameMess, std::string);
|
||||
CPPEXTERN_MSG1(classPtr, "", priorityMess, t_float);
|
||||
|
||||
gemreceive_proxy_class = class_new(0, 0, 0,
|
||||
sizeof(t_gemreceive_proxy),
|
||||
CLASS_NOINLET | CLASS_PD,
|
||||
A_NULL);
|
||||
class_addanything(gemreceive_proxy_class, reinterpret_cast<t_method>(gemreceive::proxyCallback));
|
||||
}
|
||||
|
||||
void gemreceive :: proxyCallback(t_gemreceive_proxy*p, t_symbol*s, int argc, t_atom*argv)
|
||||
{
|
||||
t_bind_element*elements=p->elements;
|
||||
|
||||
debug_post("proxy anything: %x", p);
|
||||
|
||||
while(elements) {
|
||||
gemreceive*o=elements->object;
|
||||
elements=elements->next;
|
||||
debug_post("proxy for 0x%X", o);
|
||||
if(o) {
|
||||
o->receive(s, argc, argv);
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Gem/src/Controls/gemreceive.h
Normal file
102
Gem/src/Controls/gemreceive.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
ordered receive
|
||||
|
||||
Copyright (c) 2008-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMRECEIVE_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMRECEIVE_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemreceive
|
||||
|
||||
[receive] with explicit order
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
this object is really totally unrelated to Gem.
|
||||
however, it is included here, in order to replace the current
|
||||
(integrated) implementation of [gemhead] with an abstraction that makes use
|
||||
of an ordered [receive]
|
||||
|
||||
the original object was [oreceive] in the iemguts library
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
EXTERN_STRUCT _bind_element;
|
||||
EXTERN_STRUCT _gemreceive_proxy;
|
||||
|
||||
typedef struct _bind_element t_bind_element;
|
||||
typedef struct _gemreceive_proxy t_gemreceive_proxy;
|
||||
|
||||
|
||||
class GEM_EXTERN gemreceive : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(gemreceive, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemreceive(t_symbol*s, t_floatarg f=50.f);
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemreceive();
|
||||
|
||||
//////////
|
||||
// keyboard-button
|
||||
virtual void receive(t_symbol*s, int argc, t_atom*argv);
|
||||
|
||||
//////////
|
||||
// the symbol we are bound to
|
||||
void nameMess(std::string);
|
||||
t_symbol*m_name;
|
||||
|
||||
//////////
|
||||
// the receive priority
|
||||
void priorityMess(t_float f);
|
||||
t_float m_priority;
|
||||
|
||||
//////////
|
||||
// The receive outlet
|
||||
t_outlet *m_outlet;
|
||||
|
||||
//////////
|
||||
// inlet for priority
|
||||
t_inlet*m_fltin;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void proxyCallback(t_gemreceive_proxy*, t_symbol*s, int argc, t_atom*argv);
|
||||
|
||||
static t_gemreceive_proxy*find_key(t_symbol*);
|
||||
static t_gemreceive_proxy*add_key(t_symbol*);
|
||||
static void add_element(t_gemreceive_proxy*, t_bind_element*);
|
||||
|
||||
static t_gemreceive_proxy*proxy_list;
|
||||
|
||||
|
||||
public:
|
||||
static void bind(gemreceive*x, t_symbol*name, t_float priority);
|
||||
static void unbind(gemreceive*x, t_symbol*name);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
728
Gem/src/Controls/gemwin.cpp
Normal file
728
Gem/src/Controls/gemwin.cpp
Normal file
|
|
@ -0,0 +1,728 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-2000 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef __APPLE__
|
||||
# ifdef __x86_64
|
||||
# define NO_AUTO_REGISTER_CLASS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "gemwin.h"
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <Carbon/Carbon.h>
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "Utils/GemMath.h"
|
||||
#include "Gem/Manager.h"
|
||||
|
||||
CPPEXTERN_NEW_WITH_ONE_ARG(gemwin, t_floatarg, A_DEFFLOAT);
|
||||
|
||||
static bool StillHaveGemWin(bool up) {
|
||||
static int ref_counter = 0;
|
||||
|
||||
if (up){
|
||||
ref_counter++;
|
||||
if (ref_counter==1)return false;
|
||||
} else {
|
||||
ref_counter--;
|
||||
if (ref_counter<0)ref_counter=0;
|
||||
return (ref_counter!=0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// gemwin
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemwin :: gemwin(t_floatarg framespersecond)
|
||||
: m_FrameRate(NULL)
|
||||
{
|
||||
if(!StillHaveGemWin(true)) {
|
||||
/* this is the only [gemwin] */
|
||||
GemMan::resetState();
|
||||
if (framespersecond > 0.)
|
||||
GemMan::frameRate(framespersecond);
|
||||
} else {
|
||||
if(framespersecond>0.)
|
||||
GemMan::frameRate(framespersecond);
|
||||
}
|
||||
|
||||
m_FrameRate = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
gemwin :: ~gemwin()
|
||||
{
|
||||
if(!StillHaveGemWin(false))
|
||||
GemMan::destroyWindow();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// bangMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: bangMess()
|
||||
{
|
||||
if ( GemMan::windowExists() )
|
||||
{
|
||||
if(1==GemMan::m_buffer)
|
||||
GemMan::swapBuffers();
|
||||
else /* double buffered mode */
|
||||
GemMan::render(NULL);
|
||||
}
|
||||
else
|
||||
error("no window");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// intMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: intMess(int state)
|
||||
{
|
||||
if (state)
|
||||
GemMan::startRendering();
|
||||
else
|
||||
GemMan::stopRendering();
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// renderMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: renderMess()
|
||||
{
|
||||
if (GemMan::getRenderState())
|
||||
GemMan::render(NULL);
|
||||
else
|
||||
error("not in render mode");
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// titleMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: titleMess(t_symbol* s)
|
||||
{
|
||||
GemMan::m_title = s->s_name;
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// createMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: createMess(t_symbol* s)
|
||||
{
|
||||
char* disp = NULL;
|
||||
|
||||
/* just in case a "pleaseDestroy" is still pending... */
|
||||
GemMan::pleaseDestroy=false;
|
||||
|
||||
if (s != &s_)
|
||||
disp = s->s_name;
|
||||
|
||||
if ( !GemMan::windowExists() ) {
|
||||
GemMan::createContext(disp);
|
||||
if ( !GemMan::createWindow(disp) ) {
|
||||
error("no window made");
|
||||
return;
|
||||
}
|
||||
GemMan::swapBuffers();
|
||||
GemMan::swapBuffers();
|
||||
} else
|
||||
error("window already made");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// bufferMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: bufferMess(int buf)
|
||||
{
|
||||
if (buf == 1)
|
||||
GemMan::m_buffer = 1;
|
||||
else
|
||||
GemMan::m_buffer = 2;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// stereoMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: stereoMess(int mode)
|
||||
{
|
||||
if (mode<0){
|
||||
error("stereo-mode must not be %d", mode);
|
||||
return;
|
||||
}
|
||||
if (mode>1) {
|
||||
error("only stereo-modes 1/0 are allowed!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
GemMan::m_stereo = mode;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fullscreenMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fullscreenMess(int on)
|
||||
{
|
||||
GemMan::m_fullscreen = on;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// menuBarMess 1 = show -1 = hide, but autoshow
|
||||
// 0 = hide, but neverShow
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: menuBarMess(int on)
|
||||
{
|
||||
GemMan::m_menuBar = on;
|
||||
#ifdef __APPLE__
|
||||
if (on == 0) {
|
||||
SetSystemUIMode( kUIModeAllHidden, kUIOptionDisableAppleMenu |
|
||||
kUIOptionDisableProcessSwitch |
|
||||
kUIOptionDisableSessionTerminate |
|
||||
kUIOptionDisableForceQuit );
|
||||
}else if (on > 0) {
|
||||
SetSystemUIMode( kUIModeNormal, 0 );
|
||||
}else if (on < 0) {
|
||||
SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// secondScreen
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: secondscreenMess(int on)
|
||||
{
|
||||
GemMan::m_secondscreen = on;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// dimensionsMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: dimensionsMess(int width, int height)
|
||||
{
|
||||
if (width <= 0) {
|
||||
error("width must be greater than 0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (height <= 0 ) {
|
||||
error ("height must be greater than 0");
|
||||
return;
|
||||
}
|
||||
GemMan::m_width = width;
|
||||
GemMan::m_height = height;
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// offsetMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: offsetMess(int x, int y)
|
||||
{
|
||||
GemMan::m_xoffset = x;
|
||||
GemMan::m_yoffset = y;
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// colorMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: colorMess(float red, float green, float blue, float alpha)
|
||||
{
|
||||
GemMan::m_clear_color[0] = red;
|
||||
GemMan::m_clear_color[1] = green;
|
||||
GemMan::m_clear_color[2] = blue;
|
||||
GemMan::m_clear_color[3] = alpha;
|
||||
if ( GemMan::windowExists() ) {
|
||||
glClearColor(red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// clearmaskMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: clearmaskMess(float bitmask)
|
||||
{
|
||||
GemMan::m_clear_mask = static_cast<GLbitfield>(bitmask);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// ambientMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: ambientMess(float red, float green, float blue, float alpha)
|
||||
{
|
||||
GemMan::m_mat_ambient[0] = red;
|
||||
GemMan::m_mat_ambient[1] = green;
|
||||
GemMan::m_mat_ambient[2] = blue;
|
||||
GemMan::m_mat_ambient[3] = blue;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// specularMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: specularMess(float red, float green, float blue, float alpha)
|
||||
{
|
||||
GemMan::m_mat_specular[0] = red;
|
||||
GemMan::m_mat_specular[1] = green;
|
||||
GemMan::m_mat_specular[2] = blue;
|
||||
GemMan::m_mat_specular[2] = alpha;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// shininessMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: shininessMess(float val)
|
||||
{
|
||||
GemMan::m_mat_shininess = val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fogDensityMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fogDensityMess(float val)
|
||||
{
|
||||
if (val < 0.f)
|
||||
val = 0.f;
|
||||
|
||||
GemMan::m_fog = val;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fogRangeMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fogRangeMess(float start, float end)
|
||||
{
|
||||
if (start < 0.f)
|
||||
start= 0.f;
|
||||
|
||||
if (end < 0.f)
|
||||
end = 0.f;
|
||||
|
||||
GemMan::m_fogStart = start;
|
||||
GemMan::m_fogEnd = end;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fogColorMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fogColorMess(float red, float green, float blue, float alpha)
|
||||
{
|
||||
GemMan::m_fogColor[0] = red;
|
||||
GemMan::m_fogColor[1] = green;
|
||||
GemMan::m_fogColor[2] = blue;
|
||||
GemMan::m_fogColor[3] = alpha;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fogModeMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fogModeMess(int mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 0 :
|
||||
GemMan::m_fogMode = GemMan::FOG_OFF;
|
||||
break;
|
||||
|
||||
case 1 :
|
||||
GemMan::m_fogMode = GemMan::FOG_LINEAR;
|
||||
break;
|
||||
|
||||
case 2 :
|
||||
GemMan::m_fogMode = GemMan::FOG_EXP;
|
||||
break;
|
||||
|
||||
case 3 :
|
||||
GemMan::m_fogMode = GemMan::FOG_EXP2;
|
||||
break;
|
||||
|
||||
default :
|
||||
error("fogmode must be 0, 1, 2 or 3");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// cursorMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: cursorMess(float setting)
|
||||
{
|
||||
GemMan :: cursorOnOff(static_cast<int>(setting));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// topmostMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: topmostMess(float topmost)
|
||||
{
|
||||
GemMan::topmostOnOff(static_cast<int>(topmost));
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// cursorMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: blurMess(float setting)
|
||||
{
|
||||
if (setting>=0.f && setting <= 1.f)
|
||||
GemMan :: m_motionBlur = setting;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fpsMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fpsMess()
|
||||
{
|
||||
outlet_float(m_FrameRate,GemMan :: fps);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// fsaaMess
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: fsaaMess(int value)
|
||||
{
|
||||
if (value == 2 || value == 4 || value == 8){
|
||||
GemMan :: fsaa = value;
|
||||
}
|
||||
else{
|
||||
GemMan :: fsaa = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void gemwin :: obj_setupCallback(t_class *classPtr)
|
||||
{
|
||||
CPPEXTERN_MSG0(classPtr, "bang", bangMess);
|
||||
CPPEXTERN_MSG1(classPtr, "float", intMess, int);
|
||||
CPPEXTERN_MSG0(classPtr, "render", renderMess);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::titleMessCallback),
|
||||
gensym("title"), A_DEFSYM ,A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::createMessCallback),
|
||||
gensym("create"), A_DEFSYM ,A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::createStereoMessCallback),
|
||||
gensym("createStereo"), A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::createStereoMessCallback),
|
||||
gensym("createstereo"), A_NULL);
|
||||
|
||||
CPPEXTERN_MSG1(classPtr, "buffer", bufferMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "fullscreen", fullscreenMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "menubar", menuBarMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "secondscreen", secondscreenMess, int);
|
||||
CPPEXTERN_MSG1(classPtr, "topmost", topmostMess, int);
|
||||
CPPEXTERN_MSG2(classPtr, "dimen", dimensionsMess, int, int);
|
||||
CPPEXTERN_MSG2(classPtr, "offset", offsetMess, int, int);
|
||||
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::colorMessCallback),
|
||||
gensym("color"), A_GIMME, A_NULL);
|
||||
CPPEXTERN_MSG1(classPtr, "clearmask", clearmaskMess, float);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::perspectiveMessCallback),
|
||||
gensym("perspec"), A_GIMME, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::viewMessCallback),
|
||||
gensym("view"), A_GIMME, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::fogMessCallback),
|
||||
gensym("fog"), A_GIMME, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::fogColorMessCallback),
|
||||
gensym("fogcolor"), A_GIMME, A_NULL);
|
||||
|
||||
CPPEXTERN_MSG1(classPtr, "fogmode", fogModeMess, int);
|
||||
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::ambientMessCallback),
|
||||
gensym("ambient"), A_GIMME, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::specularMessCallback),
|
||||
gensym("specular"), A_GIMME, A_NULL);
|
||||
CPPEXTERN_MSG1(classPtr, "shininess", shininessMess, float);
|
||||
|
||||
CPPEXTERN_MSG1(classPtr, "cursor", cursorMess, float);
|
||||
CPPEXTERN_MSG1(classPtr, "blur", blurMess, float);
|
||||
|
||||
// just call GemMan directly
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::resetMessCallback),
|
||||
gensym("reset"), A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::destroyMessCallback),
|
||||
gensym("destroy"), A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::printMessCallback),
|
||||
gensym("print"), A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::profileMessCallback),
|
||||
gensym("profile"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::lightingMessCallback),
|
||||
gensym("lighting"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoMessCallback),
|
||||
gensym("stereo"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoSepMessCallback),
|
||||
gensym("stereoSep"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoFocMessCallback),
|
||||
gensym("stereoFoc"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoSepMessCallback),
|
||||
gensym("stereosep"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoFocMessCallback),
|
||||
gensym("stereofoc"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoLineMessCallback),
|
||||
gensym("stereoLine"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::stereoLineMessCallback),
|
||||
gensym("stereoline"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::borderMessCallback),
|
||||
gensym("border"), A_FLOAT, A_NULL);
|
||||
class_addmethod(classPtr, reinterpret_cast<t_method>(&gemwin::frameMessCallback),
|
||||
gensym("frame"), A_FLOAT, A_NULL);
|
||||
|
||||
CPPEXTERN_MSG0(classPtr, "fps", fpsMess);
|
||||
CPPEXTERN_MSG1(classPtr, "FSAA", fsaaMess, int);
|
||||
}
|
||||
void gemwin :: printMessCallback(void *)
|
||||
{
|
||||
GemMan::printInfo();
|
||||
}
|
||||
void gemwin :: profileMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::m_profile = static_cast<int>(state);
|
||||
}
|
||||
void gemwin :: lightingMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::lightingOnOff(static_cast<int>(state));
|
||||
}
|
||||
void gemwin :: fogMessCallback(void *data, t_symbol *, int argc, t_atom *argv)
|
||||
{
|
||||
switch (argc)
|
||||
{
|
||||
case (1):
|
||||
GetMyClass(data)->fogDensityMess(atom_getfloat(&argv[0]));
|
||||
break;
|
||||
case (2):
|
||||
GetMyClass(data)->fogRangeMess(atom_getfloat(&argv[0]),atom_getfloat(&argv[1]));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("fog message needs 1 or 2 arguments");
|
||||
}
|
||||
}
|
||||
void gemwin :: fogColorMessCallback(void *data, t_symbol*s,int argc, t_atom*argv)
|
||||
{
|
||||
float red, green, blue, alpha=1.f;
|
||||
switch(argc){
|
||||
case 4:
|
||||
alpha=atom_getfloat(argv+3);
|
||||
case 3:
|
||||
red= atom_getfloat(argv);
|
||||
green=atom_getfloat(argv+1);
|
||||
blue= atom_getfloat(argv+2);
|
||||
GetMyClass(data)->fogColorMess(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("\"fogcolor\" expects 3 or 4 values");
|
||||
}
|
||||
}
|
||||
void gemwin :: stereoMessCallback(void *data, t_float state)
|
||||
{
|
||||
int mode = static_cast<int>(state);
|
||||
if (mode<0 || mode>3){
|
||||
GetMyClass(data)->error("possible stereo-modes are: 0, 1, 2, 3");
|
||||
return;
|
||||
}
|
||||
|
||||
GemMan::m_stereo = mode;
|
||||
}
|
||||
void gemwin :: stereoSepMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::m_stereoSep = state;
|
||||
}
|
||||
void gemwin :: stereoFocMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::m_stereoFocal = state;
|
||||
}
|
||||
void gemwin :: stereoLineMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::m_stereoLine = (state!=0.0);
|
||||
}
|
||||
void gemwin :: borderMessCallback(void *, t_float state)
|
||||
{
|
||||
GemMan::m_border = static_cast<int>(state);
|
||||
}
|
||||
void gemwin :: destroyMessCallback(void *)
|
||||
{
|
||||
GemMan::destroyWindow();
|
||||
}
|
||||
void gemwin :: resetMessCallback(void *)
|
||||
{
|
||||
GemMan::resetState();
|
||||
}
|
||||
void gemwin :: frameMessCallback(void *, t_float rate)
|
||||
{
|
||||
GemMan::frameRate(static_cast<float>(rate));
|
||||
}
|
||||
void gemwin :: perspectiveMessCallback(void *data, t_symbol *, int argc, t_atom *argv)
|
||||
{
|
||||
if (argc != 6)
|
||||
{
|
||||
GetMyClass(data)->error("perspec message needs 6 arguments");
|
||||
return;
|
||||
}
|
||||
GemMan::m_perspect[0] = atom_getfloat(&argv[0]); // left
|
||||
GemMan::m_perspect[1] = atom_getfloat(&argv[1]); // right
|
||||
GemMan::m_perspect[2] = atom_getfloat(&argv[2]); // bottom
|
||||
GemMan::m_perspect[3] = atom_getfloat(&argv[3]); // top
|
||||
GemMan::m_perspect[4] = atom_getfloat(&argv[4]); // front
|
||||
GemMan::m_perspect[5] = atom_getfloat(&argv[5]); // back
|
||||
}
|
||||
void gemwin :: viewMessCallback(void *data, t_symbol *, int argc, t_atom *argv)
|
||||
{
|
||||
const float DEG2RAD = 0.01745329251994f;
|
||||
float azimuth = 0.f;
|
||||
float theta = 0.f;
|
||||
float distance = 1.f;
|
||||
|
||||
if (GemMan::m_stereoFocal > 0)
|
||||
{
|
||||
distance = GemMan::m_stereoFocal;
|
||||
}
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
// setting all lookat values directly
|
||||
case 9 :
|
||||
GemMan::m_lookat[0] = atom_getfloat(&argv[0]); // eyex
|
||||
GemMan::m_lookat[1] = atom_getfloat(&argv[1]); // eyey
|
||||
GemMan::m_lookat[2] = atom_getfloat(&argv[2]); // eyez
|
||||
GemMan::m_lookat[3] = atom_getfloat(&argv[3]); // centerx
|
||||
GemMan::m_lookat[4] = atom_getfloat(&argv[4]); // centery
|
||||
GemMan::m_lookat[5] = atom_getfloat(&argv[5]); // centerz
|
||||
GemMan::m_lookat[6] = atom_getfloat(&argv[6]); // upx
|
||||
GemMan::m_lookat[7] = atom_getfloat(&argv[7]); // upy
|
||||
GemMan::m_lookat[8] = atom_getfloat(&argv[8]); // upz
|
||||
break;
|
||||
|
||||
case 5 :
|
||||
theta = static_cast<float>(DEG2RAD) * atom_getfloat(&argv[4]);
|
||||
|
||||
case 4 :
|
||||
azimuth = static_cast<float>(DEG2RAD) * atom_getfloat(&argv[3]);
|
||||
|
||||
// just have position
|
||||
case 3 :
|
||||
{
|
||||
const float dx = static_cast<float>(cos(theta) * sinf(azimuth));
|
||||
const float dy = static_cast<float>(sin(theta));
|
||||
const float dz = -static_cast<float>(cos(theta) * cosf(azimuth));
|
||||
|
||||
GemMan::m_lookat[0] = atom_getfloat(&argv[0]); // eyex
|
||||
GemMan::m_lookat[1] = atom_getfloat(&argv[1]); // eyey
|
||||
GemMan::m_lookat[2] = atom_getfloat(&argv[2]); // eyez
|
||||
GemMan::m_lookat[3] = GemMan::m_lookat[0] + dx * distance; // centerx
|
||||
GemMan::m_lookat[4] = GemMan::m_lookat[1] + dy * distance; // centery
|
||||
GemMan::m_lookat[5] = GemMan::m_lookat[2] + dz * distance; // centery
|
||||
GemMan::m_lookat[6] = -dx*dy; // upx
|
||||
GemMan::m_lookat[7] = dx*dx+dz*dz; // upy
|
||||
GemMan::m_lookat[8] = -dy*dz; // upz
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
GetMyClass(data)->error("view message needs 3, 4, 5 or 9 arguments");
|
||||
|
||||
// note :: LATER set the StereoView ...
|
||||
}
|
||||
}
|
||||
void gemwin :: titleMessCallback(void *data, t_symbol* disp)
|
||||
{
|
||||
GetMyClass(data)->titleMess(disp);
|
||||
}
|
||||
void gemwin :: createMessCallback(void *data, t_symbol* disp)
|
||||
{
|
||||
GetMyClass(data)->createMess(disp);
|
||||
}
|
||||
void gemwin :: createStereoMessCallback(void *data)
|
||||
{
|
||||
GetMyClass(data)->error("'createStereo' is deprecated and does not work any more");
|
||||
GetMyClass(data)->error("use 'stereo 1' + 'create' instead");
|
||||
}
|
||||
void gemwin :: colorMessCallback(void *data, t_symbol*s, int argc, t_atom*argv)
|
||||
{
|
||||
float red, green, blue, alpha=0.f;
|
||||
switch(argc){
|
||||
case 4:
|
||||
alpha=atom_getfloat(argv+3);
|
||||
case 3:
|
||||
red= atom_getfloat(argv);
|
||||
green=atom_getfloat(argv+1);
|
||||
blue= atom_getfloat(argv+2);
|
||||
GetMyClass(data)->colorMess(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("\"color\" expects 3 or 4 values");
|
||||
}
|
||||
}
|
||||
void gemwin :: ambientMessCallback(void *data, t_symbol*s,int argc, t_atom*argv)
|
||||
{
|
||||
float red, green, blue, alpha=1.f;
|
||||
switch(argc){
|
||||
case 4:
|
||||
alpha=atom_getfloat(argv+3);
|
||||
case 3:
|
||||
red= atom_getfloat(argv);
|
||||
green=atom_getfloat(argv+1);
|
||||
blue= atom_getfloat(argv+2);
|
||||
GetMyClass(data)->ambientMess(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("\"ambient\" expects 3 or 4 values");
|
||||
}
|
||||
}
|
||||
void gemwin :: specularMessCallback(void *data, t_symbol*s,int argc, t_atom*argv)
|
||||
{
|
||||
float red, green, blue, alpha=1.f;
|
||||
switch(argc){
|
||||
case 4:
|
||||
alpha=atom_getfloat(argv+3);
|
||||
case 3:
|
||||
red= atom_getfloat(argv);
|
||||
green=atom_getfloat(argv+1);
|
||||
blue= atom_getfloat(argv+2);
|
||||
GetMyClass(data)->specularMess(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
|
||||
break;
|
||||
default:
|
||||
GetMyClass(data)->error("\"specular\" expects 3 or 4 values");
|
||||
}
|
||||
}
|
||||
144
Gem/src/Controls/gemwin.h
Normal file
144
Gem/src/Controls/gemwin.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Interface for the window manager
|
||||
|
||||
Copyright (c) 1997-200 Mark Danks.
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_GEMWIN_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_GEMWIN_H_
|
||||
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
gemwin
|
||||
|
||||
The window manager
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Access to GemMan.
|
||||
|
||||
"int" - turn on/off the rendering (in double buffered mode)
|
||||
"bang" - swap the buffers
|
||||
"render" - render a frame now
|
||||
"title" - set a title for the graphics window
|
||||
"create" - create a graphics window
|
||||
"destroy" - destroy the graphics window
|
||||
"buffer" - single or double buffering
|
||||
"fullscreen" - fullscreen mode
|
||||
"topmost" - set the window to stay on top
|
||||
"dimen" - the window dimensions
|
||||
"offset" - the window offset
|
||||
"frame" - the frame rate
|
||||
"lighting" - turn lighting on/off
|
||||
"ambient" - the ambient light color
|
||||
"specular" - the specular light color
|
||||
"shininess" - the shininess value
|
||||
"stereo" - select stereo-mode (0=off; 1=normal)
|
||||
"stereoSep" - the stereo separation
|
||||
"stereoFoc" - the distance to the focal point
|
||||
"stereoLine" - draw a line between two stereo screens...
|
||||
"perspective" - set the perspective viewing
|
||||
"reset" - reset the graphics manager to the initial state
|
||||
"color" - rgb color for clearing
|
||||
"profile #" - turn on/off profiling (time per frame)
|
||||
- # == 0 : turn off
|
||||
- # == 1 : turn on
|
||||
- # == 2 : turn on without image caching
|
||||
|
||||
"view" - set the viewpoint
|
||||
"fogmode" - set the fog mode
|
||||
- 0 : FOG_OFF
|
||||
- 1 : FOG_LINEAR (from begin to end)
|
||||
- 2 : FOG_EXP (density) (default)
|
||||
- 3 : FOG_EXP2 (density)
|
||||
"fog" - set the fog density or begin/end of the fog
|
||||
"fogcolor" - the fog color
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN gemwin : public CPPExtern
|
||||
{
|
||||
CPPEXTERN_HEADER(gemwin, CPPExtern);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
gemwin(t_floatarg framespersecond);
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~gemwin();
|
||||
|
||||
void bangMess();
|
||||
void intMess(int state);
|
||||
void renderMess();
|
||||
void titleMess(t_symbol* s);
|
||||
void createMess(t_symbol* s);
|
||||
void stereoMess(int mode);
|
||||
void bufferMess(int buf);
|
||||
void dimensionsMess(int width, int height);
|
||||
void fullscreenMess(int on);
|
||||
void menuBarMess(int on);
|
||||
void secondscreenMess(int on);
|
||||
void offsetMess(int x, int y);
|
||||
void colorMess(float red, float green, float blue, float alpha);
|
||||
void clearmaskMess(float bitmask);
|
||||
void ambientMess(float red, float green, float blue, float alpha);
|
||||
void specularMess(float red, float green, float blue, float alpha);
|
||||
void shininessMess(float val);
|
||||
|
||||
void fogModeMess(int mode);
|
||||
void fogDensityMess(float val);
|
||||
void fogRangeMess(float start, float end);
|
||||
void fogColorMess(float red, float green, float blue, float alpha);
|
||||
void cursorMess(float setting);
|
||||
void topmostMess(float settting);
|
||||
void blurMess(float setting);
|
||||
void fpsMess();
|
||||
void fsaaMess(int value);
|
||||
t_outlet *m_FrameRate;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// Static member functions
|
||||
static void titleMessCallback(void *data, t_symbol* s);
|
||||
static void createMessCallback(void *data, t_symbol* s);
|
||||
static void createStereoMessCallback(void *data);
|
||||
static void colorMessCallback(void *data, t_symbol*,int,t_atom*);
|
||||
static void ambientMessCallback(void *data, t_symbol*,int,t_atom*);
|
||||
static void specularMessCallback(void *data, t_symbol*,int,t_atom*);
|
||||
static void fogMessCallback(void *, t_symbol *, int argc, t_atom *argv);
|
||||
static void fogColorMessCallback(void *, t_symbol*,int,t_atom*);
|
||||
|
||||
// just call GemMan directly
|
||||
static void destroyMessCallback(void *);
|
||||
static void printMessCallback(void *);
|
||||
static void profileMessCallback(void *, t_float state);
|
||||
static void resetMessCallback(void *);
|
||||
static void lightingMessCallback(void *, t_float state);
|
||||
static void borderMessCallback(void *, t_float state);
|
||||
static void frameMessCallback(void *, t_float framesPerSecond);
|
||||
static void perspectiveMessCallback(void *, t_symbol *, int argc, t_atom *argv);
|
||||
static void viewMessCallback(void *, t_symbol *, int argc, t_atom *argv);
|
||||
static void stereoMessCallback(void *data, t_float state);
|
||||
static void stereoFocMessCallback(void *, t_float state);
|
||||
static void stereoSepMessCallback(void *, t_float state);
|
||||
static void stereoLineMessCallback(void *, t_float state);
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
68
Gem/src/Controls/render_trigger.cpp
Normal file
68
Gem/src/Controls/render_trigger.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "render_trigger.h"
|
||||
|
||||
CPPEXTERN_NEW(render_trigger);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// render_trigger
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
render_trigger :: render_trigger()
|
||||
{
|
||||
m_preOut = outlet_new(this->x_obj, 0);
|
||||
m_postOut = outlet_new(this->x_obj, 0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
render_trigger :: ~render_trigger()
|
||||
{
|
||||
outlet_free(m_preOut);
|
||||
outlet_free(m_postOut);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// render
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void render_trigger :: render(GemState *)
|
||||
{
|
||||
outlet_bang(m_preOut);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// postrender
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void render_trigger :: postrender(GemState *)
|
||||
{
|
||||
outlet_bang(m_postOut);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// static member function
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void render_trigger :: obj_setupCallback(t_class *)
|
||||
{ }
|
||||
63
Gem/src/Controls/render_trigger.h
Normal file
63
Gem/src/Controls/render_trigger.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Send out a bang on pre and post render
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_CONTROLS_RENDER_TRIGGER_H_
|
||||
#define _INCLUDE__GEM_CONTROLS_RENDER_TRIGGER_H_
|
||||
|
||||
#include "Base/GemBase.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
render_trigger
|
||||
|
||||
Send out a bang on pre and post render
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
"render_triggerstate" - whether to use render_trigger blending
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN render_trigger : public GemBase
|
||||
{
|
||||
CPPEXTERN_HEADER(render_trigger, GemBase);
|
||||
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
render_trigger();
|
||||
|
||||
protected:
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~render_trigger();
|
||||
|
||||
//////////
|
||||
// Push the current state
|
||||
virtual void render(GemState *state);
|
||||
|
||||
//////////
|
||||
// Pop the state
|
||||
virtual void postrender(GemState *state);
|
||||
|
||||
//////////
|
||||
t_outlet *m_preOut; // bang for the pre render
|
||||
|
||||
//////////
|
||||
t_outlet *m_postOut; // bang for the post render
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
64
Gem/src/Gem/Cache.cpp
Normal file
64
Gem/src/Gem/Cache.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "Cache.h"
|
||||
#include "Controls/gemhead.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemCache
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemCache :: GemCache(gemhead *parent)
|
||||
: dirty(true), resendImage(false), vertexDirty(false),
|
||||
m_parent(parent), m_magic(GEMCACHE_MAGIC)
|
||||
{
|
||||
}
|
||||
GemCache :: GemCache(const GemCache&org)
|
||||
: dirty(org.dirty), resendImage(org.resendImage), vertexDirty(org.vertexDirty),
|
||||
m_parent(org.m_parent), m_magic(GEMCACHE_MAGIC)
|
||||
{
|
||||
}
|
||||
void GemCache :: reset(gemhead *parent)
|
||||
{
|
||||
dirty =true;
|
||||
resendImage=false;
|
||||
vertexDirty=false;
|
||||
m_parent =parent;
|
||||
m_magic =GEMCACHE_MAGIC;
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemCache :: ~GemCache(void)
|
||||
{
|
||||
m_magic=0xFFFFFFF;
|
||||
m_parent=NULL;
|
||||
}
|
||||
|
||||
GemCache&GemCache::operator=(const GemCache&org) {
|
||||
dirty=org.dirty;
|
||||
resendImage=org.resendImage;
|
||||
vertexDirty=org.vertexDirty;
|
||||
m_parent=org.m_parent;
|
||||
m_magic=GEMCACHE_MAGIC;
|
||||
return *this;
|
||||
}
|
||||
74
Gem/src/Gem/Cache.h
Normal file
74
Gem/src/Gem/Cache.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The state to pass among GEM objects
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_CACHE_H_
|
||||
#define _INCLUDE__GEM_GEM_CACHE_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
class gemhead;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemCache
|
||||
|
||||
The cache to pass among GEM objects
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
#define GEMCACHE_MAGIC 0x1234567
|
||||
class GEM_EXTERN GemCache
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemCache(gemhead *parent);
|
||||
|
||||
GemCache(const GemCache&);
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemCache(void);
|
||||
|
||||
|
||||
virtual GemCache& operator=(const GemCache&);
|
||||
|
||||
//////////
|
||||
// Was a modification made which will void a display list?
|
||||
bool dirty;
|
||||
|
||||
//////////
|
||||
// Should the image be resent?
|
||||
bool resendImage;
|
||||
|
||||
//////////
|
||||
// has the Vertex-Array changed?
|
||||
bool vertexDirty;
|
||||
|
||||
//////////
|
||||
// re-set (like creation, but without instantiating
|
||||
void reset(gemhead*parent);
|
||||
|
||||
//////////
|
||||
gemhead *m_parent;
|
||||
|
||||
//////////
|
||||
// indicates a valid cache
|
||||
int m_magic;
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
33
Gem/src/Gem/ContextData.cpp
Normal file
33
Gem/src/Gem/ContextData.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include "ContextData.h"
|
||||
#include "Base/GemContext.h"
|
||||
|
||||
using namespace gem;
|
||||
|
||||
/* LATER, when we have multiple contexts, this should really be "-1" or such
|
||||
*/
|
||||
const int ContextDataBase::INVALID_CONTEXT=0;
|
||||
|
||||
int ContextDataBase::getCurContext(void) {
|
||||
/* this should get an integer-index of the current context from GemContext */
|
||||
int id=0;
|
||||
id=gem::Context::getContextId();
|
||||
return id;
|
||||
}
|
||||
|
||||
ContextDataBase::~ContextDataBase(void) {
|
||||
}
|
||||
149
Gem/src/Gem/ContextData.h
Normal file
149
Gem/src/Gem/ContextData.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
data specific to a rendering context
|
||||
|
||||
Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_CONTEXTDATA_H_
|
||||
#define _INCLUDE__GEM_GEM_CONTEXTDATA_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
#include <vector>
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
ContextData
|
||||
|
||||
rendering context specific data
|
||||
this is heavily inspired by VrJuggler
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
several things in openGL like display-lists are context dependent
|
||||
if we have multiple contexts, such values most be generated for each context
|
||||
ContextData provides a generic (templated) datatype for this
|
||||
|
||||
LATER (SOONER) think about splitting the render() into a context-specific section that
|
||||
set's up display-lists,... and a draw() function that just calls the pre-generated values
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
namespace gem {
|
||||
|
||||
class GEM_EXTERN ContextDataBase {
|
||||
protected:
|
||||
static const int INVALID_CONTEXT;
|
||||
virtual int getCurContext(void);
|
||||
virtual ~ContextDataBase(void);
|
||||
};
|
||||
|
||||
|
||||
template<class ContextDataType = int>
|
||||
class GEM_EXTERN ContextData : ContextDataBase
|
||||
{
|
||||
private:
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
ContextData(void) : m_haveDefaultValue(false) {;}
|
||||
|
||||
ContextData(ContextDataType v) : m_haveDefaultValue(true), m_defaultValue(v) {;}
|
||||
|
||||
virtual ~ContextData() {
|
||||
m_ContextDataVector.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the context-specific value
|
||||
*
|
||||
* @usage ContextData<GLenum>m_fun; m_fun=GL_FUNC_ADD;
|
||||
*
|
||||
* @pre We are in a draw process.
|
||||
* @note Should only be called from the draw function.
|
||||
* Results are un-defined for other functions.
|
||||
*/
|
||||
virtual operator ContextDataType()
|
||||
{
|
||||
return (*getPtrToCur());
|
||||
}
|
||||
|
||||
/**
|
||||
* assigns a value to the correct context
|
||||
*
|
||||
* @pre We are in a draw process.
|
||||
* @note Should only be called from the draw function.
|
||||
* Results are un-defined for other functions.
|
||||
*/
|
||||
virtual ContextDataType&operator = (ContextDataType value)
|
||||
{
|
||||
/* simplistic approach to handle out-of-context assignments:
|
||||
* assign the value to all context instances
|
||||
*/
|
||||
if(INVALID_CONTEXT==getCurContext()) {
|
||||
doSetAll(value);
|
||||
}
|
||||
|
||||
return (*getPtrToCur()=value);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_haveDefaultValue;
|
||||
ContextDataType m_defaultValue;
|
||||
std::vector<ContextDataType*> m_ContextDataVector;
|
||||
|
||||
|
||||
/* Makes sure that the vector is at least requiredSize large */
|
||||
void checkSize(unsigned int requiredSize)
|
||||
{
|
||||
if(requiredSize > m_ContextDataVector.size())
|
||||
{
|
||||
m_ContextDataVector.reserve(requiredSize); // Resize smartly
|
||||
while(m_ContextDataVector.size() < requiredSize) // Add any new items needed
|
||||
{
|
||||
if(m_haveDefaultValue) {
|
||||
m_ContextDataVector.push_back(new ContextDataType(m_defaultValue));
|
||||
} else {
|
||||
m_ContextDataVector.push_back(new ContextDataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the correct data element in the current context.
|
||||
*
|
||||
* @pre We are in the draw function.
|
||||
* @post Synchronized.
|
||||
* @note ASSERT: Same context is rendered by same thread each time.
|
||||
*/
|
||||
ContextDataType* getPtrToCur(void)
|
||||
{
|
||||
// Get current context
|
||||
int context_id = getCurContext();
|
||||
// Cache ref for better performance
|
||||
checkSize(context_id+1); // Make sure we are large enough (+1 since we have index)
|
||||
|
||||
return m_ContextDataVector[context_id];
|
||||
}
|
||||
|
||||
void doSetAll(ContextDataType v)
|
||||
{
|
||||
unsigned int i=0;
|
||||
for(i=0; i< m_ContextDataVector.size(); i++) {
|
||||
*m_ContextDataVector[i]=v;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // for header file
|
||||
327
Gem/src/Gem/Dylib.cpp
Normal file
327
Gem/src/Gem/Dylib.cpp
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-2000 Mark Danks.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2002 James Tittle & Chris Clepper
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
// a wrapper for calling Pd's sys_register_loader()
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable: 4091)
|
||||
# define snprintf _snprintf
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#include "Dylib.h"
|
||||
#include "Files.h"
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined __linux__ || defined __APPLE__ || defined __FreeBSD_kernel__
|
||||
#include <unistd.h>
|
||||
# define DL_OPEN
|
||||
#endif
|
||||
|
||||
#ifdef DL_OPEN
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if defined _WIN32
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class GemDylibHandle {
|
||||
public:
|
||||
std::string fullname;
|
||||
#ifdef DL_OPEN
|
||||
void * dlhandle;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
HINSTANCE w32handle;
|
||||
#endif
|
||||
int dummy2;
|
||||
|
||||
|
||||
GemDylibHandle(void) :
|
||||
fullname(std::string()),
|
||||
#ifdef DL_OPEN
|
||||
dlhandle(NULL),
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
w32handle(NULL),
|
||||
#endif
|
||||
dummy2(0)
|
||||
{;}
|
||||
|
||||
~GemDylibHandle(void) {
|
||||
close();
|
||||
}
|
||||
|
||||
static std::string getFullfilename(const t_canvas*canvas, const char*filename, const char*ext) {
|
||||
std::string fullname_;
|
||||
|
||||
char buf[MAXPDSTRING];
|
||||
char*bufptr;
|
||||
int fd=0;
|
||||
if ((fd=canvas_open(const_cast<t_canvas*>(canvas), filename, ext, buf, &bufptr, MAXPDSTRING, 1))>=0){
|
||||
gem::files::close(fd);
|
||||
fullname_=buf;
|
||||
fullname_+="/";
|
||||
fullname_+=bufptr;
|
||||
} else {
|
||||
if(canvas) {
|
||||
canvas_makefilename(const_cast<t_canvas*>(canvas), const_cast<char*>(filename), buf, MAXPDSTRING);
|
||||
fullname_=buf;
|
||||
} else {
|
||||
return std::string("");
|
||||
}
|
||||
}
|
||||
return fullname_;
|
||||
}
|
||||
|
||||
static GemDylibHandle*open(const std::string filename) {
|
||||
GemDylibHandle*handle=new GemDylibHandle();
|
||||
|
||||
char buf[MAXPDSTRING];
|
||||
if(filename.empty()) {
|
||||
throw(GemException(std::string("No DyLib name given!")));
|
||||
}
|
||||
|
||||
sys_bashfilename(filename.c_str(), buf);
|
||||
|
||||
#ifdef DL_OPEN
|
||||
handle->dlhandle=dlopen(filename.c_str(), RTLD_NOW);
|
||||
if(handle->dlhandle) {
|
||||
handle->fullname=filename;
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
UINT errorboxflags=SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
SetLastError(0);
|
||||
handle->w32handle=LoadLibrary(buf);
|
||||
DWORD errorNumber = GetLastError();
|
||||
errorboxflags=SetErrorMode(errorboxflags);
|
||||
if(handle->w32handle) {
|
||||
handle->fullname=filename;
|
||||
return handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
delete handle;
|
||||
handle=NULL;
|
||||
|
||||
std::string errormsg;
|
||||
#ifdef DL_OPEN
|
||||
errormsg=dlerror();
|
||||
if(!errormsg.empty()) {
|
||||
std::string error="dlerror '";
|
||||
error+=errormsg;
|
||||
error+="'";
|
||||
throw(GemException(error));
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
LPVOID lpErrorMessage=NULL;
|
||||
if(errorNumber) {
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errorNumber,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpErrorMessage,
|
||||
0, NULL );
|
||||
}
|
||||
std::cerr << "GemDylib failed: #"<<errorNumber<<": ";
|
||||
if(lpErrorMessage) {
|
||||
std::cerr<<(const char*)lpErrorMessage;
|
||||
}else {
|
||||
std::cerr<<"(unknown)";
|
||||
}
|
||||
std::cerr<<std::endl;
|
||||
std::string error = "DLLerror(";
|
||||
char errbuf[10];
|
||||
snprintf(errbuf, 10, "0x%x", errorNumber);
|
||||
errbuf[10-1]=0;
|
||||
error+=errbuf;
|
||||
error+=")";
|
||||
if(lpErrorMessage) {
|
||||
error+=(const char*)lpErrorMessage;
|
||||
}
|
||||
std::cerr << "GemDylib throwing: "<< error << std::endl;
|
||||
throw(GemException(std::string(error)));
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GemDylibHandle*open(const CPPExtern*obj, const std::string filename, const std::string extension) {
|
||||
const t_canvas*canvas=(obj)?(canvas=const_cast<CPPExtern*>(obj)->getCanvas()):0;
|
||||
const char*ext=extension.c_str();
|
||||
|
||||
//std::string fullname=getFullfilename(canvas, filename.c_str(), ext);
|
||||
std::string fullname=gem::files::getFullpath(filename+ext, obj);
|
||||
if(fullname.empty()) {
|
||||
//fullname=getFullfilename(canvas, filename.c_str(), GemDylibHandle::defaultExtension.c_str());
|
||||
fullname=gem::files::getFullpath(filename+GemDylibHandle::defaultExtension, obj);
|
||||
}
|
||||
|
||||
if(fullname.empty()) {
|
||||
std::string error="couldn't find '";
|
||||
error+=filename;
|
||||
error+="'.'";
|
||||
error+=ext;
|
||||
error+="'";
|
||||
throw(GemException(error));
|
||||
}
|
||||
|
||||
return open(fullname);
|
||||
}
|
||||
|
||||
static const std::string defaultExtension;
|
||||
|
||||
void close(void) {
|
||||
#ifdef DL_OPEN
|
||||
if(dlhandle)
|
||||
dlclose(dlhandle);
|
||||
dlhandle=NULL;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
if(w32handle)
|
||||
FreeLibrary(w32handle);
|
||||
w32handle=NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const std::string GemDylibHandle::defaultExtension =
|
||||
#ifdef _WIN32
|
||||
std::string(".dll")
|
||||
#elif defined DL_OPEN
|
||||
std::string(".so")
|
||||
#else
|
||||
std::string("")
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
GemDylib::GemDylib(const CPPExtern*obj, const std::string filename, const std::string extension)
|
||||
throw (GemException) :
|
||||
m_handle(0) {
|
||||
m_handle=GemDylibHandle::open(obj, filename, extension);
|
||||
if(NULL==m_handle) {
|
||||
std::string err="unable to open '";
|
||||
err+=filename;
|
||||
if(!extension.empty()) {
|
||||
err+=".";
|
||||
err+=extension;
|
||||
}
|
||||
err+="'";
|
||||
throw GemException(err);
|
||||
}
|
||||
}
|
||||
|
||||
GemDylib::GemDylib(const std::string filename, const std::string extension) throw (GemException) : m_handle(0) {
|
||||
m_handle=GemDylibHandle::open(0, filename, extension);
|
||||
if(NULL==m_handle) {
|
||||
std::string err="unable to open '";
|
||||
err+=filename;
|
||||
if(!extension.empty()) {
|
||||
err+=".";
|
||||
err+=extension;
|
||||
}
|
||||
err+="'";
|
||||
throw GemException(err);
|
||||
}
|
||||
}
|
||||
|
||||
GemDylib::GemDylib(const GemDylib&org) : m_handle(NULL) {
|
||||
std::string filename=org.m_handle->fullname;
|
||||
m_handle=GemDylibHandle::open(filename);
|
||||
if(NULL==m_handle) {
|
||||
std::string err="unable to open '";
|
||||
err+=filename;
|
||||
err+="'";
|
||||
throw GemException(err);
|
||||
}
|
||||
}
|
||||
|
||||
GemDylib::~GemDylib(void) {
|
||||
if(m_handle)
|
||||
delete m_handle;
|
||||
m_handle=NULL;
|
||||
}
|
||||
|
||||
GemDylib& GemDylib::operator=(const GemDylib&org) {
|
||||
if(m_handle)
|
||||
delete m_handle;
|
||||
m_handle=NULL;
|
||||
if(org.m_handle) {
|
||||
m_handle=GemDylibHandle::open(org.m_handle->fullname);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
GemDylib::function_t GemDylib::proc(const std::string procname) {
|
||||
function_t result=NULL;
|
||||
// if(NULL==procname)return NULL;
|
||||
#ifdef DL_OPEN
|
||||
dlerror();
|
||||
if(m_handle->dlhandle)
|
||||
result=(function_t)(dlsym(m_handle->dlhandle, procname.c_str()));
|
||||
if(NULL!=result)return result;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
if(m_handle->w32handle)
|
||||
result=(function_t)(GetProcAddress(m_handle->w32handle, procname.c_str()));
|
||||
if(NULL!=result)return result;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GemDylib::run(const std::string procname) {
|
||||
function_t runproc=proc(procname);
|
||||
if(runproc) {
|
||||
(runproc)();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GemDylib::LoadLib(const std::string basefilename, const std::string extension, const std::string procname) {
|
||||
try {
|
||||
GemDylib*dylib=new GemDylib(basefilename, extension);
|
||||
if(NULL!=dylib) {
|
||||
dylib->run(procname);
|
||||
return true;
|
||||
}
|
||||
} catch (GemException&x) {
|
||||
std::cerr << "GemDylib::LoadLib: "<<x.what()<<std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const std::string GemDylib::getDefaultExtension(void) {
|
||||
return GemDylibHandle::defaultExtension;
|
||||
}
|
||||
68
Gem/src/Gem/Dylib.h
Normal file
68
Gem/src/Gem/Dylib.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
- registers a loader with Pd
|
||||
|
||||
Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_DYLIB_H_
|
||||
#define _INCLUDE__GEM_GEM_DYLIB_H_
|
||||
|
||||
#include "Gem/Exception.h"
|
||||
|
||||
|
||||
/* an opaque handle to the platform specific library handle */
|
||||
class GemDylibHandle;
|
||||
class CPPExtern;
|
||||
|
||||
class GEM_EXTERN GemDylib {
|
||||
private:
|
||||
GemDylibHandle*m_handle;
|
||||
|
||||
public:
|
||||
GemDylib(const CPPExtern*obj,
|
||||
const std::string libname,
|
||||
const std::string extension=std::string("")
|
||||
) throw(GemException);
|
||||
GemDylib(const std::string libname,
|
||||
const std::string extension=std::string("")
|
||||
) throw(GemException);
|
||||
|
||||
GemDylib(const GemDylib&);
|
||||
|
||||
virtual ~GemDylib(void);
|
||||
|
||||
typedef void (*function_t)(void);
|
||||
|
||||
virtual GemDylib& operator=(const GemDylib&);
|
||||
|
||||
// if void<procname>(void) exists in dylib, run it and return "true"
|
||||
// else return false;
|
||||
bool run(const std::string procname);
|
||||
|
||||
// if <procname> exists in dylib, return it, else return NULL
|
||||
function_t proc(const std::string procname);
|
||||
|
||||
public:
|
||||
/**
|
||||
* LoadLib(): convenience function that searches a library named <baselibname> and then runs <procname>()
|
||||
* if "extension" is NULL, a platform-specific default is used
|
||||
* on success "true" is returned, else "false
|
||||
*/
|
||||
static bool LoadLib(const std::string procname,
|
||||
const std::string baselibname,
|
||||
const std::string fileext=std::string(""));
|
||||
|
||||
|
||||
static const std::string getDefaultExtension(void);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
466
Gem/src/Gem/Event.cpp
Normal file
466
Gem/src/Gem/Event.cpp
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "m_pd.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// The callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
struct CallbackList{
|
||||
CallbackList() : data(NULL), func(NULL), next(NULL) {}
|
||||
void *data;
|
||||
void *func;
|
||||
CallbackList *next;
|
||||
};
|
||||
|
||||
static CallbackList *s_motionList = NULL;
|
||||
static CallbackList *s_buttonList = NULL;
|
||||
static CallbackList *s_wheelList = NULL;
|
||||
static CallbackList *s_keyboardList = NULL;
|
||||
static CallbackList *s_resizeList = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Motion callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void setMotionCallback(MOTION_CB callback, void *data)
|
||||
{
|
||||
CallbackList *newCallback = new CallbackList;
|
||||
newCallback->data = data;
|
||||
newCallback->func = (void *)callback;
|
||||
|
||||
if (!s_motionList)
|
||||
s_motionList = newCallback;
|
||||
else
|
||||
{
|
||||
CallbackList *theList = s_motionList;
|
||||
while(theList->next)
|
||||
theList = theList->next;
|
||||
theList->next = newCallback;
|
||||
}
|
||||
}
|
||||
GEM_EXTERN void removeMotionCallback(MOTION_CB callback, void *data)
|
||||
{
|
||||
CallbackList *theList = s_motionList;
|
||||
if (!theList)
|
||||
return;
|
||||
else if (theList->func == (void *)callback &&
|
||||
theList->data == data)
|
||||
{
|
||||
s_motionList = theList->next;
|
||||
delete theList;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(theList->next)
|
||||
{
|
||||
if (theList->next->func == (void *)callback &&
|
||||
theList->next->data == data)
|
||||
{
|
||||
CallbackList *holder = theList->next;
|
||||
theList->next = holder->next;
|
||||
delete holder;
|
||||
return;
|
||||
}
|
||||
theList = theList->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Button callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void setButtonCallback(BUTTON_CB callback, void *data)
|
||||
{
|
||||
CallbackList *newCallback = new CallbackList;
|
||||
|
||||
newCallback->data = data;
|
||||
newCallback->func = (void *)callback;
|
||||
|
||||
if (!s_buttonList)
|
||||
s_buttonList = newCallback;
|
||||
else
|
||||
{
|
||||
CallbackList *theList = s_buttonList;
|
||||
while(theList->next)
|
||||
theList = theList->next;
|
||||
theList->next = newCallback;
|
||||
}
|
||||
}
|
||||
GEM_EXTERN void removeButtonCallback(BUTTON_CB callback, void *data)
|
||||
{
|
||||
CallbackList *theList = s_buttonList;
|
||||
if (!theList)
|
||||
return;
|
||||
else if (theList->func == (void *)callback &&
|
||||
theList->data == data)
|
||||
{
|
||||
s_buttonList = theList->next;
|
||||
delete theList;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(theList->next)
|
||||
{
|
||||
if (theList->next->func == (void *)callback &&
|
||||
theList->next->data == data)
|
||||
{
|
||||
CallbackList *holder = theList->next;
|
||||
theList->next = holder->next;
|
||||
delete holder;
|
||||
return;
|
||||
}
|
||||
theList = theList->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Wheel callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void setWheelCallback(WHEEL_CB callback, void *data)
|
||||
{
|
||||
CallbackList *newCallback = new CallbackList;
|
||||
newCallback->data = data;
|
||||
newCallback->func = (void *)callback;
|
||||
|
||||
if (!s_wheelList)
|
||||
s_wheelList = newCallback;
|
||||
else
|
||||
{
|
||||
CallbackList *theList = s_wheelList;
|
||||
while(theList->next)
|
||||
theList = theList->next;
|
||||
theList->next = newCallback;
|
||||
}
|
||||
}
|
||||
GEM_EXTERN void removeWheelCallback(WHEEL_CB callback, void *data)
|
||||
{
|
||||
CallbackList *theList = s_wheelList;
|
||||
if (!theList)
|
||||
return;
|
||||
else if (theList->func == (void *)callback &&
|
||||
theList->data == data)
|
||||
{
|
||||
s_wheelList = theList->next;
|
||||
delete theList;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(theList->next)
|
||||
{
|
||||
if (theList->next->func == (void *)callback &&
|
||||
theList->next->data == data)
|
||||
{
|
||||
CallbackList *holder = theList->next;
|
||||
theList->next = holder->next;
|
||||
delete holder;
|
||||
return;
|
||||
}
|
||||
theList = theList->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Keyboard callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void setKeyboardCallback(KEYBOARD_CB callback, void *data)
|
||||
{
|
||||
CallbackList *newCallback = new CallbackList;
|
||||
newCallback->data = data;
|
||||
newCallback->func = (void *)callback;
|
||||
|
||||
if (!s_keyboardList)
|
||||
s_keyboardList = newCallback;
|
||||
else
|
||||
{
|
||||
CallbackList *theList = s_keyboardList;
|
||||
while(theList->next)
|
||||
theList = theList->next;
|
||||
theList->next = newCallback;
|
||||
}
|
||||
}
|
||||
GEM_EXTERN void removeKeyboardCallback(KEYBOARD_CB callback, void *data)
|
||||
{
|
||||
CallbackList *theList = s_keyboardList;
|
||||
if (!theList)
|
||||
return;
|
||||
else if (theList->func == (void *)callback &&
|
||||
theList->data == data)
|
||||
{
|
||||
s_keyboardList = theList->next;
|
||||
delete theList;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(theList->next)
|
||||
{
|
||||
if (theList->next->func == (void *)callback &&
|
||||
theList->next->data == data)
|
||||
{
|
||||
CallbackList *holder = theList->next;
|
||||
theList->next = holder->next;
|
||||
delete holder;
|
||||
return;
|
||||
}
|
||||
theList = theList->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Resize callbacks
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void setResizeCallback(RESIZE_CB callback, void *data)
|
||||
{
|
||||
CallbackList *newCallback = new CallbackList;
|
||||
newCallback->data = data;
|
||||
newCallback->func = (void *)callback;
|
||||
|
||||
if (!s_resizeList)
|
||||
s_resizeList = newCallback;
|
||||
else
|
||||
{
|
||||
CallbackList *theList = s_resizeList;
|
||||
while(theList->next)
|
||||
theList = theList->next;
|
||||
theList->next = newCallback;
|
||||
}
|
||||
}
|
||||
GEM_EXTERN void removeResizeCallback(RESIZE_CB callback, void *data)
|
||||
{
|
||||
CallbackList *theList = s_resizeList;
|
||||
if (!theList)
|
||||
return;
|
||||
else if (theList->func == (void *)callback &&
|
||||
theList->data == data)
|
||||
{
|
||||
s_resizeList = theList->next;
|
||||
delete theList;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(theList->next)
|
||||
{
|
||||
if (theList->next->func == (void *)callback &&
|
||||
theList->next->data == data)
|
||||
{
|
||||
CallbackList *holder = theList->next;
|
||||
theList->next = holder->next;
|
||||
delete holder;
|
||||
return;
|
||||
}
|
||||
theList = theList->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Trigger queue
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef enum {
|
||||
NONE,
|
||||
MOTION,
|
||||
BUTTON,
|
||||
WHEEL,
|
||||
KEYBOARD,
|
||||
RESIZE
|
||||
} gem_event_t;
|
||||
|
||||
typedef struct _event_queue_item {
|
||||
gem_event_t type;
|
||||
struct _event_queue_item*next;
|
||||
char*string;
|
||||
int x;
|
||||
int y;
|
||||
int state;
|
||||
int axis;
|
||||
int value;
|
||||
int which;
|
||||
} gem_event_queue_item_t;
|
||||
|
||||
typedef struct _gem_event_queue_t{
|
||||
gem_event_queue_item_t*first;
|
||||
gem_event_queue_item_t*last;
|
||||
t_clock *clock;
|
||||
|
||||
} gem_event_queue_t;
|
||||
|
||||
gem_event_queue_t*event_queue = NULL;
|
||||
|
||||
static gem_event_queue_item_t* createEvent(gem_event_t type, char*string, int x, int y, int state, int axis, int value, int which)
|
||||
{
|
||||
gem_event_queue_item_t*ret=new gem_event_queue_item_t;
|
||||
ret->type=type;
|
||||
ret->next=NULL;
|
||||
ret->string=string;
|
||||
ret->x=x;
|
||||
ret->y=y;
|
||||
ret->state=state;
|
||||
ret->axis=axis;
|
||||
ret->value=value;
|
||||
ret->which=which;
|
||||
|
||||
return ret;
|
||||
}
|
||||
static void deleteEvent( gem_event_queue_item_t* event) {
|
||||
if(event == event_queue->first) {
|
||||
event_queue->first=event->next;
|
||||
}
|
||||
|
||||
if(event == event_queue->last) {
|
||||
event_queue->last=NULL;
|
||||
}
|
||||
|
||||
event->type=NONE;
|
||||
event->next=NULL;
|
||||
event->string=0;
|
||||
event->x=0;
|
||||
event->y=0;
|
||||
event->state=0;
|
||||
event->axis=0;
|
||||
event->value=0;
|
||||
event->which=0;
|
||||
|
||||
delete event;
|
||||
}
|
||||
|
||||
static void eventClock(void *x);
|
||||
|
||||
static void addEvent(gem_event_t type, char*string, int x, int y, int state, int axis, int value, int which) {
|
||||
if (NULL==event_queue) {
|
||||
event_queue=new gem_event_queue_t;
|
||||
event_queue->first=NULL;
|
||||
event_queue->last =NULL;
|
||||
event_queue->clock=clock_new(NULL, reinterpret_cast<t_method>(eventClock));
|
||||
}
|
||||
gem_event_queue_item_t*item=createEvent(type, string, x, y, state, axis, value, which);
|
||||
if(NULL==event_queue->first) {
|
||||
event_queue->first=item;
|
||||
}
|
||||
if(event_queue->last) {
|
||||
event_queue->last->next=item;
|
||||
}
|
||||
event_queue->last=item;
|
||||
|
||||
clock_delay(event_queue->clock, 0);
|
||||
}
|
||||
|
||||
static void dequeueEvents(void) {
|
||||
CallbackList *theList=NULL;
|
||||
if (NULL==event_queue) {
|
||||
error("dequeue NULL queue");
|
||||
return;
|
||||
}
|
||||
gem_event_queue_item_t*events = event_queue->first;
|
||||
if(NULL==events) {
|
||||
error("dequeue empty queue");
|
||||
return;
|
||||
}
|
||||
while(events) {
|
||||
|
||||
switch(events->type) {
|
||||
case( MOTION):
|
||||
theList = s_motionList;
|
||||
while(theList)
|
||||
{
|
||||
MOTION_CB callback = (MOTION_CB)theList->func;
|
||||
(*callback)(events->x, events->y, theList->data);
|
||||
theList = theList->next;
|
||||
}
|
||||
break;
|
||||
case( BUTTON):
|
||||
theList = s_buttonList;
|
||||
while(theList)
|
||||
{
|
||||
BUTTON_CB callback = (BUTTON_CB)theList->func;
|
||||
(*callback)(events->which, events->state, events->x, events->y, theList->data);
|
||||
theList = theList->next;
|
||||
}
|
||||
break;
|
||||
case( WHEEL):
|
||||
theList = s_wheelList;
|
||||
while(theList)
|
||||
{
|
||||
WHEEL_CB callback = (WHEEL_CB)theList->func;
|
||||
(*callback)(events->axis, events->value, theList->data);
|
||||
theList = theList->next;
|
||||
}
|
||||
break;
|
||||
case( KEYBOARD):
|
||||
theList = s_keyboardList;
|
||||
while(theList)
|
||||
{
|
||||
KEYBOARD_CB callback = (KEYBOARD_CB)theList->func;
|
||||
(*callback)(events->string, events->value, events->state, theList->data);
|
||||
theList = theList->next;
|
||||
}
|
||||
break;
|
||||
case( RESIZE):
|
||||
theList = s_resizeList;
|
||||
while(theList)
|
||||
{
|
||||
RESIZE_CB callback = (RESIZE_CB)theList->func;
|
||||
(*callback)(events->x, events->y, theList->data);
|
||||
theList = theList->next;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
gem_event_queue_item_t*old = events;
|
||||
events=events->next;
|
||||
|
||||
deleteEvent(old);
|
||||
}
|
||||
}
|
||||
|
||||
static void eventClock(void *x)
|
||||
{
|
||||
dequeueEvents();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Trigger events
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GEM_EXTERN void triggerMotionEvent(int x, int y)
|
||||
{
|
||||
addEvent(MOTION, NULL, x, y, 0, 0, 0, 0);
|
||||
}
|
||||
GEM_EXTERN void triggerButtonEvent(int which, int state, int x, int y)
|
||||
{
|
||||
addEvent(BUTTON, NULL, x, y, state, 0, 0, which);
|
||||
}
|
||||
GEM_EXTERN void triggerWheelEvent(int axis, int value)
|
||||
{
|
||||
addEvent(WHEEL, NULL, 0, 0, 0, axis, value, 0);
|
||||
}
|
||||
GEM_EXTERN void triggerKeyboardEvent(char *string, int value, int state)
|
||||
{
|
||||
addEvent(KEYBOARD, gensym(string)->s_name, 0, 0, state, 0, value, 0);
|
||||
}
|
||||
GEM_EXTERN void triggerResizeEvent(int xSize, int ySize)
|
||||
{
|
||||
addEvent(RESIZE, NULL, xSize, ySize, 0, 0, 0, 0);
|
||||
}
|
||||
104
Gem/src/Gem/Event.h
Normal file
104
Gem/src/Gem/Event.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
get keyboard/mouse callbacks
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_EVENT_H_
|
||||
#define _INCLUDE__GEM_GEM_EVENT_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Mouse motion callback
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
typedef void (*MOTION_CB)(int, int, void *);
|
||||
//////////
|
||||
// Set a mouse motion callback
|
||||
GEM_EXTERN extern void setMotionCallback(MOTION_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Remove a mouse motion callback
|
||||
GEM_EXTERN extern void removeMotionCallback(MOTION_CB callback, void *data);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Mouse button callback
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
typedef void (*BUTTON_CB)(int, int, int, int, void *);
|
||||
//////////
|
||||
// Set a button callback
|
||||
// which == 0 == left
|
||||
// which == 1 == middle
|
||||
// which == 2 == right
|
||||
GEM_EXTERN extern void setButtonCallback(BUTTON_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Remove a button callback
|
||||
GEM_EXTERN extern void removeButtonCallback(BUTTON_CB callback, void *data);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Mouse wheel callback
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
typedef void (*WHEEL_CB)(int, int, void *);
|
||||
//////////
|
||||
// Set a wheel callback
|
||||
GEM_EXTERN extern void setWheelCallback(WHEEL_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Remove a wheel callback
|
||||
GEM_EXTERN extern void removeWheelCallback(WHEEL_CB callback, void *data);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Keyboard callback
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
typedef void (*KEYBOARD_CB)(char *,int, int, void *);
|
||||
//////////
|
||||
// Set a keyboard callback
|
||||
GEM_EXTERN extern void setKeyboardCallback(KEYBOARD_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Remove a keyboard callback
|
||||
GEM_EXTERN extern void removeKeyboardCallback(KEYBOARD_CB callback, void *data);
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Resize callback
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
typedef void (*RESIZE_CB)(int, int, void *);
|
||||
//////////
|
||||
// Set a resize callback
|
||||
GEM_EXTERN extern void setResizeCallback(RESIZE_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Remove a resize callback
|
||||
GEM_EXTERN extern void removeResizeCallback(RESIZE_CB callback, void *data);
|
||||
|
||||
//////////
|
||||
// Trigger an event
|
||||
GEM_EXTERN extern void triggerMotionEvent(int x, int y);
|
||||
GEM_EXTERN extern void triggerButtonEvent(int which, int state, int x, int y);
|
||||
GEM_EXTERN extern void triggerWheelEvent(int axis, int value);
|
||||
GEM_EXTERN extern void triggerKeyboardEvent(char *string, int value, int state);
|
||||
GEM_EXTERN extern void triggerResizeEvent(int xSize, int ySize);
|
||||
|
||||
#endif // for header file
|
||||
|
||||
67
Gem/src/Gem/Exception.cpp
Normal file
67
Gem/src/Gem/Exception.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// for NULL
|
||||
#include <new>
|
||||
|
||||
#include "Exception.h"
|
||||
|
||||
// for error()
|
||||
#include "m_pd.h"
|
||||
|
||||
|
||||
GemException::GemException(const char *error) throw()
|
||||
: ErrorString(error)
|
||||
{}
|
||||
|
||||
GemException::GemException(const std::string error) throw()
|
||||
: ErrorString(error)
|
||||
{}
|
||||
|
||||
GemException::GemException() throw()
|
||||
: ErrorString(std::string(""))
|
||||
{}
|
||||
GemException::~GemException() throw()
|
||||
{}
|
||||
const char *GemException::what() const throw() {
|
||||
return ErrorString.c_str();
|
||||
}
|
||||
|
||||
void GemException::report(const char*origin) const throw() {
|
||||
if(!(ErrorString.empty())) {
|
||||
if (NULL==origin)
|
||||
error("GemException: %s", ErrorString.c_str());
|
||||
else
|
||||
error("[%s]: %s", origin, ErrorString.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gem::catchGemException(const char*name, const t_object*obj) {
|
||||
try {
|
||||
throw;
|
||||
} catch (GemException&ex) {
|
||||
if(NULL==obj) {
|
||||
ex.report(name);
|
||||
} else {
|
||||
t_object*o=(t_object*)obj;
|
||||
char*str=(char*)ex.what();
|
||||
if(NULL!=str) {
|
||||
if (NULL==name)
|
||||
pd_error(o, "GemException: %s", str);
|
||||
else
|
||||
pd_error(o, "[%s]: %s", name, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Gem/src/Gem/Exception.h
Normal file
58
Gem/src/Gem/Exception.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The base class for exceptions thrown by Gem
|
||||
|
||||
Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemException
|
||||
|
||||
an exception class...
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
this is a class, we can throw on creation,
|
||||
to make sure that the pd-object can not be created
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_EXCEPTION_H_
|
||||
#define _INCLUDE__GEM_GEM_EXCEPTION_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
#include <string>
|
||||
|
||||
typedef struct _text t_object;
|
||||
|
||||
class GEM_EXTERN GemException
|
||||
{
|
||||
public:
|
||||
GemException(void) throw();
|
||||
GemException(const char*error) throw();
|
||||
GemException(const std::string error) throw();
|
||||
virtual ~GemException(void) throw();
|
||||
|
||||
virtual const char *what(void) const throw();
|
||||
virtual void report(const char*origin=0) const throw();
|
||||
private:
|
||||
const std::string ErrorString;
|
||||
};
|
||||
|
||||
namespace gem {
|
||||
GEM_EXTERN void catchGemException(const char*name=NULL, const t_object*obj=NULL);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_EXCEPTION_H_ */
|
||||
71
Gem/src/Gem/ExportDef.h
Normal file
71
Gem/src/Gem/ExportDef.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
Export crap
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_EXPORTDEF_H_
|
||||
#define _INCLUDE__GEM_GEM_EXPORTDEF_H_
|
||||
|
||||
#if defined _MSC_VER
|
||||
/* turn of some warnings on vc-compilers */
|
||||
|
||||
/* data conversion with possible loss of data */
|
||||
# pragma warning( disable : 4244 )
|
||||
/* identifier conversion with possible loss of data */
|
||||
# pragma warning( disable : 4305 )
|
||||
/* declspec without variable declaration */
|
||||
# pragma warning( disable : 4091 )
|
||||
/* M$DN classes exporting STL members... */
|
||||
# pragma warning( disable : 4251 )
|
||||
/* "switch" without "case" (just "default") */
|
||||
# pragma warning( disable : 4065 )
|
||||
/* Exception Specifications! */
|
||||
# pragma warning (disable : 4290)
|
||||
/* CRT deprecation warnings */
|
||||
# define _CRT_SECURE_NO_WARNINGS 1
|
||||
|
||||
/* MSVC always uses dllimport/dllexport */
|
||||
#define DLL_EXPORT
|
||||
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
#ifdef DLL_EXPORT
|
||||
// Windows requires explicit import and exporting of functions and classes.
|
||||
// While this is a pain to do sometimes, in large software development
|
||||
// projects, it is very useful.
|
||||
# define GEM_EXPORT __declspec(dllexport)
|
||||
# define GEM_IMPORT __declspec(dllimport)
|
||||
|
||||
# define GEM_DEPRECATED __declspec(deprecated)
|
||||
|
||||
#elif defined __GNUC__
|
||||
# define GEM_EXPORT
|
||||
# define GEM_IMPORT
|
||||
|
||||
# define GEM_DEPRECATED __attribute__ ((deprecated))
|
||||
|
||||
#else
|
||||
/* unknown compiler */
|
||||
# warning set up compiler specific defines
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef GEM_INTERNAL
|
||||
# define GEM_EXTERN GEM_EXPORT
|
||||
#else
|
||||
# define GEM_EXTERN GEM_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // for header file
|
||||
178
Gem/src/Gem/Files.cpp
Normal file
178
Gem/src/Gem/Files.cpp
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
#include "Gem/GemConfig.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_WINNT 0x0400
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <glob.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Files.h"
|
||||
|
||||
#ifdef HAVE_WORDEXP_H
|
||||
# include <wordexp.h>
|
||||
#endif
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
#include "Base/CPPExtern.h"
|
||||
|
||||
namespace gem {
|
||||
namespace files {
|
||||
|
||||
std::vector<std::string>getFilenameListing(const std::string&pattern) {
|
||||
std::vector<std::string>result;
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA findData;
|
||||
DWORD errorNumber;
|
||||
HANDLE hFind;
|
||||
LPVOID lpErrorMessage;
|
||||
|
||||
hFind = FindFirstFile(pattern.c_str(), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
errorNumber = GetLastError();
|
||||
switch (errorNumber)
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
break;
|
||||
default:
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
errorNumber,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpErrorMessage,
|
||||
0, NULL );
|
||||
//pd_error(x,"[folder_list] %s", (char *)lpErrorMessage);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
do {
|
||||
result.push_back(findData.cFileName);
|
||||
} while (FindNextFile(hFind, &findData) != 0);
|
||||
|
||||
FindClose(hFind);
|
||||
#else
|
||||
/* use glob */
|
||||
glob_t glob_buffer;
|
||||
int i=0;
|
||||
switch( glob( pattern.c_str(), GLOB_TILDE, NULL, &glob_buffer ) ) {
|
||||
case GLOB_NOSPACE:
|
||||
// error("out of memory for \"%s\"",pattern.c_str());
|
||||
return result;
|
||||
# ifdef GLOB_ABORTED
|
||||
case GLOB_ABORTED:
|
||||
//error("aborted \"%s\"",pattern.c_str());
|
||||
return result;
|
||||
# endif
|
||||
# ifdef GLOB_NOMATCH
|
||||
case GLOB_NOMATCH:
|
||||
//error("nothing found for \"%s\"",pattern.c_str());
|
||||
return result;
|
||||
# endif
|
||||
}
|
||||
for(i=0; i<glob_buffer.gl_pathc; i++) {
|
||||
result.push_back(glob_buffer.gl_pathv[i]);
|
||||
}
|
||||
globfree( &(glob_buffer) );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string expandEnv(const std::string&value, bool bashfilename) {
|
||||
std::string ret;
|
||||
/* FIXXME:
|
||||
* ouch, on linux value has to include "$VARIABLENAME", check whether we need "%VARIABLENAME%" on w32
|
||||
*/
|
||||
|
||||
if(value.empty())
|
||||
return value;
|
||||
|
||||
if(bashfilename) {
|
||||
char bashBuffer[MAXPDSTRING];
|
||||
sys_bashfilename(value.c_str(), bashBuffer);
|
||||
ret=bashBuffer;
|
||||
} else {
|
||||
ret=value;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WORDEXP_H
|
||||
wordexp_t pwordexp;
|
||||
|
||||
if(0==wordexp(ret.c_str(), &pwordexp, 0)) {
|
||||
pwordexp.we_offs=0;
|
||||
if(pwordexp.we_wordc) {
|
||||
// we only take the first match into account
|
||||
ret=pwordexp.we_wordv[0];
|
||||
}
|
||||
# ifdef __APPLE__
|
||||
/* wordfree() broken on apple: keeps deallocating non-aligned memory */
|
||||
# warning wordfree() not called
|
||||
# else
|
||||
wordfree(&pwordexp);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
char envVarBuffer[MAXPDSTRING];
|
||||
ExpandEnvironmentStrings(ret.c_str(), envVarBuffer, MAX_PATH - 2);
|
||||
ret=envVarBuffer;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string getExtension(const std::string&fileName, const bool lower) {
|
||||
using namespace std;
|
||||
std::string Ext;
|
||||
std::string::size_type idx;
|
||||
idx = fileName.rfind('.');
|
||||
|
||||
if(idx != std::string::npos)
|
||||
Ext=fileName.substr(idx + 1);
|
||||
|
||||
if(lower) {
|
||||
// lower-case: http://www.cplusplus.com/forum/general/837/
|
||||
#if 0
|
||||
std::transform(Ext.begin(), Ext.end(), Ext.begin(), std::tolower);
|
||||
#else
|
||||
const int length = Ext.length();
|
||||
for(int i=0; i < length; ++i) {
|
||||
Ext[i] = tolower(Ext[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return Ext;
|
||||
}
|
||||
|
||||
std::string getFullpath(const std::string&path, const CPPExtern*obj) {
|
||||
std::string result=expandEnv(path);
|
||||
if(obj!=NULL) {
|
||||
char buf[MAXPDSTRING];
|
||||
t_canvas*canvas=const_cast<t_canvas*>(obj->getCanvas());
|
||||
|
||||
if(canvas) {
|
||||
canvas_makefilename(canvas, const_cast<char*>(result.c_str()), buf, MAXPDSTRING);
|
||||
result=buf;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void close(int fd) {
|
||||
#ifdef _WIN32
|
||||
::_close(fd);
|
||||
#else
|
||||
::close(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
39
Gem/src/Gem/Files.h
Normal file
39
Gem/src/Gem/Files.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
- file handling with Gem
|
||||
|
||||
Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_FILES_H_
|
||||
#define _INCLUDE__GEM_GEM_FILES_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
class CPPExtern;
|
||||
namespace gem {
|
||||
|
||||
namespace files {
|
||||
|
||||
GEM_EXTERN std::vector<std::string>getFilenameListing(const std::string&pattern);
|
||||
GEM_EXTERN std::string expandEnv(const std::string&, bool bashfilename=false);
|
||||
|
||||
GEM_EXTERN std::string getExtension(const std::string&filename, bool make_lowercase=false);
|
||||
|
||||
|
||||
GEM_EXTERN std::string getFullpath(const std::string&, const CPPExtern*obj=NULL);
|
||||
|
||||
GEM_EXTERN void close(int fd);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_FILES_H_ */
|
||||
200
Gem/src/Gem/GLStack.cpp
Normal file
200
Gem/src/Gem/GLStack.cpp
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2002 tigital
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma NOTE("memory(484): warning C4150: Löschen eines Zeigers auf den nicht definierten Typ 'gem::GLStack::Data'. Destruktor wurde nicht aufgerufen.")
|
||||
#endif
|
||||
|
||||
#include "Gem/GLStack.h"
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
/* need GLUtil for glReportError */
|
||||
#include "Gem/GemGL.h"
|
||||
#include "Utils/GLUtil.h"
|
||||
#include <map>
|
||||
|
||||
#define GLDEBUG if(glReportError())::startpost("glError @ %s:%d[%s] ", __FILE__, __LINE__, __FUNCTION__), ::post
|
||||
|
||||
using namespace gem;
|
||||
|
||||
namespace gem {
|
||||
class GLStack::Data {
|
||||
public:
|
||||
Data(void) {
|
||||
int i=0;
|
||||
for(i=0; i<4; i++) {
|
||||
stackDepth[i]=0;
|
||||
maxDepth[i]=0;
|
||||
orgDepth[i]=0;
|
||||
}
|
||||
}
|
||||
int stackDepth[4];
|
||||
int maxDepth[4];
|
||||
int orgDepth[4];
|
||||
};
|
||||
};
|
||||
|
||||
namespace {
|
||||
static std::map<enum GLStack::GemStackId, GLenum>s_id2mode;
|
||||
static std::map<enum GLStack::GemStackId, GLenum>s_id2depth;
|
||||
static std::map<enum GLStack::GemStackId, GLenum>s_id2maxdepth;
|
||||
static std::map<enum GLStack::GemStackId, bool>s_id2init;
|
||||
}
|
||||
|
||||
|
||||
GLStack:: GLStack(bool haveValidContext) : data(new Data()) {
|
||||
static bool firsttime=true;
|
||||
if(firsttime) {
|
||||
s_id2mode[MODELVIEW] =GL_MODELVIEW;
|
||||
s_id2mode[PROJECTION]=GL_PROJECTION;
|
||||
s_id2mode[TEXTURE] =GL_TEXTURE;
|
||||
s_id2mode[COLOR] =GL_COLOR;
|
||||
|
||||
s_id2depth[MODELVIEW] =GL_MODELVIEW_STACK_DEPTH;
|
||||
s_id2depth[PROJECTION]=GL_PROJECTION_STACK_DEPTH;
|
||||
s_id2depth[TEXTURE] =GL_TEXTURE_STACK_DEPTH;
|
||||
s_id2depth[COLOR] =GL_COLOR_MATRIX_STACK_DEPTH;
|
||||
|
||||
s_id2maxdepth[MODELVIEW] =GL_MAX_MODELVIEW_STACK_DEPTH;
|
||||
s_id2maxdepth[PROJECTION]=GL_MAX_PROJECTION_STACK_DEPTH;
|
||||
s_id2maxdepth[TEXTURE] =GL_MAX_TEXTURE_STACK_DEPTH;
|
||||
s_id2maxdepth[COLOR] =GL_MAX_COLOR_MATRIX_STACK_DEPTH;
|
||||
|
||||
s_id2init[MODELVIEW] =false;
|
||||
s_id2init[PROJECTION]=false;
|
||||
s_id2init[TEXTURE] =false;
|
||||
s_id2init[COLOR] =false;
|
||||
}
|
||||
firsttime=false;
|
||||
|
||||
if(haveValidContext) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
GLStack::~GLStack() {
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
# warning push/pop texture matrix has to be done per texunit
|
||||
// each texunit has it's own matrix to be pushed/popped
|
||||
// changing the texunit (e.g. in [pix_texture]) makes the
|
||||
// local depthcounter a useless, and we get a lot of
|
||||
// stack under/overflows
|
||||
#endif
|
||||
|
||||
|
||||
/** push the given matrix to the stack if the maximum has not been reached
|
||||
* returns true on success and false otherwise (stack overflow)
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
bool GLStack::push(enum GemStackId id) {
|
||||
GLenum mode=s_id2mode[id];
|
||||
if(!mode)return false;
|
||||
if(data->stackDepth[id]<data->maxDepth[id]) {
|
||||
glMatrixMode(mode);
|
||||
glPushMatrix();
|
||||
data->stackDepth[id]++;
|
||||
return true;
|
||||
}
|
||||
|
||||
data->stackDepth[id]++;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLStack::push() {
|
||||
push(COLOR);
|
||||
push(TEXTURE);
|
||||
push(PROJECTION);
|
||||
push(MODELVIEW);
|
||||
}
|
||||
|
||||
|
||||
/** pop the given matrix from the stack if the maximum has not been reached
|
||||
* returns true on success and false otherwise (stack underlow)
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
bool GLStack::pop(enum GemStackId id) {
|
||||
GLenum mode=s_id2mode[id];
|
||||
if(!mode)return false;
|
||||
|
||||
data->stackDepth[id]--;
|
||||
if(data->stackDepth[id]<data->maxDepth[id]) {
|
||||
glMatrixMode(mode);
|
||||
glPopMatrix();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLStack::pop() {
|
||||
pop(COLOR);
|
||||
pop(TEXTURE);
|
||||
pop(PROJECTION);
|
||||
pop(MODELVIEW);
|
||||
}
|
||||
/**
|
||||
* reset the maximum stack depth of the given stack
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
void GLStack::reset() {
|
||||
reset(MODELVIEW);
|
||||
reset(PROJECTION);
|
||||
reset(TEXTURE);
|
||||
reset(COLOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the maximum stack depth of all stacks
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
int GLStack::reset(enum GemStackId id) {
|
||||
bool firsttime=!(s_id2init[id]);
|
||||
if(firsttime) {
|
||||
s_id2init[id]=true;
|
||||
|
||||
if(COLOR == id && !GLEW_ARB_imaging) {
|
||||
s_id2maxdepth[id]=0;
|
||||
s_id2depth[id]=0;
|
||||
}
|
||||
glReportError(); // clear any errors so far
|
||||
}
|
||||
|
||||
|
||||
GLenum maxdepth=s_id2maxdepth[id];
|
||||
GLenum depth=s_id2depth[id];
|
||||
|
||||
if(maxdepth && depth) {
|
||||
/* hmm, some ati-cards (with fglrx) report GLEW_ARB_imaging support but fail the 'depth' test for COLOR */
|
||||
|
||||
glGetIntegerv(maxdepth, data->maxDepth+id);
|
||||
if(firsttime && glReportError())s_id2maxdepth[id]=0;
|
||||
|
||||
glGetIntegerv(depth, data->stackDepth+id);
|
||||
if(firsttime && glReportError())s_id2depth[id]=0;
|
||||
|
||||
data->orgDepth[id]=data->stackDepth[id];
|
||||
return data->stackDepth[id];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GLStack::print() {
|
||||
post("MODELVIEW: %02d/%02d", data->stackDepth[MODELVIEW], data->maxDepth[MODELVIEW]);
|
||||
post("PROJECTION: %02d/%02d", data->stackDepth[PROJECTION], data->maxDepth[PROJECTION]);
|
||||
post("TEXTURE: %02d/%02d", data->stackDepth[TEXTURE], data->maxDepth[TEXTURE]);
|
||||
post("COLOR: %02d/%02d", data->stackDepth[COLOR], data->maxDepth[COLOR]);
|
||||
}
|
||||
74
Gem/src/Gem/GLStack.h
Normal file
74
Gem/src/Gem/GLStack.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
handling of diverse openGL stacks
|
||||
|
||||
Copyright (c) 1997-2000 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
#ifndef _INCLUDE__GEM_GEM_GLSTACK_H_
|
||||
#define _INCLUDE__GEM_GEM_GLSTACK_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace gem {
|
||||
class GEM_EXTERN GLStack {
|
||||
public:
|
||||
GLStack(bool haveValidContext=false);
|
||||
virtual ~GLStack(void);
|
||||
|
||||
enum GemStackId { MODELVIEW, COLOR, TEXTURE, PROJECTION };
|
||||
|
||||
/** push the given matrix to the stack if the maximum has not been reached
|
||||
* returns true on success and false otherwise (stack overflow)
|
||||
* NOTE: needs valid openGL context
|
||||
* NOTE: might change the current matrix mode; you have to manually reset it
|
||||
*/
|
||||
bool push(enum GemStackId);
|
||||
|
||||
/** pushes all matrices possible
|
||||
* NOTE: finishes in MODELVIEW matrix mode
|
||||
*/
|
||||
void push(void);
|
||||
|
||||
/** pop the given matrix from the stack if the maximum has not been reached
|
||||
* returns true on success and false otherwise (stack underflow)
|
||||
* NOTE: needs valid openGL context
|
||||
* NOTE: might change the current matrix mode; you have to manually reset it
|
||||
*/
|
||||
bool pop(enum GemStackId);
|
||||
/** pops all matrices possible
|
||||
* NOTE: finishes in MODELVIEW matrix mode
|
||||
*/
|
||||
void pop(void);
|
||||
|
||||
/**
|
||||
* reset the maximum stack depth of the given stack
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
void reset(void);
|
||||
/**
|
||||
* reset the maximum stack depth of all stacks
|
||||
* returns the current stack depth (-1 on failure)
|
||||
* NOTE: needs valid openGL context
|
||||
*/
|
||||
int reset(enum GemStackId);
|
||||
|
||||
void print(void);
|
||||
|
||||
private:
|
||||
class Data;
|
||||
std::auto_ptr<Data>data;
|
||||
};
|
||||
|
||||
} /* namespace gem */
|
||||
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_GLSTACK_H_ */
|
||||
64
Gem/src/Gem/GemConfig.h
Normal file
64
Gem/src/Gem/GemConfig.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* configuration-file */
|
||||
#ifndef HAVE_BASE_GEMCONFIG_H_
|
||||
#define HAVE_BASE_GEMCONFIG_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef _WIN32
|
||||
# define _WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef NT
|
||||
# define NT
|
||||
# endif
|
||||
# ifndef MSW
|
||||
# define MSW
|
||||
# endif
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define GEM_FILMBACKEND_undefined 0
|
||||
#define GEM_FILMBACKEND_Darwin 1
|
||||
|
||||
#define GEM_VIDEOBACKEND_undefined 0
|
||||
#define GEM_VIDEOBACKEND_Darwin 1
|
||||
#define GEM_VIDEOBACKEND_DS 2
|
||||
#define GEM_VIDEOBACKEND_NT 3
|
||||
#define GEM_VIDEOBACKEND_SGI 4
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
||||
# include "config.h"
|
||||
|
||||
/* stupid hack to avoid duplicate inclusion of config.h e.g. in avifile.h */
|
||||
# undef HAVE_CONFIG_H
|
||||
|
||||
#else /* includes system-specific files */
|
||||
|
||||
# ifdef __linux__
|
||||
# include "Gem/configLinux.h"
|
||||
# elif defined __APPLE__
|
||||
# include "Gem/configDarwin.h"
|
||||
# elif defined _WIN32
|
||||
# include "Gem/configNT.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined GEM_VIDEOBACKEND && GEM_VIDEOBACKEND == GEM_VIDEOBACKEND_undefined
|
||||
# warning ignoring unknown video backend
|
||||
# undef GEM_VIDEOBACKEND
|
||||
#endif
|
||||
|
||||
#if defined GEM_FILMBACKEND && GEM_FILMBACKEND == GEM_FILMBACKEND_undefined
|
||||
# warning ignoring unknown film backend
|
||||
# undef GEM_FILMBACKEND
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBFTGL
|
||||
# define FTGL
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_BASE_GEMCONFIG_H_ */
|
||||
87
Gem/src/Gem/GemGL.h
Normal file
87
Gem/src/Gem/GemGL.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* GemGL: openGL includes for GEM
|
||||
*
|
||||
* include this file if you want to include the
|
||||
* openGL-headers installed on your system
|
||||
*
|
||||
* tasks:
|
||||
*
|
||||
* + this file hides the peculiarities of the various platforms
|
||||
* (like "OpenGL/gl.h" vs "GL/gl.h")
|
||||
*
|
||||
* + define some pre-processor defines that are missing in the GL-headers
|
||||
*
|
||||
* + try to exclude parts of the GL-headers based on GemConfig.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_GEMGL_H_
|
||||
#define _INCLUDE__GEM_GEM_GEMGL_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
// I hate Microsoft...I shouldn't have to do this!
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef GLEW_MX
|
||||
# define GEM_MULTICONTEXT
|
||||
#endif
|
||||
|
||||
#include "Gem/glew.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/OpenGL.h>
|
||||
#elif defined _WIN32
|
||||
# include "Gem/wglew.h"
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__)
|
||||
# include "Gem/glxew.h"
|
||||
#endif /* OS */
|
||||
|
||||
#ifdef GEM_MULTICONTEXT
|
||||
GEM_EXTERN GLEWContext*glewGetContext(void);
|
||||
# ifdef __APPLE__
|
||||
# elif defined _WIN32
|
||||
GEM_EXTERN WGLEWContext*wglewGetContext(void);
|
||||
# elif defined __linux__ || defined HAVE_GL_GLX_H
|
||||
GEM_EXTERN GLXEWContext*glxewGetContext(void);
|
||||
# endif
|
||||
|
||||
#endif /* GEM_MULTICONTEXT */
|
||||
|
||||
#ifndef GL_YUV422_GEM
|
||||
# define GL_YCBCR_422_GEM GL_YCBCR_422_APPLE
|
||||
# define GL_YUV422_GEM GL_YCBCR_422_GEM
|
||||
#endif /* GL_YUV422_GEM */
|
||||
|
||||
|
||||
#ifndef GL_RGBA_GEM
|
||||
# ifdef __APPLE__
|
||||
# define GL_RGBA_GEM GL_BGRA_EXT
|
||||
# else
|
||||
# define GL_RGBA_GEM GL_RGBA
|
||||
# endif
|
||||
#endif /* GL_RGBA_GEM */
|
||||
|
||||
/* default draw-style */
|
||||
#ifndef GL_DEFAULT_GEM
|
||||
# define GL_DEFAULT_GEM 0xFFFF
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* uäh: in OSX10.3 we only have CGL-1.1 and
|
||||
* all the functions are using "long*" rather than "GLint*")
|
||||
* only CGL-1.2 got it right
|
||||
*/
|
||||
#ifdef CGL_VERSION_1_0
|
||||
# ifdef CGL_VERSION_1_2
|
||||
# define GemCGLint GLint
|
||||
# else
|
||||
# define GemCGLint long
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_GEMGL_H_ */
|
||||
1954
Gem/src/Gem/Image.cpp
Normal file
1954
Gem/src/Gem/Image.cpp
Normal file
File diff suppressed because it is too large
Load diff
288
Gem/src/Gem/Image.h
Normal file
288
Gem/src/Gem/Image.h
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
GemPixUtil.h
|
||||
- contains image functions for pix objects
|
||||
- part of GEM
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_IMAGE_H_
|
||||
#define _INCLUDE__GEM_GEM_IMAGE_H_
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// basic helper functions, like CLAMP and powerOfTwo
|
||||
#include "Utils/Functions.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Color component defines
|
||||
//
|
||||
// These should be used to reference the various color channels
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* RGBA */
|
||||
|
||||
#if GL_RGBA_GEM == GL_RGBA
|
||||
const int chRed = 0;
|
||||
const int chGreen = 1;
|
||||
const int chBlue = 2;
|
||||
const int chAlpha = 3;
|
||||
#else
|
||||
const int chAlpha = 0;
|
||||
const int chRed = 1;
|
||||
const int chGreen = 2;
|
||||
const int chBlue = 3;
|
||||
#endif
|
||||
|
||||
|
||||
/* Gray */
|
||||
const int chGray = 0;
|
||||
|
||||
/* YUV422 */
|
||||
const int chU = 0;
|
||||
const int chY0 = 1;
|
||||
const int chV = 2;
|
||||
const int chY1 = 3;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
imageStruct
|
||||
|
||||
The basic image structure
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
// we now have a class "imageStruct";
|
||||
// since i need to compile some of the sources with an older version of Gem
|
||||
// there is a new define here:
|
||||
#define IMAGE_CLASS
|
||||
|
||||
struct GEM_EXTERN imageStruct
|
||||
{
|
||||
imageStruct(void);
|
||||
imageStruct(const imageStruct&);
|
||||
virtual ~imageStruct(void);
|
||||
|
||||
virtual void info(void);
|
||||
//////////
|
||||
// columns
|
||||
virtual unsigned char* allocate(size_t size);
|
||||
virtual unsigned char* allocate(void);
|
||||
|
||||
// if we have allocated some space already, only re-allocate when needed.
|
||||
virtual unsigned char* reallocate(size_t size);
|
||||
virtual unsigned char* reallocate(void);
|
||||
|
||||
// delete the buffer (if it is ours)
|
||||
virtual void clear(void);
|
||||
|
||||
|
||||
//////////
|
||||
// dimensions of the image
|
||||
GLint xsize;
|
||||
GLint ysize;
|
||||
|
||||
//////////
|
||||
// (average) width of 1 pixel (LUMINANCE = 1, RGBA = 4, YUV = 2)
|
||||
GLint csize;
|
||||
|
||||
//////////
|
||||
// data type - always GL_UNSIGNED_BYTE (except for OS X)
|
||||
GLenum type;
|
||||
|
||||
//////////
|
||||
// the format - either GL_RGBA, GL_LUMINANCE
|
||||
// or GL_YCBCR_422_GEM (which is on mac-computers GL_YCBCR_422_APPLE)
|
||||
GLenum format;
|
||||
|
||||
//////////
|
||||
// is this owned by us (? what about underscores ?)
|
||||
int notowned;
|
||||
|
||||
//////////
|
||||
// gets a pixel
|
||||
/* X,Y are the coordinates
|
||||
* C is the offset in the interleaved data (like chRed==0 for red)
|
||||
* you should use chRed instead of 0 (because it might not be 0)
|
||||
*
|
||||
* you must make sure that (0<=X<xsize) and (0<=Y<ysize)
|
||||
*/
|
||||
// heck, why are X&Y swapped ?? (JMZ)
|
||||
inline unsigned char GetPixel(int Y, int X, int C) const
|
||||
{
|
||||
return(data[Y * xsize * csize + X * csize + C]); }
|
||||
|
||||
//////////
|
||||
// sets a pixel
|
||||
/* while X and Y should be clear (coordinates),
|
||||
* C is the offset (like chRed==0 for red).
|
||||
* VAL is the value to set.
|
||||
*
|
||||
* you must make sure that (0<=X<xsize) and (0<=Y<ysize)
|
||||
*/
|
||||
inline void SetPixel(int Y, int X, int C, unsigned char VAL)
|
||||
{ data[Y * xsize * csize + X * csize + C] = VAL; }
|
||||
|
||||
|
||||
/////////
|
||||
// gets the color of a pixel
|
||||
virtual void getRGB(int X, int Y, unsigned char*r, unsigned char*g, unsigned char*b, unsigned char*a=NULL) const;
|
||||
virtual void getGrey(int X, int Y, unsigned char*g) const;
|
||||
virtual void getYUV(int X, int Y, unsigned char*y, unsigned char*u, unsigned char*v) const;
|
||||
|
||||
/* following will set the whole image-data to either black or white
|
||||
* the size of the image-data is NOT xsize*ysize*csize but datasize
|
||||
* this is mostly slower
|
||||
* i have put the datasize into private (like pdata) (bad idea?)
|
||||
*/
|
||||
virtual void setBlack(void);
|
||||
virtual void setWhite(void);
|
||||
|
||||
/* certain formats are bound to certain csizes,
|
||||
* it's quite annoying to have to think again and again (ok, not much thinking)
|
||||
* so we just give the format (like GL_LUMINANCE)
|
||||
* and it will set the image format to this format
|
||||
* and set and return the correct csize (like 1)
|
||||
* if no format is given the current format is used
|
||||
*/
|
||||
virtual int setCsizeByFormat(int format);
|
||||
virtual int setCsizeByFormat(void);
|
||||
|
||||
|
||||
/* various copy functions
|
||||
* sometimes we want to copy the whole image (including pixel-data),
|
||||
* but often it is enough to just copy the meta-data (without pixel-data)
|
||||
* into a new imageStruct
|
||||
*/
|
||||
virtual void copy2Image(imageStruct *to) const;
|
||||
virtual void copy2ImageStruct(imageStruct *to) const; // copy the imageStruct (but not the actual data)
|
||||
/* this is a sort of better copy2Image,
|
||||
* which only copies the imageStruct-data if it is needed
|
||||
*/
|
||||
virtual void refreshImage(imageStruct *to) const;
|
||||
|
||||
|
||||
/* inplace swapping Red and Blue channel */
|
||||
virtual void swapRedBlue(void);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// acquiring data including colour-transformations
|
||||
// should be accelerated if possible
|
||||
/* i wonder whether this is the right place to put these routines
|
||||
* they should be stored somewhere centrally
|
||||
* (because maybe a lot of objects would like them) (like [pix_rgba]...)
|
||||
* but it might be better to put them (the actual conversion routines) into
|
||||
* separate files (a separate library?)
|
||||
* orgdata points to the actual data in the given format
|
||||
* the datasize will be read from image.xsize, image.ysize
|
||||
* the dest-format will be given by image.format
|
||||
* this is maybe not really clean (the meta-data is stored in the destination,
|
||||
* while the source has no meta-data of its own)
|
||||
*/
|
||||
virtual void convertTo (imageStruct*to, GLenum dest_format=0) const;
|
||||
virtual void convertFrom(const imageStruct*from, GLenum dest_format=0);
|
||||
|
||||
virtual void fromRGB (const unsigned char* orgdata);
|
||||
virtual void fromRGBA (const unsigned char* orgdata);
|
||||
virtual void fromBGR (const unsigned char* orgdata);
|
||||
virtual void fromBGRA (const unsigned char* orgdata);
|
||||
virtual void fromRGB16 (const unsigned char* orgdata);
|
||||
virtual void fromABGR (const unsigned char* orgdata);
|
||||
virtual void fromARGB (const unsigned char* orgdata);
|
||||
virtual void fromGray (const unsigned char* orgdata);
|
||||
virtual void fromGray (short* orgdata);
|
||||
virtual void fromUYVY (const unsigned char* orgdata);
|
||||
virtual void fromYUY2 (const unsigned char* orgdata); // YUYV
|
||||
virtual void fromYVYU (const unsigned char* orgdata);
|
||||
/* planar YUV420: this is rather generic and not really YV12 only */
|
||||
virtual void fromYV12 (const unsigned char* Y, const unsigned char*U, const unsigned char*V);
|
||||
/* assume that the planes are near each other: YVU */
|
||||
virtual void fromYV12 (const unsigned char* orgdata);
|
||||
/* assume that the planes are near each other: YVU */
|
||||
virtual void fromYU12 (const unsigned char* orgdata);
|
||||
/* overloading the above two in order to accept pdp YV12 packets */
|
||||
virtual void fromYV12 (const short* Y, const short*U, const short*V);
|
||||
virtual void fromYV12 (const short* orgdata);
|
||||
|
||||
/* aliases */
|
||||
virtual void fromYUV422 (const unsigned char* orgdata){fromUYVY(orgdata);}
|
||||
virtual void fromYUV420P(const unsigned char* orgdata){fromYV12(orgdata);}
|
||||
virtual void fromYUV420P(const unsigned char*Y,const unsigned char*U,const unsigned char*V){fromYV12(Y,U,V);}
|
||||
|
||||
// "data" points to the image.
|
||||
// the memory could(!) be reserved by this class or someone else
|
||||
// "notowned" should be set to "1", if "data" points to foreign memory
|
||||
// "data" is not freed directly, when the destructor is called
|
||||
unsigned char *data; // the pointer to the data
|
||||
private:
|
||||
// "pdata" is the private data, and is the memory reserved by this class
|
||||
// this data is freed when the destructor is called
|
||||
unsigned char *pdata;
|
||||
// "datasize" is the size of data reserved at "pdata"
|
||||
size_t datasize;
|
||||
|
||||
public:
|
||||
//////////
|
||||
// true if the image is flipped horizontally (origin is upper-left)
|
||||
// false if the image is openGL-conformant (origin is lower-left)
|
||||
GLboolean upsidedown;
|
||||
|
||||
/* make the image orientation openGL-conformant */
|
||||
virtual void fixUpDown(void);
|
||||
|
||||
imageStruct& operator=(const imageStruct&);
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
pixBlock
|
||||
|
||||
The pix block structure
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
struct GEM_EXTERN pixBlock
|
||||
{
|
||||
pixBlock();
|
||||
|
||||
//////////
|
||||
// the block's image
|
||||
imageStruct image;
|
||||
|
||||
//////////
|
||||
// is this a newimage since last time?
|
||||
// ie, has it been refreshed
|
||||
bool newimage;
|
||||
|
||||
//////////
|
||||
// keeps track of when new films are loaded
|
||||
// useful for rectangle_textures on OSX
|
||||
bool newfilm;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// imageStruct utility functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//////////
|
||||
// copies all of the data over and mallocs memory
|
||||
GEM_EXTERN extern void copy2Image(imageStruct *to, imageStruct *from);
|
||||
|
||||
//////////
|
||||
// assumes that it only has to refresh the data
|
||||
GEM_EXTERN extern void refreshImage(imageStruct *to, imageStruct *from);
|
||||
|
||||
GEM_EXTERN extern int getPixFormat(char*);
|
||||
#endif // GEMPIXUTIL_H_
|
||||
153
Gem/src/Gem/ImageIO.h
Normal file
153
Gem/src/Gem/ImageIO.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
GemPixImageLoad.h
|
||||
- code to load in and resize an image
|
||||
- part of GEM
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_IMAGEIO_H_
|
||||
#define _INCLUDE__GEM_GEM_IMAGEIO_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
struct imageStruct;
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
// image2mem() reads an image file into memory
|
||||
// and a pointer to an imageStruct
|
||||
// NULL = failure
|
||||
//
|
||||
// format:
|
||||
// returns either GL_LUMINANCE or GL_RGBA
|
||||
//
|
||||
// automatically allocates the memory for the user
|
||||
//
|
||||
// This can read TIFF, SGI, and JPG images
|
||||
//
|
||||
namespace gem {
|
||||
class Properties;
|
||||
namespace image {
|
||||
class GEM_EXTERN load {
|
||||
public:
|
||||
/**
|
||||
* loads an image (given as 'filename') synchronously
|
||||
* the function blocks until the image is loaded (in which case it returns TRUE)
|
||||
* of the image-loading completely failed (in which case it returns FALSE)
|
||||
*
|
||||
* the loaded image is stored in 'img'
|
||||
* 'props' holds a list of additional image properties discovered during loading
|
||||
*/
|
||||
static bool sync(const std::string filename,
|
||||
imageStruct&img,
|
||||
Properties&props);
|
||||
|
||||
|
||||
|
||||
typedef unsigned int id_t;
|
||||
static const id_t IMMEDIATE;
|
||||
static const id_t INVALID;
|
||||
|
||||
/* the callback used for asynchronous image loading
|
||||
* userdata is is the pointer supplied when calling async();
|
||||
* id is the ID returned by async()
|
||||
* img holds a reference to the newly loaded image
|
||||
* the image is allocated by the loder, but
|
||||
* the callback (you!) is responsible for freeing the image
|
||||
* once it is no more needed
|
||||
* if image loading failed, img is set to NULL
|
||||
* props holds a list of additional image properties discovered during loading
|
||||
*
|
||||
* currently (with Pd being the only RTE),
|
||||
* the callback will always be called from within the main thread
|
||||
*
|
||||
* the callback might be called directly from within async(),
|
||||
* in which case the ID given in the callback and returned by async()
|
||||
* is IMMEDIATE
|
||||
*/
|
||||
typedef void (*callback)(void *userdata,
|
||||
id_t ID,
|
||||
imageStruct*img,
|
||||
const Properties&props);
|
||||
|
||||
/* loads an image (given as 'filename') asynchronously
|
||||
* image loading is done in a separate thread (if possible);
|
||||
* when the image is loaded, the callback 'cb' is called with the new image
|
||||
*
|
||||
* this function returns an ID which is also passed to the callback function,
|
||||
* so the caller can identify a certain request (e.g. if several images have been
|
||||
* queued for loading before the 1st one was successfully returned;
|
||||
*
|
||||
* the image might get loaded (and the cb called) before the call to loadAsync()
|
||||
* has finished, in which case IMMEDIATE is returned (and used in the CB)
|
||||
*
|
||||
* if the image cannot be loaded at all, INVALID is returned
|
||||
* (and no callback will ever be called)
|
||||
*
|
||||
*/
|
||||
static bool async(callback cb,
|
||||
void*userdata,
|
||||
const std::string filename,
|
||||
id_t&ID
|
||||
);
|
||||
|
||||
/* cancels asynchronous loading of an image
|
||||
* removes the given ID (as returned by loadAsync()) from the loader queue
|
||||
* returns TRUE if item could be removed, or FALSE if no item ID is in the queue
|
||||
*
|
||||
* there is no point in cancel()ing an IMMEDIATE or ILLEGAL id
|
||||
*/
|
||||
static bool cancel(id_t ID);
|
||||
|
||||
/* load an image in a synchronous way (that is argument compatible with async())
|
||||
*/
|
||||
static bool sync(callback cb,
|
||||
void*userdata,
|
||||
const std::string filename,
|
||||
id_t&ID);
|
||||
|
||||
/*
|
||||
* deliver all loaded images not delivered yet
|
||||
*/
|
||||
static void poll(void);
|
||||
|
||||
/*
|
||||
* set asynch loading to "polling" mode
|
||||
* in "polling" mode, the caller has to call 'poll()' manually in order to get any loaded images delivered
|
||||
* in "pushing" mode this is done automatically (but might hang with current Pd)
|
||||
*/
|
||||
static bool setPolling(bool);
|
||||
|
||||
|
||||
};};};
|
||||
|
||||
/* legacy */
|
||||
GEM_EXTERN extern imageStruct *image2mem(const char *filename);
|
||||
|
||||
|
||||
// image2mem() reads an image file into memory
|
||||
// and a pointer to an imageStruct
|
||||
// NULL = failure
|
||||
//
|
||||
// format:
|
||||
// returns either GL_LUMINANCE or GL_RGBA
|
||||
//
|
||||
// automatically allocates the memory for the user
|
||||
//
|
||||
// This can write TIFF, JPG and other images (depending on which backends are available
|
||||
// legacy: type=0 -> TIFF; type>0 -> JPEG and (quality:=type)
|
||||
//
|
||||
GEM_EXTERN extern int mem2image(imageStruct *image, const char *filename, const int type);
|
||||
|
||||
|
||||
#endif
|
||||
233
Gem/src/Gem/ImageLoad.cpp
Normal file
233
Gem/src/Gem/ImageLoad.cpp
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2002-2003 james tittle/tigital
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#include "ImageIO.h"
|
||||
#include "Gem/RTE.h"
|
||||
#include "Utils/SynchedWorkerThread.h"
|
||||
|
||||
#include "plugins/imageloader.h"
|
||||
|
||||
namespace gem { namespace image {
|
||||
struct PixImageThreadLoader : public gem::thread::SynchedWorkerThread {
|
||||
struct InData {
|
||||
load::callback cb;
|
||||
void*userdata;
|
||||
std::string filename;
|
||||
InData(load::callback cb_, void*data_, std::string fname) :
|
||||
cb(cb_),
|
||||
userdata(data_),
|
||||
filename(fname) {
|
||||
};
|
||||
};
|
||||
|
||||
struct OutData {
|
||||
load::callback cb;
|
||||
void*userdata;
|
||||
imageStruct*img;
|
||||
gem::Properties props;
|
||||
OutData(const InData&in) :
|
||||
cb(in.cb),
|
||||
userdata(in.userdata),
|
||||
img(NULL) {
|
||||
};
|
||||
};
|
||||
|
||||
static gem::plugins::imageloader*s_imageloader;
|
||||
PixImageThreadLoader(void) :
|
||||
SynchedWorkerThread(false)
|
||||
{
|
||||
if(NULL==s_imageloader) {
|
||||
s_imageloader=gem::plugins::imageloader::getInstance();
|
||||
}
|
||||
if(!s_imageloader)
|
||||
throw(40);
|
||||
|
||||
if(!s_imageloader->isThreadable())
|
||||
throw(42);
|
||||
start();
|
||||
}
|
||||
virtual ~PixImageThreadLoader(void) {
|
||||
}
|
||||
|
||||
virtual void* process(id_t ID, void*data) {
|
||||
if(!data){
|
||||
// post("========================================= oops: %d", ID);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
InData*in=reinterpret_cast<InData*>(data);
|
||||
OutData*out=new OutData(*in);
|
||||
if(!out) {
|
||||
return NULL;
|
||||
}
|
||||
// DOIT
|
||||
out->img=new imageStruct;
|
||||
if(!s_imageloader->load(in->filename, *out->img, out->props)) {
|
||||
delete out->img;
|
||||
out->img=0;
|
||||
}
|
||||
void*result=reinterpret_cast<void*>(out);
|
||||
//post("processing[%d] %p -> %p", ID, data, result);
|
||||
return result;
|
||||
};
|
||||
|
||||
virtual void done(id_t ID, void*data) {
|
||||
OutData*out=reinterpret_cast<OutData*>(data);
|
||||
if(out) {
|
||||
(*(out->cb))(out->userdata, ID, out->img, out->props);
|
||||
delete out;
|
||||
} else {
|
||||
error("loaded image:%d with no data!", ID);
|
||||
}
|
||||
};
|
||||
|
||||
virtual bool queue(id_t&ID, load::callback cb, void*userdata, std::string filename) {
|
||||
InData *in = new InData(cb, userdata, filename);
|
||||
return SynchedWorkerThread::queue(ID, reinterpret_cast<void*>(in));
|
||||
};
|
||||
|
||||
static PixImageThreadLoader*getInstance(bool retry=true) {
|
||||
static bool didit=false;
|
||||
if(!retry && didit)
|
||||
return s_instance;
|
||||
didit=true;
|
||||
|
||||
if(NULL==s_instance) {
|
||||
try {
|
||||
s_instance=new PixImageThreadLoader();
|
||||
} catch(int i) {
|
||||
i=0;
|
||||
static bool dunnit=false;
|
||||
if(!dunnit) {
|
||||
verbose(1, "threaded ImageLoading not supported!");
|
||||
}
|
||||
dunnit=true;
|
||||
}
|
||||
|
||||
if(s_instance)
|
||||
s_instance->setPolling(true);
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
};
|
||||
|
||||
private:
|
||||
static PixImageThreadLoader*s_instance;
|
||||
};
|
||||
PixImageThreadLoader*PixImageThreadLoader::s_instance=NULL;
|
||||
gem::plugins::imageloader*PixImageThreadLoader::s_imageloader=NULL;
|
||||
|
||||
|
||||
const load::id_t load::IMMEDIATE= 0;
|
||||
const load::id_t load::INVALID =~0;
|
||||
|
||||
bool load::sync(const std::string filename,
|
||||
imageStruct&result,
|
||||
gem::Properties&props) {
|
||||
if(!PixImageThreadLoader::s_imageloader)
|
||||
PixImageThreadLoader::s_imageloader=gem::plugins::imageloader::getInstance();
|
||||
if((PixImageThreadLoader::s_imageloader) &&
|
||||
(PixImageThreadLoader::s_imageloader->load(filename, result, props)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool load::async(load::callback cb,
|
||||
void*userdata,
|
||||
const std::string filename,
|
||||
id_t&ID) {
|
||||
if(NULL==cb) {
|
||||
ID=INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
PixImageThreadLoader*threadloader=PixImageThreadLoader::getInstance();
|
||||
|
||||
//post("threadloader %p", threadloader);
|
||||
|
||||
if(threadloader) {
|
||||
return threadloader->queue(ID, cb, userdata, filename);
|
||||
}
|
||||
return sync(cb, userdata, filename, ID);
|
||||
}
|
||||
|
||||
bool load::sync(load::callback cb,
|
||||
void*userdata,
|
||||
const std::string filename,
|
||||
id_t&ID) {
|
||||
if(NULL==cb) {
|
||||
ID=INVALID;
|
||||
return false;
|
||||
}
|
||||
imageStruct*result=new imageStruct;
|
||||
gem::Properties props;
|
||||
if(sync(filename, *result, props)) {
|
||||
ID=IMMEDIATE;
|
||||
(*cb)(userdata, ID, result, props);
|
||||
return true;
|
||||
}
|
||||
ID=INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool load::cancel(id_t ID) {
|
||||
PixImageThreadLoader*threadloader=PixImageThreadLoader::getInstance(false);
|
||||
if(threadloader) {
|
||||
bool success=threadloader->cancel(ID);
|
||||
if(!success)
|
||||
poll();
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool load::setPolling(bool value) {
|
||||
PixImageThreadLoader*threadloader=PixImageThreadLoader::getInstance();
|
||||
if(threadloader) {
|
||||
return threadloader->setPolling(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void load::poll(void) {
|
||||
PixImageThreadLoader*threadloader=PixImageThreadLoader::getInstance(false);
|
||||
if(threadloader) {
|
||||
threadloader->dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}; // image
|
||||
}; // gem
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* image2mem - Read in an image in various file formats
|
||||
*
|
||||
***************************************************************************/
|
||||
GEM_EXTERN imageStruct *image2mem(const char *filename)
|
||||
{
|
||||
gem::Properties props;
|
||||
imageStruct *img = new imageStruct();
|
||||
if(gem::image::load::sync(filename, *img, props))
|
||||
return img;
|
||||
|
||||
delete img;
|
||||
return NULL;
|
||||
}
|
||||
57
Gem/src/Gem/ImageSave.cpp
Normal file
57
Gem/src/Gem/ImageSave.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "ImageIO.h"
|
||||
#include "Gem/RTE.h"
|
||||
#include "Gem/Files.h"
|
||||
|
||||
#include "plugins/imagesaver.h"
|
||||
#include "plugins/PluginFactory.h"
|
||||
|
||||
namespace gem { namespace PixImageSaver {
|
||||
static gem::plugins::imagesaver*s_instance=NULL;
|
||||
static gem::plugins::imagesaver*getInstance(void) {
|
||||
if(NULL==s_instance) {
|
||||
s_instance=gem::plugins::imagesaver::getInstance();
|
||||
}
|
||||
return s_instance;
|
||||
}
|
||||
}; };
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* mem2image - Save an image to a file
|
||||
*
|
||||
***************************************************************************/
|
||||
GEM_EXTERN int mem2image(imageStruct* image, const char *filename, const int type)
|
||||
{
|
||||
gem::plugins::imagesaver*piximagesaver=gem::PixImageSaver::getInstance();
|
||||
if(piximagesaver) {
|
||||
std::string fname=filename;
|
||||
std::string mimetype;
|
||||
gem::Properties props;
|
||||
if(type>0) {
|
||||
props.set("quality", (float)type);
|
||||
}
|
||||
if(piximagesaver->save(*image, filename, mimetype, props)) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
error("GEM: Unable to save image to '%s'", filename);
|
||||
return (0);
|
||||
}
|
||||
56
Gem/src/Gem/Loaders.cpp
Normal file
56
Gem/src/Gem/Loaders.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-2000 Mark Danks.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// Copyright (c) 2002 James Tittle & Chris Clepper
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
// a wrapper for calling Pd's sys_register_loader()
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable: 4091)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
#include "Loaders.h"
|
||||
#include "RTE/RTE.h"
|
||||
|
||||
#if defined __linux__ || defined __APPLE__
|
||||
# define DL_OPEN
|
||||
#endif
|
||||
|
||||
#ifdef DL_OPEN
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if defined _WIN32
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
typedef void (*loader_registrar_t)(gem_loader_t loader);
|
||||
}
|
||||
static loader_registrar_t rte_register_loader = NULL;
|
||||
|
||||
static int find_rte_loader(void) {
|
||||
if(rte_register_loader)return 1;
|
||||
gem::RTE::RTE*rte=gem::RTE::RTE::getRuntimeEnvironment();
|
||||
if(rte)
|
||||
rte_register_loader=(loader_registrar_t)rte->getFunction("sys_register_loader");
|
||||
return(NULL!=rte_register_loader);
|
||||
}
|
||||
|
||||
void gem_register_loader(gem_loader_t loader) {
|
||||
if(find_rte_loader()) {
|
||||
rte_register_loader(loader);
|
||||
}
|
||||
}
|
||||
25
Gem/src/Gem/Loaders.h
Normal file
25
Gem/src/Gem/Loaders.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
- registers a loader with Pd
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_LOADERS_H_
|
||||
#define _INCLUDE__GEM_GEM_LOADERS_H_
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
extern "C" {
|
||||
typedef int (*gem_loader_t)(t_canvas *canvas, char *classname);
|
||||
void gem_register_loader(gem_loader_t loader);
|
||||
}
|
||||
|
||||
#endif
|
||||
113
Gem/src/Gem/Makefile.am
Normal file
113
Gem/src/Gem/Makefile.am
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
#####################################################################
|
||||
# Gem/Gem: core infrastructure of Gem
|
||||
#####################################################################
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src @GEM_CPPFLAGS@
|
||||
include ../check-sources.mk
|
||||
|
||||
noinst_LTLIBRARIES = libGem.la
|
||||
|
||||
libGem_la_CXXFLAGS =
|
||||
libGem_la_LIBADD =
|
||||
libGem_la_LDFLAGS =
|
||||
|
||||
# RTE flags
|
||||
libGem_la_CXXFLAGS += @GEM_RTE_CFLAGS@ @GEM_ARCH_CXXFLAGS@
|
||||
libGem_la_LIBADD += @GEM_RTE_LIBS@
|
||||
libGem_la_LDFLAGS += @GEM_ARCH_LDFLAGS@
|
||||
|
||||
|
||||
# GLEW
|
||||
libGem_la_CXXFLAGS += @GEM_LIB_GLEW_CFLAGS@
|
||||
libGem_la_LIBADD += @GEM_LIB_GLEW_LIBS@
|
||||
|
||||
|
||||
|
||||
libGem_la_includedir = $(includedir)/Gem/Gem
|
||||
libGem_la_include_HEADERS = \
|
||||
ExportDef.h \
|
||||
Version.h \
|
||||
RTE.h \
|
||||
State.h \
|
||||
Cache.h \
|
||||
Rectangle.h \
|
||||
Exception.h \
|
||||
Dylib.h \
|
||||
Files.h \
|
||||
ContextData.h \
|
||||
Properties.h \
|
||||
Settings.h \
|
||||
Loaders.h \
|
||||
Manager.h \
|
||||
PBuffer.h \
|
||||
Event.h
|
||||
|
||||
libGem_la_include_HEADERS += \
|
||||
GemGL.h \
|
||||
glew.h \
|
||||
glxew.h \
|
||||
wglew.h \
|
||||
GLStack.h
|
||||
|
||||
libGem_la_include_HEADERS += \
|
||||
Image.h \
|
||||
ImageIO.h \
|
||||
PixConvert.h
|
||||
|
||||
libGem_la_SOURCES =
|
||||
|
||||
if !HAVE_LIB_GLEW
|
||||
libGem_la_SOURCES += glew.cpp
|
||||
endif !HAVE_LIB_GLEW
|
||||
|
||||
libGem_la_SOURCES += \
|
||||
configDarwin.h \
|
||||
configLinux.h \
|
||||
configNT.h \
|
||||
GemConfig.h \
|
||||
GemGL.h \
|
||||
glew.h \
|
||||
glxew.h \
|
||||
wglew.h \
|
||||
Cache.cpp \
|
||||
Cache.h \
|
||||
ContextData.cpp \
|
||||
ContextData.h \
|
||||
Dylib.cpp \
|
||||
Dylib.h \
|
||||
Event.cpp \
|
||||
Event.h \
|
||||
Exception.cpp \
|
||||
Exception.h \
|
||||
ExportDef.h \
|
||||
Files.cpp \
|
||||
Files.h \
|
||||
GLStack.cpp \
|
||||
GLStack.h \
|
||||
Image.cpp \
|
||||
Image.h \
|
||||
ImageLoad.cpp \
|
||||
ImageSave.cpp \
|
||||
ImageIO.h \
|
||||
PixConvert.h \
|
||||
PixConvertAltivec.cpp \
|
||||
PixConvertSSE2.cpp \
|
||||
Loaders.cpp \
|
||||
Loaders.h \
|
||||
Manager.cpp \
|
||||
Manager.h \
|
||||
PBuffer.cpp \
|
||||
PBuffer.h \
|
||||
Properties.cpp \
|
||||
Properties.h \
|
||||
Rectangle.cpp \
|
||||
Rectangle.h \
|
||||
RTE.h \
|
||||
Settings.cpp \
|
||||
Settings.h \
|
||||
Setup.cpp \
|
||||
State.cpp \
|
||||
State.h \
|
||||
Version.h
|
||||
|
||||
15
Gem/src/Gem/Makefile.am.template
Normal file
15
Gem/src/Gem/Makefile.am.template
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
AM_CPPFLAGS = -I$(top_srcdir)
|
||||
|
||||
noinst_LTLIBRARIES = libGem.la
|
||||
|
||||
libGem_la_CXXFLAGS =
|
||||
libGem_la_LIBADD =
|
||||
|
||||
# RTE flags
|
||||
libGem_la_CXXFLAGS += @GEM_RTE_CFLAGS@
|
||||
libGem_la_LIBADD += @GEM_RTE_LIBS@
|
||||
|
||||
libGem_la_SOURCES= @SOURCES@
|
||||
|
||||
1447
Gem/src/Gem/Manager.cpp
Normal file
1447
Gem/src/Gem/Manager.cpp
Normal file
File diff suppressed because it is too large
Load diff
250
Gem/src/Gem/Manager.h
Normal file
250
Gem/src/Gem/Manager.h
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The base functions and structures
|
||||
Also includes gemwin header file
|
||||
|
||||
Copyright (c) 1997-2000 Mark Danks.mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_MANAGER_H_
|
||||
#define _INCLUDE__GEM_GEM_MANAGER_H_
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
#include "Utils/GLUtil.h"
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class gemhead;
|
||||
class GemState;
|
||||
class WindowInfo;
|
||||
|
||||
namespace gem {
|
||||
class Context;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemMan
|
||||
|
||||
A static class to create windows, etc.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN GemMan
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Should only be called once (usually by GemSetup)
|
||||
static void initGem(void);
|
||||
|
||||
//////////
|
||||
static void addObj(gemhead *obj, float priority);
|
||||
|
||||
//////////
|
||||
static void removeObj(gemhead *obj, float priority);
|
||||
|
||||
//////////
|
||||
// Is there a window.
|
||||
static int windowExists(void);
|
||||
|
||||
//////////
|
||||
// Are we rendering.
|
||||
static int getRenderState(void);
|
||||
|
||||
//////////
|
||||
// is there a context (has its meaning under X)
|
||||
static void createContext(char* disp);
|
||||
static int contextExists(void);
|
||||
|
||||
//////////
|
||||
// If an object needs to know if the window changed.
|
||||
// This is important for display lists.
|
||||
static int windowNumber(void);
|
||||
|
||||
//////////
|
||||
// reset to the initial state
|
||||
static void resetState(void);
|
||||
|
||||
//////////
|
||||
// Just send out one frame (if double buffered, will swap buffers)
|
||||
static void render(void *);
|
||||
|
||||
static void renderChain(t_symbol *head, bool start);
|
||||
static void renderChain(t_symbol *head, GemState *state);
|
||||
|
||||
|
||||
//////////
|
||||
// Start a clock to do rendering.
|
||||
static void startRendering(void);
|
||||
|
||||
//////////
|
||||
// Stop the clock to do rendering.
|
||||
static void stopRendering(void);
|
||||
|
||||
//////////
|
||||
// Create the window with the current parameters
|
||||
static int createWindow(char* disp = 0);
|
||||
|
||||
//////////
|
||||
// Destroy the window
|
||||
static void destroyWindow(void);
|
||||
// Destroy the window after a minimal delay
|
||||
static void destroyWindowSoon(void);
|
||||
|
||||
//////////
|
||||
// Swap the buffers.
|
||||
// If single buffered, just clears the window
|
||||
static void swapBuffers(void);
|
||||
|
||||
//////////
|
||||
// Set the frame rate
|
||||
static void frameRate(float framespersecond);
|
||||
//////////
|
||||
// Get the frame rate
|
||||
static float getFramerate(void);
|
||||
|
||||
static int getProfileLevel(void);
|
||||
|
||||
static void getDimen(int*width, int*height);
|
||||
static void getRealDimen(int*width, int*height);
|
||||
static void getOffset(int*x, int*y);
|
||||
|
||||
//////////
|
||||
// Turn on/off lighting
|
||||
static void lightingOnOff(int state);
|
||||
|
||||
//////////
|
||||
// Turn on/off cursor
|
||||
static void cursorOnOff(int state);
|
||||
|
||||
//////////
|
||||
// Turn on/off topmost position
|
||||
static void topmostOnOff(int state);
|
||||
|
||||
|
||||
//////////
|
||||
// Request a lighting value - it is yours until you free it.
|
||||
// The return can be 0, in which there are too many lights
|
||||
// [in] specific - If you want a specific light. == 0 means that you don't care.
|
||||
static GLenum requestLight(int specific = 0);
|
||||
|
||||
//////////
|
||||
// Free a lighting value
|
||||
static void freeLight(GLenum lightNum);
|
||||
|
||||
//////////
|
||||
// Print out information
|
||||
static void printInfo(void);
|
||||
|
||||
//////////
|
||||
static void fillGemState(GemState &);
|
||||
|
||||
static int texture_rectangle_supported;
|
||||
|
||||
enum GemStackId { STACKMODELVIEW, STACKCOLOR, STACKTEXTURE, STACKPROJECTION };
|
||||
static GLint maxStackDepth[4]; // for push/pop of matrix-stacks
|
||||
|
||||
|
||||
static float m_perspect[6]; // values for the perspective matrix
|
||||
static float m_lookat[9]; // values for the lookat matrix
|
||||
|
||||
// LATER make this private (right now it is needed in gem2pdp)
|
||||
static int m_buffer; // single(1) or double(2)
|
||||
|
||||
private:
|
||||
|
||||
//////////
|
||||
// computer and window information
|
||||
static std::string m_title; // title to be displayed
|
||||
static int m_fullscreen; // fullscreen (1) or not (0!)
|
||||
static int m_menuBar; // hide (0), show(1), hide but autoshow(-1)
|
||||
static int m_secondscreen; // set the second screen
|
||||
static int m_height; // window height
|
||||
static int m_width; // window width
|
||||
static int m_w; // the real window width (reported by gemCreateWindow())
|
||||
static int m_h; // the real window height
|
||||
static int m_xoffset; // window offset (x)
|
||||
static int m_yoffset; // window offset (y)
|
||||
|
||||
static int m_border; // window border
|
||||
static int m_stereo; // stereoscopic
|
||||
|
||||
static int m_profile; // off(0), on(1), w/o image caching(2)
|
||||
static int m_rendering;
|
||||
|
||||
static float m_fog; // fog density
|
||||
enum FOG_TYPE
|
||||
{ FOG_OFF = 0, FOG_LINEAR, FOG_EXP, FOG_EXP2 };
|
||||
static FOG_TYPE m_fogMode; // what kind of fog we have
|
||||
static GLfloat m_fogColor[4]; // colour of the fog
|
||||
static float m_fogStart; // start of the linear fog
|
||||
static float m_fogEnd; // start of the linear fog
|
||||
|
||||
static float m_motionBlur; // motion-blur factor in double-buffer mode
|
||||
|
||||
static float fps;
|
||||
static int fsaa;
|
||||
static bool pleaseDestroy;
|
||||
|
||||
//////////
|
||||
// Changing these variables is likely to crash GEM
|
||||
// This is current rendering window information
|
||||
// The window is created and destroyed by the user, so
|
||||
// if there is no window, this will contain NULL pointers.
|
||||
static WindowInfo &getWindowInfo(void);
|
||||
|
||||
//////////
|
||||
// Changing these variables is likely to crash GEM
|
||||
// This is constant rendering window information
|
||||
// This window is always available (although not visible)
|
||||
static WindowInfo &getConstWindowInfo(void);
|
||||
static int createConstWindow(char* disp = 0);
|
||||
|
||||
// gemwin is allowed to modifying "global" window attributes
|
||||
friend class gemwin;
|
||||
friend class gem::Context;
|
||||
|
||||
static GLfloat m_clear_color[4]; // the frame buffer clear
|
||||
static GLbitfield m_clear_mask; // the clear bitmask
|
||||
static GLfloat m_mat_ambient[4]; // default ambient material
|
||||
static GLfloat m_mat_specular[4]; // default specular material
|
||||
static GLfloat m_mat_shininess; // default shininess material
|
||||
|
||||
static GLfloat m_stereoSep; // stereo separation
|
||||
static GLfloat m_stereoFocal; // distance to focal point
|
||||
static bool m_stereoLine; // draw a line between 2 stereo-screens
|
||||
|
||||
static double m_lastRenderTime; // the time of the last rendered frame
|
||||
|
||||
// gemwin should not touch the following member variables and member functions
|
||||
static int m_windowState;
|
||||
static int m_windowNumber;
|
||||
static int m_windowContext;
|
||||
static int m_cursor;
|
||||
static int m_topmost;
|
||||
|
||||
static void windowInit(void);
|
||||
static void windowCleanup(void);
|
||||
static void resetValues(void);
|
||||
|
||||
static void resizeCallback(int xsize, int ysize, void*);
|
||||
static void dispatchWinmessCallback(void);
|
||||
|
||||
//////////
|
||||
// check for supported openGL extensions we might need
|
||||
static void checkOpenGLExtensions(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
474
Gem/src/Gem/PBuffer.cpp
Normal file
474
Gem/src/Gem/PBuffer.cpp
Normal file
|
|
@ -0,0 +1,474 @@
|
|||
/* OpenGL pixel buffer
|
||||
*
|
||||
* Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if 0
|
||||
# define debug error
|
||||
#else
|
||||
# define debug
|
||||
#endif
|
||||
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <iostream>
|
||||
# include <Carbon/Carbon.h>
|
||||
#else
|
||||
# include <vector>
|
||||
#endif
|
||||
|
||||
#include "PBuffer.h"
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
#ifdef GLX_VERSION_1_3
|
||||
struct PBuffer_data {
|
||||
Display *display;
|
||||
|
||||
GLXPbuffer pbuffer;
|
||||
GLXContext context;
|
||||
|
||||
GLXPbuffer old_pbuffer;
|
||||
GLXContext old_context;
|
||||
};
|
||||
|
||||
/*
|
||||
* constructor (linux specific)
|
||||
*/
|
||||
PBuffer::PBuffer(int width,int height,int flags) : width(width), height(height), data(NULL)
|
||||
{
|
||||
Display *display = glXGetCurrentDisplay();
|
||||
int screen = DefaultScreen(display);
|
||||
GLXContext old_context = glXGetCurrentContext();
|
||||
|
||||
std::vector<int> attrib;
|
||||
attrib.push_back(GLX_RENDER_TYPE);
|
||||
attrib.push_back(GLX_RGBA_BIT);
|
||||
attrib.push_back(GLX_DRAWABLE_TYPE);
|
||||
attrib.push_back(GLX_PBUFFER_BIT);
|
||||
if(flags & GEM_PBUFLAG_RGB || flags & GEM_PBUFLAG_RGBA) {
|
||||
attrib.push_back(GLX_RED_SIZE);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
attrib.push_back(GLX_GREEN_SIZE);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
attrib.push_back(GLX_BLUE_SIZE);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
if(flags & GEM_PBUFLAG_RGBA) {
|
||||
attrib.push_back(GLX_ALPHA_SIZE);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
}
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_DEPTH) {
|
||||
attrib.push_back(GLX_DEPTH_SIZE);
|
||||
attrib.push_back(24);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_STENCIL) {
|
||||
attrib.push_back(GLX_STENCIL_SIZE);
|
||||
attrib.push_back(8);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_FLOAT) {
|
||||
attrib.push_back(GLX_FLOAT_COMPONENTS_NV);
|
||||
attrib.push_back(true);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_MULTISAMPLE_2 || flags & GEM_PBUFLAG_MULTISAMPLE_4) {
|
||||
attrib.push_back(GLX_SAMPLE_BUFFERS_ARB);
|
||||
attrib.push_back(true);
|
||||
attrib.push_back(GLX_SAMPLES_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_MULTISAMPLE_2 ? 2 : 4);
|
||||
}
|
||||
attrib.push_back(0);
|
||||
|
||||
std::vector<int> pattrib;
|
||||
|
||||
pattrib.push_back(GLX_LARGEST_PBUFFER);
|
||||
pattrib.push_back(true);
|
||||
pattrib.push_back(GLX_PRESERVED_CONTENTS);
|
||||
pattrib.push_back(true);
|
||||
|
||||
GLXPbuffer pbuffer;
|
||||
GLXContext context;
|
||||
|
||||
try {
|
||||
int count;
|
||||
GLXFBConfig *config;
|
||||
|
||||
if(GLXEW_SGIX_fbconfig && GLXEW_SGIX_pbuffer) {
|
||||
debug("using SGIX pbuffers\n");
|
||||
pattrib.push_back(0);
|
||||
|
||||
config = glXChooseFBConfigSGIX(display,screen,&attrib[0],&count);
|
||||
if(!config) throw("glXChooseFBConfigSGIX() failed");
|
||||
|
||||
pbuffer = glXCreateGLXPbufferSGIX(display,config[0],width,height,&pattrib[0]);
|
||||
if(!pbuffer) throw("glXCreateGLXPbufferSGIX() failed");
|
||||
|
||||
context = glXCreateContextWithConfigSGIX(display,config[0],GLX_RGBA_TYPE,old_context,true);
|
||||
if(!context) throw("glXCreateContextWithConfigSGIX() failed");
|
||||
} else if (NULL!=glXChooseFBConfig) { /* LATER make a better check! */
|
||||
debug("using GLX pbuffers");
|
||||
pattrib.push_back(GLX_PBUFFER_WIDTH);
|
||||
pattrib.push_back(width);
|
||||
pattrib.push_back(GLX_PBUFFER_HEIGHT);
|
||||
pattrib.push_back(height);
|
||||
pattrib.push_back(0);
|
||||
|
||||
config = glXChooseFBConfig(display,screen,&attrib[0],&count);
|
||||
if(!config) throw("glXChooseFBConfig() failed");
|
||||
|
||||
pbuffer = glXCreatePbuffer(display,config[0],&pattrib[0]);
|
||||
if(!pbuffer) throw("glXCreatePbuffer() failed");
|
||||
|
||||
XVisualInfo *visual = glXGetVisualFromFBConfig(display,config[0]);
|
||||
if(!visual) throw("glXGetVisualFromFBConfig() failed");
|
||||
|
||||
context = glXCreateContext(display,visual,old_context,true);
|
||||
if(!context) throw("glXCreateContext() failed");
|
||||
} else {
|
||||
throw("your system lacks PBuffer support!");
|
||||
}
|
||||
}
|
||||
catch(const char *err) {
|
||||
error("PBuffer::PBuffer(): %s",err);
|
||||
pbuffer = glXGetCurrentDrawable();
|
||||
context = old_context;
|
||||
}
|
||||
|
||||
data = new PBuffer_data;
|
||||
data->display = display;
|
||||
|
||||
data->pbuffer = pbuffer;
|
||||
data->context = context;
|
||||
|
||||
data->old_pbuffer = glXGetCurrentDrawable();
|
||||
data->old_context = old_context;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
PBuffer::~PBuffer() {
|
||||
if(data->context) glXDestroyContext(data->display,data->context);
|
||||
if(data->pbuffer) glXDestroyPbuffer(data->display,data->pbuffer);
|
||||
delete data;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::enable() {
|
||||
data->old_pbuffer = glXGetCurrentDrawable();
|
||||
data->old_context = glXGetCurrentContext();
|
||||
|
||||
if(!glXMakeCurrent(data->display,data->pbuffer,data->context)) {
|
||||
error("PBuffer::enable(): glXMakeCurrent() failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::disable() {
|
||||
if(!glXMakeCurrent(data->display,data->old_pbuffer,data->old_context)) {
|
||||
error("PBuffer::disable(): glXMakeCurrent() failed");
|
||||
}
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
#pragma mark ------AppleCode------
|
||||
/*
|
||||
Apple OSX pBuffer Setup
|
||||
*/
|
||||
|
||||
struct PBuffer_data {
|
||||
CGLPBufferObj pbuffer;
|
||||
CGLContextObj context;
|
||||
|
||||
CGLContextObj old_context;
|
||||
CGLPixelFormatObj pixfmt;
|
||||
};
|
||||
|
||||
#pragma mark ---- Error Reporting ----
|
||||
|
||||
// ---------------------------------
|
||||
float gErrorTime = 0.0;
|
||||
extern AbsoluteTime gStartTime;
|
||||
char gErrorMessage[256] = "";
|
||||
// error reporting as both window message and debugger string
|
||||
void reportError (char * strError)
|
||||
{
|
||||
//gErrorTime = getElapsedTime ();
|
||||
//sprintf (gErrorMessage, "Error: %s (at time: %0.1f secs)", strError, gErrorTime);
|
||||
error ("Error: %s", strError);
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
|
||||
// if error dump cgl errors to debugger string, return error
|
||||
OSStatus cglReportError (CGLError err)
|
||||
{
|
||||
if (0 != err)
|
||||
reportError ((char *) CGLErrorString(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* constructor (APPLE specific)
|
||||
*/
|
||||
PBuffer::PBuffer(int width, int height, int flag) : width(width), height(height)
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
CGLPixelFormatAttribute *att,attrib[64];
|
||||
GemCGLint vs, npf;
|
||||
|
||||
// setup offscreen context
|
||||
att=attrib;
|
||||
*att++=kCGLPFANoRecovery;
|
||||
*att++=kCGLPFAAccelerated;
|
||||
*att++=kCGLPFAWindow;
|
||||
// *att++=kCGLPFAPBuffer;
|
||||
*att++=kCGLPFAColorSize;
|
||||
*att++=(CGLPixelFormatAttribute)32;
|
||||
|
||||
if (flag & GEM_PBUFLAG_DEPTH){
|
||||
*att++=kCGLPFADepthSize;
|
||||
//*att++=(CGLPixelFormatAttribute)24;
|
||||
*att++=(CGLPixelFormatAttribute)16;
|
||||
}
|
||||
if (flag & GEM_PBUFLAG_STENCIL){
|
||||
*att++=kCGLPFADepthSize;
|
||||
*att++=(CGLPixelFormatAttribute)8;
|
||||
}
|
||||
if (flag & GEM_PBUFLAG_FLOAT){
|
||||
// *att++=kCGLPFADepthSize;
|
||||
// *att++=(CGLPixelFormatAttribute)8;
|
||||
}
|
||||
//*att++=kCGLPFADoubleBuffer;
|
||||
// *att++=kCGLPFADisplayMask;
|
||||
// *att++=kCGLPFAAllRenderers;
|
||||
|
||||
*att=(CGLPixelFormatAttribute)0;
|
||||
|
||||
data = new PBuffer_data;
|
||||
data->old_context = CGLGetCurrentContext();
|
||||
err = CGLGetVirtualScreen(data->old_context, &vs);
|
||||
verbose (2, "Target Context (0x%X) Renderer: %s\n",data->old_context, glGetString (GL_RENDERER));
|
||||
cglReportError(CGLChoosePixelFormat (attrib, &data->pixfmt, &npf));
|
||||
|
||||
cglReportError(CGLCreateContext (data->pixfmt, data->old_context, &(data->context)));
|
||||
verbose (2, "pBuffer Context (0x%X) Renderer: %s\n",data->context, glGetString (GL_RENDERER));
|
||||
|
||||
/* if (float_buffer)
|
||||
cglReportError( CGLCreatePBuffer ( width, height, GL_TEXTURE_2D, GL_FLOAT, 0, &(data->pbuffer) ) );
|
||||
else
|
||||
*/
|
||||
cglReportError( CGLCreatePBuffer ( width, height, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, &(data->pbuffer) ));
|
||||
cglReportError( CGLSetCurrentContext( data->context ) );
|
||||
cglReportError( CGLGetVirtualScreen(data->old_context, &vs) );
|
||||
cglReportError( CGLSetPBuffer(data->context, data->pbuffer, 0, 0, vs) );
|
||||
verbose (2, "pbuffer (0x%X) Renderer: %s\n",data->pbuffer, glGetString (GL_RENDERER));
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
PBuffer::~PBuffer()
|
||||
{
|
||||
if(data->context) CGLDestroyContext( data->context );
|
||||
if(data->pbuffer) CGLDestroyPBuffer( data->pbuffer );
|
||||
if(data->pixfmt) CGLDestroyPixelFormat( data->pixfmt );
|
||||
CGLSetCurrentContext(NULL);
|
||||
|
||||
delete data;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::enable()
|
||||
{
|
||||
GemCGLint vs;
|
||||
|
||||
cglReportError (CGLSetCurrentContext (data->context));
|
||||
cglReportError (CGLGetVirtualScreen ( data->old_context, &vs ));
|
||||
cglReportError( CGLSetPBuffer( data->context, data->pbuffer, 0, 0, vs) );
|
||||
debug ("enable Context (0x%X) Renderer: %s\n",CGLGetCurrentContext(), glGetString (GL_RENDERER));
|
||||
debug ("pBuffer Context (0x%X) Renderer: %s\n",data->context, glGetString (GL_RENDERER));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::disable() {
|
||||
cglReportError ( CGLSetCurrentContext( data->old_context) );
|
||||
return;
|
||||
}
|
||||
#elif defined _WIN32
|
||||
|
||||
struct PBuffer_data {
|
||||
HDC hdc;
|
||||
HPBUFFERARB pbuffer;
|
||||
HGLRC context;
|
||||
|
||||
HDC old_hdc;
|
||||
HGLRC old_context;
|
||||
};
|
||||
|
||||
#ifndef wglChoosePixelFormatARB
|
||||
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
|
||||
#endif
|
||||
#ifndef wglCreatePbufferARB
|
||||
static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = NULL;
|
||||
#endif
|
||||
#ifndef wglGetPbufferDCARB
|
||||
static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = NULL;
|
||||
#endif
|
||||
#ifndef wglReleasePbufferDCARB
|
||||
static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = NULL;
|
||||
#endif
|
||||
#ifndef wglDestroyPbufferARB
|
||||
static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = NULL;
|
||||
#endif
|
||||
/*
|
||||
* constructor (w32 specific)
|
||||
*/
|
||||
PBuffer::PBuffer(int width,int height,int flags) : width(width), height(height) {
|
||||
|
||||
HDC old_hdc = wglGetCurrentDC();
|
||||
HGLRC old_context = wglGetCurrentContext();
|
||||
|
||||
std::vector<int> attrib;
|
||||
attrib.push_back(WGL_PIXEL_TYPE_ARB);
|
||||
attrib.push_back(WGL_TYPE_RGBA_ARB);
|
||||
attrib.push_back(WGL_DRAW_TO_PBUFFER_ARB);
|
||||
attrib.push_back(true);
|
||||
attrib.push_back(WGL_SUPPORT_OPENGL_ARB);
|
||||
attrib.push_back(true);
|
||||
if(flags & GEM_PBUFLAG_RGB || flags & GEM_PBUFLAG_RGBA) {
|
||||
attrib.push_back(WGL_RED_BITS_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
attrib.push_back(WGL_GREEN_BITS_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
attrib.push_back(WGL_BLUE_BITS_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
if(flags & GEM_PBUFLAG_RGBA) {
|
||||
attrib.push_back(WGL_ALPHA_BITS_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_FLOAT ? 32 : 8);
|
||||
}
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_DEPTH) {
|
||||
attrib.push_back(WGL_DEPTH_BITS_ARB);
|
||||
attrib.push_back(24);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_STENCIL) {
|
||||
attrib.push_back(WGL_STENCIL_BITS_ARB);
|
||||
attrib.push_back(8);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_FLOAT) {
|
||||
attrib.push_back(WGL_FLOAT_COMPONENTS_NV);
|
||||
attrib.push_back(true);
|
||||
}
|
||||
if(flags & GEM_PBUFLAG_MULTISAMPLE_2 || flags & GEM_PBUFLAG_MULTISAMPLE_4) {
|
||||
attrib.push_back(WGL_SAMPLE_BUFFERS_ARB);
|
||||
attrib.push_back(true);
|
||||
attrib.push_back(WGL_SAMPLES_ARB);
|
||||
attrib.push_back(flags & GEM_PBUFLAG_MULTISAMPLE_2 ? 2 : 4);
|
||||
}
|
||||
attrib.push_back(0);
|
||||
|
||||
HDC hdc;
|
||||
HPBUFFERARB pbuffer;
|
||||
HGLRC context;
|
||||
|
||||
try {
|
||||
|
||||
if(!wglChoosePixelFormatARB) wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
if(!wglChoosePixelFormatARB) throw("wglGetProcAddress(\"wglChoosePixelFormatARB\") failed");
|
||||
|
||||
if(!wglCreatePbufferARB) wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
|
||||
if(!wglCreatePbufferARB) throw("wglGetProcAddress(\"wglCreatePbufferARB\") failed");
|
||||
|
||||
if(!wglGetPbufferDCARB) wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB");
|
||||
if(!wglGetPbufferDCARB) throw("wglGetProcAddress(\"wglGetPbufferDCARB\") failed");
|
||||
|
||||
if(!wglReleasePbufferDCARB) wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB");
|
||||
if(!wglReleasePbufferDCARB) throw("wglGetProcAddress(\"wglReleasePbufferDCARB\") failed\n");
|
||||
|
||||
if(!wglDestroyPbufferARB) wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB");
|
||||
if(!wglDestroyPbufferARB) throw("wglGetProcAddress(\"wglDestroyPbufferARB\") failed\n");
|
||||
|
||||
int pixelformat;
|
||||
unsigned int count;
|
||||
wglChoosePixelFormatARB(old_hdc,&attrib[0],NULL,1,&pixelformat,&count);
|
||||
if(count == 0) throw("wglChoosePixelFormatARB() failed");
|
||||
|
||||
int pattrib[] = { 0 };
|
||||
|
||||
pbuffer = wglCreatePbufferARB(old_hdc,pixelformat,width,height,pattrib);
|
||||
if(!pbuffer) throw("wglCreatePbufferARB() failed");
|
||||
|
||||
hdc = wglGetPbufferDCARB(pbuffer);
|
||||
if(!hdc) throw("wglGetPbufferDCARB() failed");
|
||||
|
||||
context = wglCreateContext(hdc);
|
||||
if(!context) throw("wglCreateContext() failed");
|
||||
|
||||
if(!wglShareLists(old_context,context)) throw("wglShareLists() failed");
|
||||
}
|
||||
catch(const char *err) {
|
||||
error("GemPBuffer: %s",err);
|
||||
hdc = old_hdc;
|
||||
context = old_context;
|
||||
}
|
||||
|
||||
data = new PBuffer_data;
|
||||
data->hdc = hdc;
|
||||
data->pbuffer = pbuffer;
|
||||
data->context = context;
|
||||
|
||||
data->old_hdc = old_hdc;
|
||||
data->old_context = old_context;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
PBuffer::~PBuffer() {
|
||||
wglDeleteContext(data->context);
|
||||
wglReleasePbufferDCARB(data->pbuffer,data->hdc);
|
||||
wglDestroyPbufferARB(data->pbuffer);
|
||||
wglMakeCurrent(data->hdc,data->context);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::enable() {
|
||||
data->old_hdc = wglGetCurrentDC();
|
||||
data->old_context = wglGetCurrentContext();
|
||||
|
||||
if(!wglMakeCurrent(data->hdc,data->context)) {
|
||||
error("PBuffer::disable(): wglMakeCurrent() failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void PBuffer::disable() {
|
||||
if(!wglMakeCurrent(data->old_hdc,data->old_context)) {
|
||||
error("PBuffer::disable(): wglMakeCurrent() failed");
|
||||
}
|
||||
}
|
||||
#else
|
||||
# error do Pbuffers on your OS !
|
||||
#endif /* OS */
|
||||
|
||||
/* dummy implementations */
|
||||
PBuffer::PBuffer(const PBuffer&org) : width(org.width), height(org.height), data(NULL) {}
|
||||
PBuffer&PBuffer::operator=(const PBuffer&org) { return (*this);}
|
||||
54
Gem/src/Gem/PBuffer.h
Normal file
54
Gem/src/Gem/PBuffer.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* OpenGL pixel buffer
|
||||
*
|
||||
* Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __PBUFFER_H__
|
||||
#define __PBUFFER_H__
|
||||
|
||||
struct PBuffer_data;
|
||||
|
||||
class PBuffer {
|
||||
public:
|
||||
|
||||
enum {
|
||||
GEM_PBUFLAG_RGB = 1 << 0,
|
||||
GEM_PBUFLAG_RGBA = 1 << 1,
|
||||
GEM_PBUFLAG_DEPTH = 1 << 2,
|
||||
GEM_PBUFLAG_STENCIL = 1 << 3,
|
||||
GEM_PBUFLAG_FLOAT = 1 << 4,
|
||||
GEM_PBUFLAG_MULTISAMPLE_2 = 1 << 5,
|
||||
GEM_PBUFLAG_MULTISAMPLE_4 = 1 << 6
|
||||
};
|
||||
|
||||
PBuffer(int width,int height,int flags = GEM_PBUFLAG_RGBA | GEM_PBUFLAG_DEPTH | GEM_PBUFLAG_STENCIL);
|
||||
~PBuffer(void);
|
||||
|
||||
void enable(void);
|
||||
void disable(void);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
private:
|
||||
struct PBuffer_data *data;
|
||||
|
||||
PBuffer(const PBuffer&);
|
||||
PBuffer&operator=(const PBuffer&);
|
||||
};
|
||||
|
||||
#endif /* __PBUFFER_H__ */
|
||||
173
Gem/src/Gem/PixConvert.h
Normal file
173
Gem/src/Gem/PixConvert.h
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
GemPixConvertSIMD.h
|
||||
- header-file for color conversion
|
||||
- this is mainly for (SIMD-)optimized routines
|
||||
- part of GEM
|
||||
|
||||
Copyright (c) 2006-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_PIXCONVERT_H_
|
||||
#define _INCLUDE__GEM_GEM_PIXCONVERT_H_
|
||||
|
||||
#include "Gem/Image.h"
|
||||
#include "Utils/SIMD.h"
|
||||
|
||||
// use formulae from http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
|
||||
/*
|
||||
* [Y] 1 [ 65.738 129.075 25.064 ] [R] [ 16]
|
||||
* [U] = --- * [ -37.945 -74.494 112.439 ] * [G]+[128]
|
||||
* [V] = 256 [ 112.439 -94.154 -18.285 ] [B] [128]
|
||||
*
|
||||
* [R] 1 [ 298.082 0.0 408.583 ] [Y] [ 16]
|
||||
* [G] = --- * [ 298.082 -100.291 -208.120 ] * ([U]-[128])
|
||||
* [B] = 256 [ 298.082 516.411 0.0 ] [V] [128]
|
||||
*/
|
||||
|
||||
#define YUV_POYNTON
|
||||
// here comes something to be afraid of:
|
||||
// (probably it would be better to define the matrices as real constant-value matrices)
|
||||
// (instead of element-wise)
|
||||
|
||||
#ifdef YUV_POYNTON
|
||||
# define Y_OFFSET 16
|
||||
# define UV_OFFSET 128
|
||||
|
||||
// RGB2YUV
|
||||
// poynton-values rounded
|
||||
# define RGB2YUV_11 66
|
||||
# define RGB2YUV_12 129
|
||||
# define RGB2YUV_13 25
|
||||
# define RGB2YUV_21 -38
|
||||
# define RGB2YUV_22 -74
|
||||
# define RGB2YUV_23 112
|
||||
# define RGB2YUV_31 112
|
||||
# define RGB2YUV_32 -94
|
||||
# define RGB2YUV_33 -18
|
||||
|
||||
// YUV2RGB
|
||||
// (we skip _21 and _31 as they are equal to _11)
|
||||
#if 0
|
||||
// poynton-values rounded
|
||||
# define YUV2RGB_11 298
|
||||
# define YUV2RGB_12 0
|
||||
# define YUV2RGB_13 409
|
||||
# define YUV2RGB_22 -100
|
||||
# define YUV2RGB_23 -208
|
||||
# define YUV2RGB_32 516
|
||||
# define YUV2RGB_33 0
|
||||
#else
|
||||
|
||||
// this is round(256*inv(rgb2yuv/256))
|
||||
// so the general error should be smaller
|
||||
# define YUV2RGB_11 298
|
||||
# define YUV2RGB_12 -1
|
||||
# define YUV2RGB_13 409
|
||||
# define YUV2RGB_22 -100
|
||||
# define YUV2RGB_23 -210
|
||||
# define YUV2RGB_32 519
|
||||
# define YUV2RGB_33 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
/* the old ones: */
|
||||
# define Y_OFFSET 0
|
||||
# define UV_OFFSET 128
|
||||
// RGB2YUV
|
||||
# define RGB2YUV_11 77
|
||||
# define RGB2YUV_12 150
|
||||
# define RGB2YUV_13 29
|
||||
# define RGB2YUV_21 -43
|
||||
# define RGB2YUV_22 -85
|
||||
# define RGB2YUV_23 128
|
||||
# define RGB2YUV_31 128
|
||||
# define RGB2YUV_32 -107
|
||||
# define RGB2YUV_33 -21
|
||||
// YUV2RGB
|
||||
# define YUV2RGB_11 256
|
||||
# define YUV2RGB_12 0
|
||||
# define YUV2RGB_13 359
|
||||
# define YUV2RGB_22 -88
|
||||
# define YUV2RGB_23 -183
|
||||
# define YUV2RGB_32 454
|
||||
# define YUV2RGB_33 0
|
||||
|
||||
#endif /* POYNTON */
|
||||
|
||||
#if 0
|
||||
/* yuv-coefficients would also need an offset! */
|
||||
# define RGB2GRAY_RED RGB2YUV_11
|
||||
# define RGB2GRAY_GREEN RGB2YUV_12
|
||||
# define RGB2GRAY_BLUE RGB2YUV_13
|
||||
# define RGB2GRAY_OFFSET Y_OFFSET
|
||||
#else
|
||||
# define RGB2GRAY_RED 77
|
||||
# define RGB2GRAY_GREEN 150
|
||||
# define RGB2GRAY_BLUE 29
|
||||
# define RGB2GRAY_OFFSET 0
|
||||
#endif
|
||||
|
||||
/* AltiVec */
|
||||
#ifdef __VEC__
|
||||
|
||||
/* there are problems on OSX10.3 with older versions of gcc, since the intrinsic code
|
||||
* below freely changes between signed and unsigned short vectors
|
||||
* newer versions of gcc accept this...
|
||||
* LATER: fix the code (GemPixConvertAltivec:750..800)
|
||||
*/
|
||||
# ifdef __GNUC__
|
||||
/* according to hcs it does NOT work with gcc-3.3
|
||||
* for simplicity, i disable everything below gcc4
|
||||
* JMZ: 20061114
|
||||
*/
|
||||
# if __GNUC__ < 4
|
||||
# warning disabling AltiVec for older gcc: please fix me
|
||||
# define NO_VECTORINT_TO_VECTORUNSIGNEDINT
|
||||
# endif
|
||||
# endif /* GNUC */
|
||||
|
||||
|
||||
void RGB_to_YCbCr_altivec(const unsigned char *rgbdata, size_t RGB_size,
|
||||
unsigned char *pixels);
|
||||
void RGBA_to_YCbCr_altivec(const unsigned char *rgbadata, size_t RGBA_size,
|
||||
unsigned char *pixels);
|
||||
void BGR_to_YCbCr_altivec(const unsigned char *bgrdata, size_t BGR_size,
|
||||
unsigned char *pixels);
|
||||
void BGRA_to_YCbCr_altivec(const unsigned char *bgradata, size_t BGRA_size,
|
||||
unsigned char *pixels);
|
||||
void YUV422_to_BGRA_altivec(const unsigned char *yuvdata, size_t pixelnum,
|
||||
unsigned char *pixels);
|
||||
void YV12_to_YUV422_altivec(const short*Y, const short*U, const short*V,
|
||||
unsigned char *data, int xsize, int ysize);
|
||||
# ifndef NO_VECTORINT_TO_VECTORUNSIGNEDINT
|
||||
void YUV422_to_YV12_altivec(short*pY, short*pY2, short*pU, short*pV,
|
||||
const unsigned char *gem_image, int xsize, int ysize);
|
||||
# endif
|
||||
#endif /* AltiVec */
|
||||
|
||||
/* SSE2 */
|
||||
#ifdef __SSE2__
|
||||
void RGBA_to_UYVY_SSE2(const unsigned char *rgbadata,
|
||||
size_t size,
|
||||
unsigned char *yuvdata);
|
||||
void UYVY_to_RGBA_SSE2(const unsigned char *yuvdata,
|
||||
size_t size,
|
||||
unsigned char *rgbadata);
|
||||
void UYVY_to_RGB_SSE2(const unsigned char *yuvdata,
|
||||
size_t size,
|
||||
unsigned char *rgbadata);
|
||||
#endif /* SSE2 */
|
||||
|
||||
/* in case somebody has an old machine... */
|
||||
#ifdef __MMX__
|
||||
|
||||
#endif /* MMX */
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_PIXCONVERT_H_ */
|
||||
827
Gem/src/Gem/PixConvertAltivec.cpp
Normal file
827
Gem/src/Gem/PixConvertAltivec.cpp
Normal file
|
|
@ -0,0 +1,827 @@
|
|||
#include "Utils/SIMD.h"
|
||||
#ifdef __VEC__
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file for AltiVec-optimized color-conversion routines
|
||||
//
|
||||
// Copyright (c) 2005-2006 James Tittle
|
||||
// Copyright (c) 2005-2006 Chris Clepper
|
||||
// Copyright (c) 2006-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "PixConvert.h"
|
||||
|
||||
void RGB_to_YCbCr_altivec(const unsigned char *rgbdata, size_t RGB_size,
|
||||
unsigned char *pixels)
|
||||
{
|
||||
vector signed short r0, r1, r2, g0, g1, g2, b0, b1, b2, c0, c16, c128;
|
||||
vector unsigned char z0, tc0, tc1, tc2, tc3;
|
||||
vector signed short tr0, tr1, tg0, tg1, tb0, tb1;
|
||||
vector signed short t0, t1, t2, t3, t4, t5;
|
||||
unsigned int i;
|
||||
|
||||
const vector unsigned char *RGB_ptr = reinterpret_cast<const vector unsigned char*>( rgbdata);
|
||||
vector unsigned char *YCC_ptr = reinterpret_cast<vector unsigned char*>( pixels);
|
||||
|
||||
/* Permutation vector is used to extract the interleaved RGB. */
|
||||
vector unsigned char vPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 3, 6, 9, 12, 15, 18, 21, /* R0..R7 */
|
||||
1, 4, 7, 10, 13, 16, 19, 22 /* G0..G7 */);
|
||||
vector unsigned char vPerm2 =
|
||||
static_cast<vector unsigned char>( 2, 5, 8, 11, 14, 17, 20, 23, /* B0..B7 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
vector unsigned char vPerm3 =
|
||||
static_cast<vector unsigned char>( 8, 11, 14, 17, 20, 23, 26, 29, /* R8..R15 */
|
||||
9, 12, 15, 18, 21, 24, 27, 30 /* G8..G15 */);
|
||||
vector unsigned char vPerm4 =
|
||||
static_cast<vector unsigned char>(10, 13, 16, 19, 22, 25, 28, 31, /* B8..B15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
|
||||
/* Load the equation constants. */
|
||||
vector signed short vConst1 =
|
||||
static_cast<vector signed short>( 8432, 16425, 3176,
|
||||
-4818, -9527, 14345,
|
||||
0, 0 );
|
||||
|
||||
vector signed short vConst2 =
|
||||
static_cast<vector signed short>( 14345, -12045, -2300,
|
||||
16, 128, 0, 0, 0 );
|
||||
|
||||
r0 = vec_splat( vConst1, 0 ); /* 8432 */
|
||||
g0 = vec_splat( vConst1, 1 ); /* 16425 */
|
||||
b0 = vec_splat( vConst1, 2 ); /* 3176 */
|
||||
r1 = vec_splat( vConst1, 3 ); /* -4818 */
|
||||
g1 = vec_splat( vConst1, 4 ); /* -9527 */
|
||||
b1 = vec_splat( vConst1, 5 ); /* 14345 */
|
||||
r2 = vec_splat( vConst2, 0 ); /* 14345 */
|
||||
g2 = vec_splat( vConst2, 1 ); /*-12045 */
|
||||
b2 = vec_splat( vConst2, 2 ); /* -2300 */
|
||||
c16 = vec_splat( vConst2, 3 ); /* 16 */
|
||||
c128 = vec_splat( vConst2, 4 ); /* 128 */
|
||||
c0 = static_cast<vector signed short> (0); /* 0 */
|
||||
z0 = static_cast<vector unsigned char> (0); /* 0 */
|
||||
|
||||
for ( i = 0; i < (RGB_size/sizeof(vector unsigned char)); i+=3 ) {
|
||||
|
||||
/* Load the 3 RGB input vectors and seperate into red,
|
||||
green and blue from the interleaved format. */
|
||||
tc0 = vec_perm( RGB_ptr[i], RGB_ptr[i+1], vPerm1 ); /* R0..R7 G0..G7 */
|
||||
tc1 = vec_perm( RGB_ptr[i], RGB_ptr[i+1], vPerm2 ); /* B0..B7 */
|
||||
tc2 = vec_perm( RGB_ptr[i+1], RGB_ptr[i+2], vPerm3 ); /* R8..R15 G8..G15 */
|
||||
tc3 = vec_perm( RGB_ptr[i+1], RGB_ptr[i+2], vPerm4 ); /* B8..B15 */
|
||||
|
||||
/* Unpack to 16 bit arithmatic for converstion. */
|
||||
tr0 = static_cast<vector signed short>(vec_mergeh( z0, tc0 )); // tr0 = R0 .. R7
|
||||
tg0 = static_cast<vector signed short>(vec_mergel( z0, tc0 )); // tg0 = G0 .. G7
|
||||
tb0 = static_cast<vector signed short>(vec_mergeh( z0, tc1 )); // tb0 = B0 .. B7
|
||||
tr1 = static_cast<vector signed short>(vec_mergeh( z0, tc2 )); // tr0 = R8 .. R15
|
||||
tg1 = static_cast<vector signed short>(vec_mergel( z0, tc2 )); // tg0 = G8 .. G15
|
||||
tb1 = static_cast<vector signed short>(vec_mergeh( z0, tc3 )); // tb0 = B8 .. B15
|
||||
|
||||
/* Convert the first three input vectors. Note that
|
||||
only the top 17 bits of the 32 bit product are
|
||||
stored. This is the same as doing the divide by 32768. */
|
||||
|
||||
t0 = vec_mradds( tr0, r0, c0 ); /* (R0 .. R7) * 8432 */
|
||||
t1 = vec_mradds( tr0, r1, c0 ); /* (R0 .. R7) * -4818 */
|
||||
t2 = vec_mradds( tr0, r2, c0 ); /* (R0 .. R7) * 14345 */
|
||||
|
||||
t0 = vec_mradds( tg0, g0, t0 ); /* += (G0 .. G7) * 16425 */
|
||||
t1 = vec_mradds( tg0, g1, t1 ); /* += (G0 .. G7) * -9527 */
|
||||
t2 = vec_mradds( tg0, g2, t2 ); /* += (G0 .. G7) * -12045 */
|
||||
|
||||
t0 = vec_mradds( tb0, b0, t0 ); /* += (B0 .. B7) * 3176 */
|
||||
t1 = vec_mradds( tb0, b1, t1 ); /* += (B0 .. B7) * 14345 */
|
||||
t2 = vec_mradds( tb0, b2, t2 ); /* += (B0 .. B7) * -2300 */
|
||||
|
||||
/* Convert the next three input vectors. */
|
||||
t3 = vec_mradds( tr1, r0, c0 ); /* (R8 .. R15) * 8432 */
|
||||
t4 = vec_mradds( tr1, r1, c0 ); /* (R8 .. R15) * -4818 */
|
||||
t5 = vec_mradds( tr1, r2, c0 ); /* (R8 .. R15) * 14345 */
|
||||
|
||||
t3 = vec_mradds( tg1, g0, t3 ); /* += (G8 .. G15) * 16425 */
|
||||
t4 = vec_mradds( tg1, g1, t4 ); /* += (G8 .. G15) * -9527 */
|
||||
t5 = vec_mradds( tg1, g2, t5 ); /* += (G8 .. G15) * -12045 */
|
||||
|
||||
t3 = vec_mradds( tb1, b0, t3 ); /* += (B8 .. B15) * 3176 */
|
||||
t4 = vec_mradds( tb1, b1, t4 ); /* += (B8 .. B15) * 14345 */
|
||||
t5 = vec_mradds( tb1, b2, t5 ); /* += (B8 .. B15) * -2300 */
|
||||
|
||||
/* Add the constants. */
|
||||
t0 = vec_adds( t0, c16 );
|
||||
t3 = vec_adds( t3, c16 );
|
||||
t1 = vec_adds( t1, c128 );
|
||||
t4 = vec_adds( t4, c128 );
|
||||
t2 = vec_adds( t2, c128 );
|
||||
t5 = vec_adds( t5, c128 );
|
||||
|
||||
/* Pack the results, and store them. */
|
||||
YCC_ptr[i] = vec_packsu( t0, t3 ); /* Y0 .. Y15 */
|
||||
YCC_ptr[i+1] = vec_packsu( t1, t4 ); /* Cb0 .. Cb15 */
|
||||
YCC_ptr[i+2] = vec_packsu( t2, t5 ); /* Cr0 .. Cr15 */
|
||||
|
||||
}
|
||||
}
|
||||
void RGBA_to_YCbCr_altivec(const unsigned char *rgbadata, size_t RGBA_size,
|
||||
unsigned char *pixels)
|
||||
{
|
||||
vector signed short r0, r1, r2, g0, g1, g2, b0, b1, b2, c0, c16, c128;
|
||||
vector unsigned char z0, tc0, tc1, tc2, tc3;
|
||||
vector signed short tr0, tr1, tg0, tg1, tb0, tb1;
|
||||
vector signed short t0, t1, t2, t3, t4, t5;
|
||||
unsigned int i;
|
||||
|
||||
const vector unsigned char *RGBA_ptr = reinterpret_cast<const vector unsigned char*>( rgbadata);
|
||||
vector unsigned char *YCC_ptr = reinterpret_cast<vector unsigned char*>( pixels);
|
||||
|
||||
/* Permutation vector is used to extract the interleaved RGBA. */
|
||||
vector unsigned char vPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 4, 8, 12, 16, 20, 24, 28, /* R0..R7 */
|
||||
1, 5, 9, 13, 17, 21, 25, 29 /* G0..G7 */);
|
||||
vector unsigned char vPerm2 =
|
||||
static_cast<vector unsigned char>( 2, 6, 10, 14, 18, 22, 26, 30, /* B0..B7 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
vector unsigned char vPerm3 =
|
||||
static_cast<vector unsigned char>( 8, 12, 16, 20, 24, 28, 32, 36, /* R8..R15 */
|
||||
9, 13, 17, 21, 25, 29, 33, 37 /* G8..G15 */);
|
||||
vector unsigned char vPerm4 =
|
||||
static_cast<vector unsigned char>(10, 14, 18, 22, 26, 30, 34, 38, /* B8..B15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
|
||||
/* Load the equation constants. */
|
||||
vector signed short vConst1 =
|
||||
static_cast<vector signed short>( 8432, 16425, 3176,
|
||||
-4818, -9527, 14345,
|
||||
0, 0 );
|
||||
|
||||
vector signed short vConst2 =
|
||||
static_cast<vector signed short>( 14345, -12045, -2300,
|
||||
16, 128, 0, 0, 0 );
|
||||
|
||||
r0 = vec_splat( vConst1, 0 ); /* 8432 */
|
||||
g0 = vec_splat( vConst1, 1 ); /* 16425 */
|
||||
b0 = vec_splat( vConst1, 2 ); /* 3176 */
|
||||
r1 = vec_splat( vConst1, 3 ); /* -4818 */
|
||||
g1 = vec_splat( vConst1, 4 ); /* -9527 */
|
||||
b1 = vec_splat( vConst1, 5 ); /* 14345 */
|
||||
r2 = vec_splat( vConst2, 0 ); /* 14345 */
|
||||
g2 = vec_splat( vConst2, 1 ); /*-12045 */
|
||||
b2 = vec_splat( vConst2, 2 ); /* -2300 */
|
||||
c16 = vec_splat( vConst2, 3 ); /* 16 */
|
||||
c128 = vec_splat( vConst2, 4 ); /* 128 */
|
||||
c0 = static_cast<vector signed short> (0); /* 0 */
|
||||
z0 = static_cast<vector unsigned char> (0); /* 0 */
|
||||
|
||||
for ( i = 0; i < (RGBA_size/sizeof(vector unsigned char)); i+=3 ) {
|
||||
|
||||
/* Load the 3 RGB input vectors and seperate into red,
|
||||
green and blue from the interleaved format. */
|
||||
tc0 = vec_perm( RGBA_ptr[i], RGBA_ptr[i+1], vPerm1 ); /* R0..R7 G0..G7 */
|
||||
tc1 = vec_perm( RGBA_ptr[i], RGBA_ptr[i+1], vPerm2 ); /* B0..B7 */
|
||||
tc2 = vec_perm( RGBA_ptr[i+1], RGBA_ptr[i+2], vPerm3 ); /* R8..R15 G8..G15 */
|
||||
tc3 = vec_perm( RGBA_ptr[i+1], RGBA_ptr[i+2], vPerm4 ); /* B8..B15 */
|
||||
|
||||
/* Unpack to 16 bit arithmatic for converstion. */
|
||||
tr0 = static_cast<vector signed short>(vec_mergeh( z0, tc0 )); /* tr0 = R0 .. R7 */
|
||||
tg0 = static_cast<vector signed short>(vec_mergel( z0, tc0 )); /* tg0 = G0 .. G7 */
|
||||
tb0 = static_cast<vector signed short>(vec_mergeh( z0, tc1 )); /* tb0 = B0 .. B7 */
|
||||
tr1 = static_cast<vector signed short>(vec_mergeh( z0, tc2 )); /* tr0 = R8 .. R15 */
|
||||
tg1 = static_cast<vector signed short>(vec_mergel( z0, tc2 )); /* tg0 = G8 .. G15 */
|
||||
tb1 = static_cast<vector signed short>(vec_mergeh( z0, tc3 )); /* tb0 = B8 .. B15 */
|
||||
|
||||
/* Convert the first three input vectors. Note that
|
||||
only the top 17 bits of the 32 bit product are
|
||||
stored. This is the same as doing the divide by 32768. */
|
||||
|
||||
t0 = vec_mradds( tr0, r0, c0 ); /* (R0 .. R7) * 8432 */
|
||||
t1 = vec_mradds( tr0, r1, c0 ); /* (R0 .. R7) * -4818 */
|
||||
t2 = vec_mradds( tr0, r2, c0 ); /* (R0 .. R7) * 14345 */
|
||||
|
||||
t0 = vec_mradds( tg0, g0, t0 ); /* += (G0 .. G7) * 16425 */
|
||||
t1 = vec_mradds( tg0, g1, t1 ); /* += (G0 .. G7) * -9527 */
|
||||
t2 = vec_mradds( tg0, g2, t2 ); /* += (G0 .. G7) * -12045 */
|
||||
|
||||
t0 = vec_mradds( tb0, b0, t0 ); /* += (B0 .. B7) * 3176 */
|
||||
t1 = vec_mradds( tb0, b1, t1 ); /* += (B0 .. B7) * 14345 */
|
||||
t2 = vec_mradds( tb0, b2, t2 ); /* += (B0 .. B7) * -2300 */
|
||||
|
||||
/* Convert the next three input vectors. */
|
||||
t3 = vec_mradds( tr1, r0, c0 ); /* (R8 .. R15) * 8432 */
|
||||
t4 = vec_mradds( tr1, r1, c0 ); /* (R8 .. R15) * -4818 */
|
||||
t5 = vec_mradds( tr1, r2, c0 ); /* (R8 .. R15) * 14345 */
|
||||
|
||||
t3 = vec_mradds( tg1, g0, t3 ); /* += (G8 .. G15) * 16425 */
|
||||
t4 = vec_mradds( tg1, g1, t4 ); /* += (G8 .. G15) * -9527 */
|
||||
t5 = vec_mradds( tg1, g2, t5 ); /* += (G8 .. G15) * -12045 */
|
||||
|
||||
t3 = vec_mradds( tb1, b0, t3 ); /* += (B8 .. B15) * 3176 */
|
||||
t4 = vec_mradds( tb1, b1, t4 ); /* += (B8 .. B15) * 14345 */
|
||||
t5 = vec_mradds( tb1, b2, t5 ); /* += (B8 .. B15) * -2300 */
|
||||
|
||||
/* Add the constants. */
|
||||
t0 = vec_adds( t0, c16 );
|
||||
t3 = vec_adds( t3, c16 );
|
||||
t1 = vec_adds( t1, c128 );
|
||||
t4 = vec_adds( t4, c128 );
|
||||
t2 = vec_adds( t2, c128 );
|
||||
t5 = vec_adds( t5, c128 );
|
||||
|
||||
/* Pack the results, and store them. */
|
||||
YCC_ptr[i] = vec_packsu( t0, t3 ); /* Y0 .. Y15 */
|
||||
YCC_ptr[i+1] = vec_packsu( t1, t4 ); /* Cb0 .. Cb15 */
|
||||
YCC_ptr[i+2] = vec_packsu( t2, t5 ); /* Cr0 .. Cr15 */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BGR_to_YCbCr_altivec(const unsigned char *bgrdata, size_t BGR_size,
|
||||
unsigned char *pixels)
|
||||
{
|
||||
vector signed short r0, r1, r2, g0, g1, g2, b0, b1, b2, c0, c16, c128;
|
||||
vector unsigned char z0, tc0, tc1, tc2, tc3;
|
||||
vector signed short tr0, tr1, tg0, tg1, tb0, tb1;
|
||||
vector signed short t0, t1, t2, t3, t4, t5;
|
||||
unsigned int i;
|
||||
|
||||
const vector unsigned char *BGR_ptr = reinterpret_cast<const vector unsigned char*>( bgrdata);
|
||||
vector unsigned char *YCC_ptr = reinterpret_cast<vector unsigned char*>( pixels);
|
||||
|
||||
/* Permutation vector is used to extract the interleaved RGB. */
|
||||
vector unsigned char vPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 3, 6, 9, 12, 15, 18, 21, /* R0..R7 */
|
||||
1, 4, 7, 10, 13, 16, 19, 22 /* G0..G7 */);
|
||||
vector unsigned char vPerm2 =
|
||||
static_cast<vector unsigned char>( 2, 5, 8, 11, 14, 17, 20, 23, /* B0..B7 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
vector unsigned char vPerm3 =
|
||||
static_cast<vector unsigned char>( 8, 11, 14, 17, 20, 23, 26, 29, /* R8..R15 */
|
||||
9, 12, 15, 18, 21, 24, 27, 30 /* G8..G15 */);
|
||||
vector unsigned char vPerm4 =
|
||||
static_cast<vector unsigned char>(10, 13, 16, 19, 22, 25, 28, 31, /* B8..B15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
|
||||
/* Load the equation constants. */
|
||||
vector signed short vConst1 =
|
||||
static_cast<vector signed short>( 8432, 16425, 3176,
|
||||
-4818, -9527, 14345,
|
||||
0, 0 );
|
||||
|
||||
vector signed short vConst2 =
|
||||
static_cast<vector signed short>( 14345, -12045, -2300,
|
||||
16, 128, 0, 0, 0 );
|
||||
|
||||
r0 = vec_splat( vConst1, 0 ); /* 8432 */
|
||||
g0 = vec_splat( vConst1, 1 ); /* 16425 */
|
||||
b0 = vec_splat( vConst1, 2 ); /* 3176 */
|
||||
r1 = vec_splat( vConst1, 3 ); /* -4818 */
|
||||
g1 = vec_splat( vConst1, 4 ); /* -9527 */
|
||||
b1 = vec_splat( vConst1, 5 ); /* 14345 */
|
||||
r2 = vec_splat( vConst2, 0 ); /* 14345 */
|
||||
g2 = vec_splat( vConst2, 1 ); /*-12045 */
|
||||
b2 = vec_splat( vConst2, 2 ); /* -2300 */
|
||||
c16 = vec_splat( vConst2, 3 ); /* 16 */
|
||||
c128 = vec_splat( vConst2, 4 ); /* 128 */
|
||||
c0 = static_cast<vector signed short> (0); /* 0 */
|
||||
z0 = static_cast<vector unsigned char> (0); /* 0 */
|
||||
|
||||
for ( i = 0; i < (BGR_size/sizeof(vector unsigned char)); i+=3 ) {
|
||||
|
||||
/* Load the 3 RGB input vectors and seperate into red,
|
||||
green and blue from the interleaved format. */
|
||||
tc0 = vec_perm( BGR_ptr[i], BGR_ptr[i+1], vPerm1 ); /* R0..R7 G0..G7 */
|
||||
tc1 = vec_perm( BGR_ptr[i], BGR_ptr[i+1], vPerm2 ); /* B0..B7 */
|
||||
tc2 = vec_perm( BGR_ptr[i+1], BGR_ptr[i+2], vPerm3 ); /* R8..R15 G8..G15 */
|
||||
tc3 = vec_perm( BGR_ptr[i+1], BGR_ptr[i+2], vPerm4 ); /* B8..B15 */
|
||||
|
||||
/* Unpack to 16 bit arithmatic for converstion. */
|
||||
tr0 = static_cast<vector signed short>(vec_mergeh( z0, tc0 )); /* tr0 = R0 .. R7 */
|
||||
tg0 = static_cast<vector signed short>(vec_mergel( z0, tc0 )); /* tg0 = G0 .. G7 */
|
||||
tb0 = static_cast<vector signed short>(vec_mergeh( z0, tc1 )); /* tb0 = B0 .. B7 */
|
||||
tr1 = static_cast<vector signed short>(vec_mergeh( z0, tc2 )); /* tr0 = R8 .. R15 */
|
||||
tg1 = static_cast<vector signed short>(vec_mergel( z0, tc2 )); /* tg0 = G8 .. G15 */
|
||||
tb1 = static_cast<vector signed short>(vec_mergeh( z0, tc3 )); /* tb0 = B8 .. B15 */
|
||||
|
||||
/* Convert the first three input vectors. Note that
|
||||
only the top 17 bits of the 32 bit product are
|
||||
stored. This is the same as doing the divide by 32768. */
|
||||
|
||||
t0 = vec_mradds( tr0, r0, c0 ); /* (R0 .. R7) * 8432 */
|
||||
t1 = vec_mradds( tr0, r1, c0 ); /* (R0 .. R7) * -4818 */
|
||||
t2 = vec_mradds( tr0, r2, c0 ); /* (R0 .. R7) * 14345 */
|
||||
|
||||
t0 = vec_mradds( tg0, g0, t0 ); /* += (G0 .. G7) * 16425 */
|
||||
t1 = vec_mradds( tg0, g1, t1 ); /* += (G0 .. G7) * -9527 */
|
||||
t2 = vec_mradds( tg0, g2, t2 ); /* += (G0 .. G7) * -12045 */
|
||||
|
||||
t0 = vec_mradds( tb0, b0, t0 ); /* += (B0 .. B7) * 3176 */
|
||||
t1 = vec_mradds( tb0, b1, t1 ); /* += (B0 .. B7) * 14345 */
|
||||
t2 = vec_mradds( tb0, b2, t2 ); /* += (B0 .. B7) * -2300 */
|
||||
|
||||
/* Convert the next three input vectors. */
|
||||
t3 = vec_mradds( tr1, r0, c0 ); /* (R8 .. R15) * 8432 */
|
||||
t4 = vec_mradds( tr1, r1, c0 ); /* (R8 .. R15) * -4818 */
|
||||
t5 = vec_mradds( tr1, r2, c0 ); /* (R8 .. R15) * 14345 */
|
||||
|
||||
t3 = vec_mradds( tg1, g0, t3 ); /* += (G8 .. G15) * 16425 */
|
||||
t4 = vec_mradds( tg1, g1, t4 ); /* += (G8 .. G15) * -9527 */
|
||||
t5 = vec_mradds( tg1, g2, t5 ); /* += (G8 .. G15) * -12045 */
|
||||
|
||||
t3 = vec_mradds( tb1, b0, t3 ); /* += (B8 .. B15) * 3176 */
|
||||
t4 = vec_mradds( tb1, b1, t4 ); /* += (B8 .. B15) * 14345 */
|
||||
t5 = vec_mradds( tb1, b2, t5 ); /* += (B8 .. B15) * -2300 */
|
||||
|
||||
/* Add the constants. */
|
||||
t0 = vec_adds( t0, c16 );
|
||||
t3 = vec_adds( t3, c16 );
|
||||
t1 = vec_adds( t1, c128 );
|
||||
t4 = vec_adds( t4, c128 );
|
||||
t2 = vec_adds( t2, c128 );
|
||||
t5 = vec_adds( t5, c128 );
|
||||
|
||||
/* Pack the results, and store them. */
|
||||
YCC_ptr[i] = vec_packsu( t0, t3 ); /* Y0 .. Y15 */
|
||||
YCC_ptr[i+1] = vec_packsu( t1, t4 ); /* Cb0 .. Cb15 */
|
||||
YCC_ptr[i+2] = vec_packsu( t2, t5 ); /* Cr0 .. Cr15 */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BGRA_to_YCbCr_altivec(const unsigned char *bgradata, size_t BGRA_size,
|
||||
unsigned char *pixels)
|
||||
{
|
||||
vector signed short r0, r1, r2, g0, g1, g2, b0, b1, b2, c0, c16, c128;
|
||||
vector unsigned char z0, tc0, tc1, tc2, tc3;
|
||||
vector signed short tr0, tr1, tg0, tg1, tb0, tb1;
|
||||
vector signed short t0, t1, t2, t3, t4, t5;
|
||||
vector signed short u1, u2, uAvg, v1, v2, vAvg, out1, out2, out3, out4, uv1, uv2;
|
||||
unsigned int i;
|
||||
|
||||
const vector unsigned char *BGRA_ptr = reinterpret_cast<const vector unsigned char*>( bgradata);
|
||||
vector unsigned char *UYVY_ptr = reinterpret_cast<vector unsigned char*>( pixels);
|
||||
|
||||
/* Permutation vector is used to extract the interleaved BGRA. */
|
||||
vector unsigned char vPerm1 =
|
||||
static_cast<vector unsigned char>( 3, 7, 11, 15, 19, 23, 27, 31, // B0..B7
|
||||
2, 6, 10, 14, 18, 22, 26, 30 /* G0..G7 */);
|
||||
vector unsigned char vPerm2 =
|
||||
static_cast<vector unsigned char>( 1, 5, 9, 13, 17, 21, 25, 29, /* R0..R7 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0 /* dont care */);
|
||||
|
||||
/* Load the equation constants. */
|
||||
vector signed short vConst1 =
|
||||
static_cast<vector signed short>( 8432, 16425, 3176,
|
||||
-4818, -9527, 14345,
|
||||
0, 0 );
|
||||
vector signed short vConst2 =
|
||||
static_cast<vector signed short>( 14345, -12045, -2300,
|
||||
16, 128, 0, 0, 0 );
|
||||
|
||||
vector unsigned char avgPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 1, 4, 5, 8, 9, 12, 13,
|
||||
16, 17, 20, 21, 24, 25, 28, 29 );
|
||||
vector unsigned char avgPerm2 =
|
||||
static_cast<vector unsigned char>( 2, 3, 6, 7, 10, 11, 14, 15,
|
||||
18, 19, 22, 23, 26, 27, 30, 31 );
|
||||
vector unsigned char Perm1 =
|
||||
static_cast<vector unsigned char>( 0, 1, 16, 17, 2, 3, 18, 19,
|
||||
4, 5, 20, 21, 6, 7, 22, 23 );
|
||||
vector unsigned char Perm2 =
|
||||
static_cast<vector unsigned char>( 8, 9, 24, 25, 10, 11, 26, 27,
|
||||
12, 13, 28, 29, 14, 15, 30, 31 );
|
||||
|
||||
r0 = vec_splat( vConst1, 2 ); /* 8432 */
|
||||
g0 = vec_splat( vConst1, 1 ); /* 16425 */
|
||||
b0 = vec_splat( vConst1, 0 ); /* 3176 */
|
||||
r1 = vec_splat( vConst1, 5 ); /* -4818 */
|
||||
g1 = vec_splat( vConst1, 4 ); /* -9527 */
|
||||
b1 = vec_splat( vConst1, 3 ); /* 14345 */
|
||||
r2 = vec_splat( vConst2, 2 ); /* 14345 */
|
||||
g2 = vec_splat( vConst2, 1 ); /*-12045 */
|
||||
b2 = vec_splat( vConst2, 0 ); /* -2300 */
|
||||
c16 = vec_splat( vConst2, 3 ); /* 16 */
|
||||
c128 = vec_splat( vConst2, 4 ); /* 128 */
|
||||
c0 = static_cast<vector signed short> (0); /* 0 */
|
||||
z0 = static_cast<vector unsigned char> (0); /* 0 */
|
||||
|
||||
for ( i = 0; i < (BGRA_size/sizeof(vector unsigned char)); i++ ) {
|
||||
|
||||
/* Load the 4 BGRA input vectors and seperate into red,
|
||||
green and blue from the interleaved format. */
|
||||
const vector unsigned char *vec1 = BGRA_ptr++;
|
||||
const vector unsigned char *vec2 = BGRA_ptr++;
|
||||
const vector unsigned char *vec3 = BGRA_ptr++;
|
||||
const vector unsigned char *vec4 = BGRA_ptr++;
|
||||
|
||||
tc0 = vec_perm( *vec1, *vec2, vPerm1 ); // B0..B7 G0..G7
|
||||
tc1 = vec_perm( *vec1, *vec2, vPerm2 ); // R0..R7
|
||||
tc2 = vec_perm( *vec3, *vec4, vPerm1 ); // B8..B15 G8..G15
|
||||
tc3 = vec_perm( *vec3, *vec4, vPerm2 ); // R8..R15
|
||||
|
||||
/* Unpack to 16 bit arithmatic for conversion. */
|
||||
tr0 = static_cast<vector signed short>(vec_mergeh( z0, tc0 )); /* tr0 = R0 .. R7 */
|
||||
tg0 = static_cast<vector signed short>(vec_mergel( z0, tc0 )); /* tg0 = G0 .. G7 */
|
||||
tb0 = static_cast<vector signed short>(vec_mergeh( z0, tc1 )); /* tb0 = B0 .. B7 */
|
||||
tr1 = static_cast<vector signed short>(vec_mergeh( z0, tc2 )); /* tr0 = R8 .. R15 */
|
||||
tg1 = static_cast<vector signed short>(vec_mergel( z0, tc2 )); /* tg0 = G8 .. G15 */
|
||||
tb1 = static_cast<vector signed short>(vec_mergeh( z0, tc3 )); /* tb0 = B8 .. B15 */
|
||||
|
||||
/* Convert the first three input vectors. Note that
|
||||
only the top 17 bits of the 32 bit product are
|
||||
stored. This is the same as doing the divide by 32768. */
|
||||
|
||||
t0 = vec_mradds( tr0, r0, c0 ); /* (R0 .. R7) * 8432 */
|
||||
t1 = vec_mradds( tr0, r1, c0 ); /* (R0 .. R7) * -4818 */
|
||||
t2 = vec_mradds( tr0, r2, c0 ); /* (R0 .. R7) * 14345 */
|
||||
|
||||
t0 = vec_mradds( tg0, g0, t0 ); /* += (G0 .. G7) * 16425 */
|
||||
t1 = vec_mradds( tg0, g1, t1 ); /* += (G0 .. G7) * -9527 */
|
||||
t2 = vec_mradds( tg0, g2, t2 ); /* += (G0 .. G7) * -12045 */
|
||||
|
||||
t0 = vec_mradds( tb0, b0, t0 ); /* += (B0 .. B7) * 3176 */
|
||||
t1 = vec_mradds( tb0, b1, t1 ); /* += (B0 .. B7) * 14345 */
|
||||
t2 = vec_mradds( tb0, b2, t2 ); /* += (B0 .. B7) * -2300 */
|
||||
|
||||
/* Convert the next three input vectors. */
|
||||
t3 = vec_mradds( tr1, r0, c0 ); /* (R8 .. R15) * 8432 */
|
||||
t4 = vec_mradds( tr1, r1, c0 ); /* (R8 .. R15) * -4818 */
|
||||
t5 = vec_mradds( tr1, r2, c0 ); /* (R8 .. R15) * 14345 */
|
||||
|
||||
t3 = vec_mradds( tg1, g0, t3 ); /* += (G8 .. G15) * 16425 */
|
||||
t4 = vec_mradds( tg1, g1, t4 ); /* += (G8 .. G15) * -9527 */
|
||||
t5 = vec_mradds( tg1, g2, t5 ); /* += (G8 .. G15) * -12045 */
|
||||
|
||||
t3 = vec_mradds( tb1, b0, t3 ); /* += (B8 .. B15) * 3176 */
|
||||
t4 = vec_mradds( tb1, b1, t4 ); /* += (B8 .. B15) * 14345 */
|
||||
t5 = vec_mradds( tb1, b2, t5 ); /* += (B8 .. B15) * -2300 */
|
||||
|
||||
/* Add the constants. */
|
||||
t0 = vec_adds( t0, c16 );
|
||||
t3 = vec_adds( t3, c16 );
|
||||
t1 = vec_adds( t1, c128 );
|
||||
t4 = vec_adds( t4, c128 );
|
||||
t2 = vec_adds( t2, c128 );
|
||||
t5 = vec_adds( t5, c128 );
|
||||
|
||||
u1 = vec_perm( t1, t4, avgPerm1 ); // rearrange U's for averaging
|
||||
u2 = vec_perm( t1, t4, avgPerm2 );
|
||||
uAvg = vec_avg( u1, u2 );
|
||||
v1 = vec_perm( t2, t5, avgPerm1 ); // rearrange V's for averaging
|
||||
v2 = vec_perm( t2, t5, avgPerm2 );
|
||||
vAvg = vec_avg( v1, v2 );
|
||||
|
||||
uv1 = vec_perm( uAvg, vAvg, Perm1 );
|
||||
uv2 = vec_perm( uAvg, vAvg, Perm2 );
|
||||
out1 = vec_perm( uv1, t0, Perm1 );
|
||||
out2 = vec_perm( uv1, t0, Perm2 );
|
||||
out3 = vec_perm( uv2, t3, Perm1 );
|
||||
out4 = vec_perm( uv2, t3, Perm2 );
|
||||
|
||||
*UYVY_ptr = vec_packsu( out1, out2 ); // pack down to char's
|
||||
UYVY_ptr++;
|
||||
*UYVY_ptr = vec_packsu( out3, out4 );
|
||||
UYVY_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
void YV12_to_YUV422_altivec(const short*Y, const short*U, const short*V,
|
||||
unsigned char *data, int xsize, int ysize)
|
||||
{
|
||||
// from geowar@apple.com, 3/15/2005
|
||||
// #1. Don't use the pointers. Use vec_ld with an index that you increment (by 16) instead.
|
||||
vector unsigned char *pixels1=reinterpret_cast<vector unsigned char *>(data);
|
||||
vector unsigned char *pixels2=reinterpret_cast<vector unsigned char *>(data+(xsize*2));
|
||||
const vector unsigned short *py1 = reinterpret_cast<const vector unsigned short *>(Y);
|
||||
const vector unsigned short *py2 = reinterpret_cast<const vector unsigned short *>(Y + xsize );
|
||||
const vector unsigned short *pu = reinterpret_cast<const vector unsigned short *>(U);
|
||||
const vector unsigned short *pv = reinterpret_cast<const vector unsigned short *>(V);
|
||||
vector unsigned short uvAdd = static_cast<vector unsigned short>( 128, 128, 128, 128,
|
||||
128, 128, 128, 128 );
|
||||
vector unsigned short yShift = static_cast<vector unsigned short>( 7, 7, 7, 7, 7, 7, 7, 7 );
|
||||
vector unsigned short uvShift = static_cast<vector unsigned short>( 8, 8, 8, 8, 8, 8, 8, 8 );
|
||||
vector unsigned short tempU, tempV, doneU, doneV, tempY1, tempY2, tempY3, tempY4,
|
||||
uv1, uv2, out1, out2, out3, out4, out5, out6, out7, out8;
|
||||
vector unsigned char Perm1 =
|
||||
static_cast<vector unsigned char>( 0, 1, 16, 17, 2, 3, 18, 19,
|
||||
4, 5, 20, 21, 6, 7, 22, 23 );
|
||||
vector unsigned char Perm2 =
|
||||
static_cast<vector unsigned char>( 8, 9, 24, 25, 10, 11, 26, 27,
|
||||
12, 13, 28, 29, 14, 15, 30, 31 );
|
||||
int row=ysize>>1;
|
||||
int cols=xsize>>4;
|
||||
#if 0
|
||||
# ifndef PPC970
|
||||
UInt32 prefetchSize = GetPrefetchConstant( 16, 1, 256 );
|
||||
vec_dst( pu, prefetchSize, 0 );
|
||||
vec_dst( pv, prefetchSize, 0 );
|
||||
vec_dst( py1, prefetchSize, 0 );
|
||||
vec_dst( py2, prefetchSize, 0 );
|
||||
# endif
|
||||
#endif
|
||||
while(row--){
|
||||
int col=cols;
|
||||
while(col--){
|
||||
#if 0
|
||||
# ifndef PPC970
|
||||
vec_dst( );
|
||||
# endif
|
||||
#endif
|
||||
tempU = vec_sra( (*pu++), uvShift );
|
||||
tempV = vec_sra( (*pv++), uvShift );
|
||||
doneU = vec_add( tempU, uvAdd );
|
||||
doneV = vec_add( tempV, uvAdd );
|
||||
|
||||
uv1 = vec_perm( doneU, doneV, Perm1 ); // uvuvuvuv uvuvuvuv
|
||||
uv2 = vec_perm( doneU, doneV, Perm2 );
|
||||
|
||||
tempY1 = vec_sra( (*py1++), yShift );
|
||||
tempY2 = vec_sra( (*py2++), yShift );
|
||||
|
||||
out1 = vec_perm( uv1, tempY1, Perm1 ); //fill Y's, U's & V's
|
||||
out2 = vec_perm( uv1, tempY1, Perm2 );
|
||||
out3 = vec_perm( uv1, tempY2, Perm1 ); //fill 2nd Y's, U's & V's
|
||||
out4 = vec_perm( uv1, tempY2, Perm2 );
|
||||
|
||||
*pixels1 = vec_packsu( out1, out2 );
|
||||
*pixels2 = vec_packsu( out3, out4 );
|
||||
pixels1++; pixels2++;
|
||||
|
||||
tempY3 = vec_sra( (*py1++), yShift ); // load second set of Y's
|
||||
tempY4 = vec_sra( (*py2++), yShift );
|
||||
|
||||
out5 = vec_perm( uv2, tempY3, Perm1 );
|
||||
out6 = vec_perm( uv2, tempY3, Perm2 );
|
||||
out7 = vec_perm( uv2, tempY4, Perm1 );
|
||||
out8 = vec_perm( uv2, tempY4, Perm2 );
|
||||
|
||||
*pixels1 = vec_packsu( out5, out6 );
|
||||
*pixels2 = vec_packsu( out7, out8 );
|
||||
pixels1++; pixels2++;
|
||||
}
|
||||
pixels1+=(xsize*2)>>4; pixels2+=(xsize*2)>>4;
|
||||
py1+=xsize>>3; py2+=xsize>>3;
|
||||
}
|
||||
}
|
||||
|
||||
void YUV422_to_YV12_altivec(short*pY, short*pY2, short*pU, short*pV,
|
||||
const unsigned char *gem_image, int xsize, int ysize)
|
||||
{
|
||||
// UYVY UYVY UYVY UYVY
|
||||
const vector unsigned char *pixels1=reinterpret_cast<const vector unsigned char *>(gem_image);
|
||||
const vector unsigned char *pixels2=reinterpret_cast<const vector unsigned char *>(gem_image+(xsize*2));
|
||||
// PDP packet to be filled:
|
||||
// first Y plane
|
||||
vector signed short *py1 = reinterpret_cast<vector signed short *>(pY);
|
||||
// 2nd Y pixel
|
||||
vector signed short *py2 = reinterpret_cast<vector signed short *>(pY2);
|
||||
// U plane
|
||||
vector signed short *pCr = reinterpret_cast<vector signed short *>(pU);
|
||||
// V plane
|
||||
vector signed short *pCb = reinterpret_cast<vector signed short *>(pV);
|
||||
vector signed short uvSub = static_cast<vector signed short>( 128, 128, 128, 128,
|
||||
128, 128, 128, 128 );
|
||||
vector unsigned short yShift = static_cast<vector unsigned short>( 7, 7, 7, 7, 7, 7, 7, 7 );
|
||||
vector unsigned short uvShift = static_cast<vector unsigned short>( 8, 8, 8, 8, 8, 8, 8, 8 );
|
||||
|
||||
vector signed short tempY1, tempY2, tempY3, tempY4,
|
||||
tempUV1, tempUV2, tempUV3, tempUV4, tempUV5, tempUV6;
|
||||
|
||||
vector unsigned char uvPerm = static_cast<vector unsigned char>( 16, 0, 17, 4, 18, 8, 19, 12, // u0..u3
|
||||
20, 2, 21, 6, 22, 10, 23, 14 ); // v0..v3
|
||||
|
||||
vector unsigned char uPerm = static_cast<vector unsigned char>( 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
16,17,18,19,20,21,22,23);
|
||||
vector unsigned char vPerm = static_cast<vector unsigned char>( 8, 9, 10,11,12,13,14,15,
|
||||
24,25,26,27,28,29,30,31);
|
||||
|
||||
vector unsigned char yPerm = static_cast<vector unsigned char>( 16, 1, 17, 3, 18, 5, 19, 7, // y0..y3
|
||||
20, 9, 21, 11, 23, 13, 25, 15);// y4..y7
|
||||
vector unsigned char zeroVec = static_cast<vector unsigned char>(0);
|
||||
|
||||
int row=ysize>>1;
|
||||
int cols=xsize>>4;
|
||||
#if 0
|
||||
# ifndef PPC970
|
||||
UInt32 prefetchSize = GetPrefetchConstant( 16, 1, 256 );
|
||||
vec_dst( pu, prefetchSize, 0 );
|
||||
vec_dst( pv, prefetchSize, 0 );
|
||||
vec_dst( py1, prefetchSize, 0 );
|
||||
vec_dst( py2, prefetchSize, 0 );
|
||||
# endif
|
||||
#endif
|
||||
while(row--){
|
||||
int col=cols;
|
||||
while(col--){
|
||||
#if 0
|
||||
# ifndef PPC970
|
||||
vec_dst( );
|
||||
# endif
|
||||
#endif
|
||||
tempUV1 = static_cast<vector signed short>(vec_perm( *pixels1, zeroVec, uvPerm));
|
||||
tempY1 = static_cast<vector signed short>(vec_perm( *pixels1, zeroVec, yPerm));
|
||||
tempY2 = static_cast<vector signed short>(vec_perm( *pixels2, zeroVec, yPerm));
|
||||
pixels1++;pixels2++;
|
||||
|
||||
tempUV2 = static_cast<vector signed short>(vec_perm( *pixels1, zeroVec, uvPerm));
|
||||
tempY3 = static_cast<vector signed short>(vec_perm( *pixels1, zeroVec, yPerm));
|
||||
tempY4 = static_cast<vector signed short>(vec_perm( *pixels2, zeroVec, yPerm));
|
||||
pixels1++;pixels2++;
|
||||
|
||||
tempUV3 = vec_sub( tempUV1, uvSub );
|
||||
tempUV4 = vec_sub( tempUV2, uvSub );
|
||||
tempUV5 = vec_sl( tempUV3, uvShift );
|
||||
tempUV6 = vec_sl( tempUV4, uvShift );
|
||||
|
||||
*pCb = vec_perm( tempUV5, tempUV6, uPerm );
|
||||
*pCr = vec_perm( tempUV5, tempUV6, vPerm );
|
||||
pCr++; pCb++;
|
||||
|
||||
*py1++ = vec_sl( tempY1, yShift);
|
||||
*py2++ = vec_sl( tempY2, yShift);
|
||||
*py1++ = vec_sl( tempY3, yShift);
|
||||
*py2++ = vec_sl( tempY4, yShift);
|
||||
}
|
||||
|
||||
py1+=(xsize>>3); py2+=(xsize>>3);
|
||||
pixels1+=(xsize*2)>>4; pixels2+=(xsize*2)>>4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NO_VECTORINT_TO_VECTORUNSIGNEDINT
|
||||
# warning disabling AltiVec for older gcc: please fix me
|
||||
#else
|
||||
void YUV422_to_BGRA_altivec(const unsigned char *yuvdata,
|
||||
size_t pixelnum, unsigned char *output)
|
||||
{
|
||||
const vector unsigned char *UYVY_ptr=reinterpret_cast<const vector unsigned char *>(yuvdata);
|
||||
vector unsigned char *BGRA_ptr=reinterpret_cast<vector unsigned char *>(output);
|
||||
|
||||
vector unsigned int vShift;
|
||||
vector signed short tempU, tempV, tempY, tempUV, out1, out2, out3, out4;
|
||||
|
||||
vector signed short v16, v128, a255, szero, one;
|
||||
vector unsigned char zero;
|
||||
vector signed short t0, t1, t2, tempGB1, tempGB2, tempRA1, tempRA2;
|
||||
vector signed short vU_G, vV_G, vU_B, vU_R, y0, hiImage, loImage;
|
||||
vector unsigned int uv_rEven, uv_rOdd, uv_rHi, uv_rLo,
|
||||
uv_gUEven, uv_gVEven, uv_gUOdd, uv_gVOdd, uv_gHi, uv_gLo,
|
||||
uv_bEven, uv_bOdd;
|
||||
vector signed int tempUhi, tempUlo, tempVhi, tempVlo;
|
||||
vector signed int yEven, yOdd;
|
||||
|
||||
vector unsigned int t0Even, t0Odd, t1Even, t1Odd, t2Even, t2Odd;
|
||||
|
||||
/* Load the equation constants. */
|
||||
vector signed short vConst =
|
||||
static_cast<vector signed short>(298, 519, 409, 16, 128, 255, -100, -210 );
|
||||
|
||||
vector unsigned char vPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 1, 16, 17, 8, 9, 24, 25,
|
||||
2, 3, 18, 19, 10, 11, 26, 27 );
|
||||
vector unsigned char vPerm2 =
|
||||
static_cast<vector unsigned char>( 4, 5, 20, 21, 12, 13, 28, 29,
|
||||
6, 7, 22, 23, 14, 15, 30, 31 );
|
||||
|
||||
vector unsigned char vPermY =
|
||||
static_cast<vector unsigned char>( 2, 3, 6, 7, 10, 11, 14, 15,
|
||||
18, 19, 22, 23, 26, 27, 30, 31 );
|
||||
vector unsigned char vPermU =
|
||||
static_cast<vector unsigned char>( 0, 1, 16, 17, 4, 5, 20, 21,
|
||||
8, 9, 24, 25, 12, 13, 28, 29 );
|
||||
vector unsigned char vPermV =
|
||||
static_cast<vector unsigned char>( 2, 3, 18, 19, 6, 7, 22, 23,
|
||||
10, 11, 26, 27, 14, 15, 30, 31 );
|
||||
vector unsigned char vOutPerm1 =
|
||||
static_cast<vector unsigned char>( 0, 1, 2, 3, 16, 17, 18, 19,
|
||||
4, 5, 6, 7, 20, 21, 22, 23 );
|
||||
vector unsigned char vOutPerm2 =
|
||||
static_cast<vector unsigned char>( 8, 9, 10, 11, 24, 25, 26, 27,
|
||||
12, 13, 14, 15, 28, 29, 30, 31 );
|
||||
vector unsigned char uvPerm =
|
||||
static_cast<vector unsigned char>( 0, 1, 4, 5, 8, 9, 12, 13,
|
||||
16, 17, 20, 21, 24, 25, 28, 29 );
|
||||
|
||||
zero = vec_splat_u8(0);
|
||||
szero = vec_splat_s16(0);
|
||||
one = vec_splat_s16(1);
|
||||
vShift = vec_splat_u32(8);
|
||||
a255 = vec_splat( vConst, 5 ); // alpha channel = 255
|
||||
vU_G = vec_splat( vConst, 6 ); // -100
|
||||
vV_G = vec_splat( vConst, 7 ); // -210
|
||||
vU_B = vec_splat( vConst, 1 ); // 519
|
||||
vU_R = vec_splat( vConst, 2 ); // 409
|
||||
y0 = vec_splat( vConst, 0 ); // 298
|
||||
v16 = vec_splat( vConst, 3 ); // 16
|
||||
v128 = vec_splat( vConst, 4 ); // 128
|
||||
|
||||
for ( unsigned int i = 0; i < (pixelnum/sizeof(vector unsigned char)); i++ ) {
|
||||
|
||||
// Load UYUV input vector
|
||||
const vector unsigned char *vec1 = UYVY_ptr++;
|
||||
|
||||
//expand the UInt8's to short's
|
||||
hiImage = static_cast<vector signed short>(vec_mergeh( zero, *vec1 ));
|
||||
loImage = static_cast<vector signed short>(vec_mergel( zero, *vec1 ));
|
||||
|
||||
tempUV = static_cast<vector signed short>(vec_perm( hiImage, loImage, uvPerm ));
|
||||
tempY = static_cast<vector signed short>(vec_perm( hiImage, loImage, vPermY ));
|
||||
|
||||
// subtract UV_OFFSET from UV's (should this be saturated?)
|
||||
tempUV = static_cast<vector signed short>(vec_sub( tempUV, v128 ));
|
||||
// subtract Y-OFFSET from Y's (should this be saturated?)
|
||||
tempY = static_cast<vector signed short>(vec_sub( tempY, v16 ));
|
||||
|
||||
// expand to UUUU UUUU and VVVV VVVV
|
||||
tempU = vec_perm(tempUV, tempUV, vPermU);
|
||||
tempV = vec_perm(tempUV, tempUV, vPermV);
|
||||
//below:
|
||||
//
|
||||
//error: cannot convert `vector int' to `vector unsigned int' in assignment
|
||||
tempUhi = vec_mule( tempU, one );
|
||||
// unsigned int = vec_mule( signed short, signed short )
|
||||
// should be
|
||||
// signed int = vec_mule( signed short, signed short )
|
||||
tempUlo = vec_mulo( tempU, one );
|
||||
tempVhi = vec_mule( tempV, one );
|
||||
tempVlo = vec_mulo( tempV, one );
|
||||
|
||||
// uv_r = YUV2RGB_12*u + YUV2RGB_13*v
|
||||
// uv_r = (-1)*u + 409*v (or "409*V - U")
|
||||
uv_rEven = vec_mule( tempV, vU_R );
|
||||
uv_rOdd = vec_mulo( tempV, vU_R );
|
||||
uv_rHi = vec_sub( uv_rEven, tempUhi );
|
||||
uv_rLo = vec_sub( uv_rOdd, tempUlo );
|
||||
|
||||
// uv_g = YUV2RGB_22*u + YUV2RGB_23*v
|
||||
// uv_g = -100*u + (-210)*v
|
||||
// multiply U by -100
|
||||
uv_gUEven = vec_mule( tempU, vU_G );
|
||||
uv_gUOdd = vec_mulo( tempU, vU_G );
|
||||
// multiply V by -210
|
||||
uv_gVEven = vec_mule( tempV, vV_G );
|
||||
uv_gVOdd = vec_mulo( tempV, vV_G );
|
||||
// add U & V products
|
||||
uv_gHi = vec_add( uv_gUEven, uv_gVEven );
|
||||
uv_gLo = vec_add( uv_gUOdd, uv_gVOdd );
|
||||
|
||||
// uv_b = YUV2RGB_32*u + YUV2RGB_33*v
|
||||
// uv_b = 519*u + 0*v
|
||||
uv_bEven = vec_mule( tempU, vU_B );
|
||||
uv_bOdd = vec_mulo( tempU, vU_B );
|
||||
|
||||
// y = YUV2RGB_11 * tempY
|
||||
// y = 298* (tempY - 16)
|
||||
yEven = vec_mule( tempY, y0 );
|
||||
yOdd = vec_mulo( tempY, y0 );
|
||||
|
||||
// add while int's
|
||||
t0Even = vec_add( yEven, uv_bEven );
|
||||
t0Odd = vec_add( yOdd, uv_bOdd );
|
||||
t1Even = vec_add( yEven, uv_gHi );
|
||||
t1Odd = vec_add( yOdd, uv_gLo );
|
||||
t2Even = vec_add( yEven, uv_rHi );
|
||||
t2Odd = vec_add( yOdd, uv_rLo );
|
||||
|
||||
// shift while int's
|
||||
t0Even = vec_sra( t0Even, vShift );
|
||||
t0Odd = vec_sra( t0Odd, vShift );
|
||||
t1Even = vec_sra( t1Even, vShift );
|
||||
t1Odd = vec_sra( t1Odd, vShift );
|
||||
t2Even = vec_sra( t2Even, vShift );
|
||||
t2Odd = vec_sra( t2Odd, vShift );
|
||||
|
||||
// pack down to shorts
|
||||
t0 = vec_packs( t0Even, t0Odd );
|
||||
t1 = vec_packs( t1Even, t1Odd );
|
||||
t2 = vec_packs( t2Even, t2Odd );
|
||||
|
||||
// Permute to GBGBGBGB GBGBGBGB + re-interleave even & odd
|
||||
tempGB1 = vec_perm( t1, t0, vPerm1 );
|
||||
tempGB2 = vec_perm( t1, t0, vPerm2 );
|
||||
// Permute to ARARARAR ARARARAR + re-interleave even & odd
|
||||
tempRA1 = vec_perm( a255, t2, vPerm1 );
|
||||
tempRA2 = vec_perm( a255, t2, vPerm2 );
|
||||
|
||||
// Permute to ARGB's
|
||||
out1 = vec_perm( tempRA1, tempGB1, vOutPerm1 );
|
||||
out2 = vec_perm( tempRA1, tempGB1, vOutPerm2 );
|
||||
out3 = vec_perm( tempRA2, tempGB2, vOutPerm1 );
|
||||
out4 = vec_perm( tempRA2, tempGB2, vOutPerm2 );
|
||||
|
||||
// pack down to char's
|
||||
*BGRA_ptr = vec_packsu( out1, out2 );
|
||||
BGRA_ptr++;
|
||||
*BGRA_ptr = vec_packsu( out3, out4 );
|
||||
BGRA_ptr++;
|
||||
}
|
||||
}
|
||||
#endif /* NO_VECTORINT_TO_VECTORUNSIGNEDINT */
|
||||
|
||||
#endif /* __VEC__ */
|
||||
423
Gem/src/Gem/PixConvertSSE2.cpp
Normal file
423
Gem/src/Gem/PixConvertSSE2.cpp
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
#ifdef __SSE2__
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file for SSE2-optimized color-conversion routines
|
||||
//
|
||||
// Copyright (c) 2006-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/* darned: it seems like i just cannot get SIMD-code right!
|
||||
* to my eye, there appear to me WAY too much shuffle's down there
|
||||
* if somebody would want to have a look i'd be grateful
|
||||
*/
|
||||
|
||||
|
||||
#if defined _MSC_VER
|
||||
/* data conversion with possible loss of data */
|
||||
# pragma warning( disable : 4309 )
|
||||
#endif
|
||||
|
||||
#include "PixConvert.h"
|
||||
#include "Gem/Image.h"
|
||||
|
||||
|
||||
#define RGB2YUV_14 0
|
||||
#define RGB2YUV_24 0
|
||||
#define RGB2YUV_34 0
|
||||
|
||||
|
||||
/* for post() */
|
||||
#include "m_pd.h"
|
||||
|
||||
/* just some debugging stuff ... */
|
||||
|
||||
#define PRINT_MASK "%03d "
|
||||
static void print_char(__m128i m){
|
||||
_mm_pause();
|
||||
unsigned char*s=(unsigned char*)&m;
|
||||
int i=0;
|
||||
for(i=0; i<(sizeof(__m128i)/sizeof(unsigned char)); i++){
|
||||
startpost(PRINT_MASK, *s);s++;
|
||||
}
|
||||
endpost();
|
||||
}
|
||||
static void print_short(__m128i m){
|
||||
_mm_pause();
|
||||
signed short*s=(signed short*)&m;
|
||||
int i=0;
|
||||
for(i=0; i<(sizeof(__m128i)/sizeof(signed short)); i++){
|
||||
startpost(PRINT_MASK, *s);s++;
|
||||
}
|
||||
endpost();
|
||||
}
|
||||
static void print_int(__m128i m){
|
||||
_mm_pause();
|
||||
signed int*s=(signed int*)&m;
|
||||
int i=0;
|
||||
for(i=0; i<(sizeof(__m128i)/sizeof(signed int)); i++){
|
||||
startpost(PRINT_MASK, *s);s++;
|
||||
}
|
||||
endpost();
|
||||
}
|
||||
|
||||
|
||||
/* convert RGBA to YUV422 */
|
||||
void RGBA_to_UYVY_SSE2(const unsigned char *rgbadata,
|
||||
size_t size,
|
||||
unsigned char *yuvdata)
|
||||
{
|
||||
const __m128i *rgba_p = (const __m128i*)rgbadata; /* 4 RGBA pixels */
|
||||
__m128i *yuv_p = (__m128i*)yuvdata; /* 4*2 YUV pixels */
|
||||
|
||||
const __m128i zero = _mm_setzero_si128();
|
||||
|
||||
const __m128i RG2Y=_mm_set_epi16(RGB2YUV_12, RGB2YUV_11, RGB2YUV_12, RGB2YUV_11,
|
||||
RGB2YUV_12, RGB2YUV_11, RGB2YUV_12, RGB2YUV_11);
|
||||
const __m128i BA2Y=_mm_set_epi16(RGB2YUV_14, RGB2YUV_13, RGB2YUV_14, RGB2YUV_13,
|
||||
RGB2YUV_14, RGB2YUV_13, RGB2YUV_14, RGB2YUV_13);
|
||||
|
||||
const __m128i RG2U=_mm_set_epi16(RGB2YUV_22, RGB2YUV_21, RGB2YUV_22, RGB2YUV_21,
|
||||
RGB2YUV_22, RGB2YUV_21, RGB2YUV_22, RGB2YUV_21);
|
||||
const __m128i BA2U=_mm_set_epi16(RGB2YUV_24, RGB2YUV_23, RGB2YUV_24, RGB2YUV_23,
|
||||
RGB2YUV_24, RGB2YUV_23, RGB2YUV_24, RGB2YUV_23);
|
||||
|
||||
const __m128i RG2V=_mm_set_epi16(RGB2YUV_32, RGB2YUV_31, RGB2YUV_32, RGB2YUV_31,
|
||||
RGB2YUV_32, RGB2YUV_31, RGB2YUV_32, RGB2YUV_31);
|
||||
const __m128i BA2V=_mm_set_epi16(RGB2YUV_34, RGB2YUV_33, RGB2YUV_34, RGB2YUV_33,
|
||||
RGB2YUV_34, RGB2YUV_33, RGB2YUV_34, RGB2YUV_33);
|
||||
|
||||
const __m128i OFFSET=_mm_set_epi16(Y_OFFSET, UV_OFFSET,
|
||||
Y_OFFSET, UV_OFFSET,
|
||||
Y_OFFSET, UV_OFFSET,
|
||||
Y_OFFSET, UV_OFFSET);
|
||||
|
||||
/* nomenclatura:
|
||||
* lower-case letters denote 8bit values (like "r" is red, 8bit)
|
||||
* upper-case letters denote 16bit (or 32bit) values (like "G" is green, 16bit)
|
||||
*
|
||||
*/
|
||||
__m128i rgba0, rgba1, RGBA0, RGBA1;
|
||||
__m128i RGRG, BABA, RGRG0, BABA0, RGRG1, BABA1;
|
||||
__m128i RGRG_BABA0, RGRG_BABA1;
|
||||
__m128i Y0, Y1, U, V, UY, VY, UV, YY;
|
||||
|
||||
const int shuffle = _MM_SHUFFLE(3, 1, 2, 0);
|
||||
|
||||
int i=size>>3; /* we do 2*128bit per cycle: this is 2*4*32bit == 8 pixels */
|
||||
while(i-->0){
|
||||
rgba0=*rgba_p++; /* r0 g0 b0 a0 r1 g1 ... b3 a3 */
|
||||
rgba1=*rgba_p++; /* r4 g4 b4 a4 r5 g5 ... b7 a7 */
|
||||
|
||||
/* 1st 4 pixels */
|
||||
RGBA0 = _mm_unpacklo_epi8(rgba0, zero); /* R0 G0 B0 A0 ... B1 A1 */
|
||||
RGBA1 = _mm_unpackhi_epi8(rgba0, zero); /* R2 G2 B2 A2 ... B3 A3 */
|
||||
|
||||
RGRG_BABA0 = _mm_unpacklo_epi32(RGBA0, RGBA1); /* R0 G0 R2 G2 B0 A0 B2 A2 */
|
||||
RGRG_BABA1 = _mm_unpackhi_epi32(RGBA0, RGBA1); /* R1 G1 R3 G3 B1 A1 B3 A3 */
|
||||
|
||||
RGRG0 = _mm_unpacklo_epi64(RGRG_BABA0, RGRG_BABA1); /* R0 G0 R2 G2 R1 G1 R3 G3 */
|
||||
BABA0 = _mm_unpackhi_epi64(RGRG_BABA0, RGRG_BABA1); /* B0 A0 B2 A2 B1 A1 B3 A3 */
|
||||
|
||||
// get Y for the 1st 4 pixels (thats 32bit)
|
||||
// Y_RG32 = _mm_madd_epi16(RGRG0, RG2Y); /* R0*a+G0*b R2*a+G2*b R1*a+G1*b R3*a+G3*b */
|
||||
// Y_BA32 = _mm_madd_epi16(BABA0, BA2Y); /* B0*c+A0*d B2*c+A2*d B1*c+A1*d B3*c+A3*d */
|
||||
Y0 = _mm_add_epi32(_mm_madd_epi16(RGRG0, RG2Y), _mm_madd_epi16(BABA0, BA2Y));
|
||||
Y0 = _mm_shuffle_epi32(Y0, shuffle);
|
||||
//startpost("Y0: "); print_int(Y0); /* Y0, Y1, Y2, Y3 */
|
||||
|
||||
/* 2nd 4 pixels */
|
||||
RGBA0 = _mm_unpacklo_epi8(rgba1, zero); /* R4 G4 B4 A4 R5 G5 B5 A5 */
|
||||
RGBA1 = _mm_unpackhi_epi8(rgba1, zero); /* R6 G6 B6 A6 R7 G7 B7 A7 */
|
||||
|
||||
RGRG_BABA0 = _mm_unpacklo_epi32(RGBA0, RGBA1); /* R4 G4 R6 G6 B4 A4 B6 A6 */
|
||||
RGRG_BABA1 = _mm_unpackhi_epi32(RGBA0, RGBA1); /* R5 G5 R7 G7 B5 A5 B7 A7 */
|
||||
|
||||
RGRG1 = _mm_unpacklo_epi64(RGRG_BABA0, RGRG_BABA1); /* R4 G4 R6 G6 R5 G5 R7 G7 */
|
||||
BABA1 = _mm_unpackhi_epi64(RGRG_BABA0, RGRG_BABA1); /* B4 A4 B6 A6 B5 A5 B7 A7 */
|
||||
|
||||
// get Y for the 2nd 4 pixels (thats 32bit)
|
||||
// Y_RG32 = _mm_madd_epi16(RGRG1, RG2Y); /* R4*a+G4*b R6*a+G6*b R5*a+G5*b R7*a+G7*b */
|
||||
// Y_BA32 = _mm_madd_epi16(BABA1, BA2Y); /* B4*c+A4*d B6*c+A6*d B5*c+A5*d B7*c+A7*d */
|
||||
Y1 = _mm_add_epi32(_mm_madd_epi16(RGRG1, RG2Y), _mm_madd_epi16(BABA1, BA2Y));
|
||||
Y1 = _mm_shuffle_epi32(Y1, shuffle);
|
||||
//startpost("Y1: "); print_int(Y1);
|
||||
|
||||
// now get UV
|
||||
/* (R01 G01 R23 G23 R45 G45 R67 G67) / 2 */
|
||||
RGRG = _mm_avg_epu16(_mm_unpackhi_epi64(RGRG0, RGRG1), _mm_unpacklo_epi64(RGRG0, RGRG1));
|
||||
/* (B01 A01 B23 A23 B45 A45 B67 A67) / 2 */
|
||||
BABA = _mm_avg_epu16(_mm_unpackhi_epi64(BABA0, BABA1), _mm_unpacklo_epi64(BABA0, BABA1));
|
||||
|
||||
// get 4 U for 8 pixels (32bit each)
|
||||
//U_RG32 = _mm_madd_epi16(RGRG, RG2U); /* R4*a+G4*b R6*a+G6*b R5*a+G5*b R7*a+G7*b */
|
||||
//U_BA32 = _mm_madd_epi16(BABA, AB2U); /* B4*c+A4*d B6*c+A6*d B5*c+A5*d B7*c+A7*d */
|
||||
U = _mm_add_epi32 (_mm_madd_epi16(RGRG, RG2U), _mm_madd_epi16(BABA, BA2U));
|
||||
|
||||
// get 4 V for 8 pixels (32bit each)
|
||||
//V_RG32 = _mm_madd_epi16(RGRG, RG2V); /* R4*a+G4*b R6*a+G6*b R5*a+G5*b R7*a+G7*b */
|
||||
//V_BA32 = _mm_madd_epi16(BABA, AB2V); /* B4*c+A4*d B6*c+A6*d B5*c+A5*d B7*c+A7*d */
|
||||
V = _mm_add_epi32 (_mm_madd_epi16(RGRG, RG2V), _mm_madd_epi16(BABA, BA2V));
|
||||
|
||||
// 32 instructions so far
|
||||
|
||||
// so now we have (all values in 32bit)
|
||||
/*
|
||||
* U U U U
|
||||
* Y1 Y1 Y1 Y1
|
||||
* V V V V
|
||||
* Y2 Y2 Y2 Y2
|
||||
*/
|
||||
|
||||
// we still need to right-shift everything by 8
|
||||
// and press it into 8bit values, so we have one vector with UYVYUYVYUYVYUYVY
|
||||
// (or just take the 3rd 8bit-tuple)
|
||||
|
||||
Y0 = _mm_srai_epi32(Y0, 8);
|
||||
U = _mm_srai_epi32(U , 8);
|
||||
Y1 = _mm_srai_epi32(Y1, 8);
|
||||
V = _mm_srai_epi32(V , 8);
|
||||
|
||||
UV = _mm_packs_epi32(U, V);
|
||||
YY = _mm_packs_epi32(Y0, Y1);
|
||||
|
||||
UV = _mm_shuffle_epi32(UV, shuffle);
|
||||
UV = _mm_shufflehi_epi16(UV, shuffle);
|
||||
UV = _mm_shufflelo_epi16(UV, shuffle);
|
||||
|
||||
UY = _mm_unpacklo_epi16(UV, YY);
|
||||
VY = _mm_unpackhi_epi16(UV, YY);
|
||||
|
||||
UY = _mm_adds_epi16(UY, OFFSET);
|
||||
VY = _mm_adds_epi16(VY, OFFSET);
|
||||
|
||||
_mm_stream_si128(yuv_p++, _mm_packus_epi16(UY, VY));
|
||||
// 32+15 instructions
|
||||
}
|
||||
}
|
||||
|
||||
/* convert RGBA to YUV422 */
|
||||
void UYVY_to_RGBA_SSE2(const unsigned char *yuvdata,
|
||||
size_t size,
|
||||
unsigned char *rgbadata)
|
||||
{
|
||||
__m128i *rgba_p = (__m128i*)rgbadata; /* 4 RGBA pixels */
|
||||
const __m128i *yuv_p = (const __m128i*)yuvdata; /* 4*2 YUV pixels */
|
||||
|
||||
const __m128i Y2RGB = _mm_set_epi16(YUV2RGB_11,0,YUV2RGB_11,0,YUV2RGB_11,0,YUV2RGB_11,0);
|
||||
const __m128i UV2R = _mm_set_epi16(YUV2RGB_13, YUV2RGB_12, YUV2RGB_13, YUV2RGB_12,
|
||||
YUV2RGB_13, YUV2RGB_12, YUV2RGB_13, YUV2RGB_12);
|
||||
const __m128i UV2G = _mm_set_epi16(YUV2RGB_23, YUV2RGB_22, YUV2RGB_23, YUV2RGB_22,
|
||||
YUV2RGB_23, YUV2RGB_22, YUV2RGB_23, YUV2RGB_22);
|
||||
const __m128i UV2B = _mm_set_epi16(YUV2RGB_33, YUV2RGB_32, YUV2RGB_33, YUV2RGB_32,
|
||||
YUV2RGB_33, YUV2RGB_32, YUV2RGB_33, YUV2RGB_32);
|
||||
const __m128i offset= _mm_set_epi16(Y_OFFSET, UV_OFFSET, Y_OFFSET, UV_OFFSET,
|
||||
Y_OFFSET, UV_OFFSET, Y_OFFSET, UV_OFFSET);
|
||||
const __m128i A32 = _mm_set_epi32(255, 255, 255, 255);
|
||||
|
||||
/* nomenclatura:
|
||||
* lower-case letters denote 8bit values (like "r" is red, 8bit)
|
||||
* upper-case letters denote 16bit (or 32bit) values (like "G" is green, 16bit)
|
||||
*/
|
||||
|
||||
__m128i uyvy, UYVY0, UYVY1;
|
||||
__m128i UV, YZ, Y, Z;
|
||||
__m128i UV_R, UV_G, UV_B;
|
||||
__m128i R, G, B, A;
|
||||
__m128i RB0, RB1, GA0, GA1;
|
||||
|
||||
const int shuffle = _MM_SHUFFLE(3, 1, 2, 0);
|
||||
|
||||
int i=size>>3; /* we do 2*128bit per cycle: this is 2*4*32bit == 8 pixels */
|
||||
while(i-->0){
|
||||
uyvy=*yuv_p++; /* u0 y0 v0 z0 u1 y1 v1 z1 u2 y2 v2 z2 u3 y3 v3 z3 */
|
||||
|
||||
UYVY0 = _mm_unpacklo_epi8(uyvy, _mm_setzero_si128()); /* U0 Y0 V0 Z0 U1 Y1 V1 Z1 */
|
||||
UYVY1 = _mm_unpackhi_epi8(uyvy, _mm_setzero_si128()); /* U2 Y2 V2 Z2 U3 Y3 V3 Z3 */
|
||||
|
||||
UYVY0 = _mm_sub_epi16(UYVY0, offset);
|
||||
UYVY1 = _mm_sub_epi16(UYVY1, offset);
|
||||
|
||||
UYVY0 = _mm_shufflelo_epi16(UYVY0, shuffle);
|
||||
UYVY0 = _mm_shufflehi_epi16(UYVY0, shuffle);
|
||||
UYVY0 = _mm_shuffle_epi32 (UYVY0, shuffle); /* U0 V0 U1 V1 Y0 Z0 Y1 Z1 */
|
||||
|
||||
UYVY1 = _mm_shufflelo_epi16(UYVY1, shuffle);
|
||||
UYVY1 = _mm_shufflehi_epi16(UYVY1, shuffle);
|
||||
UYVY1 = _mm_shuffle_epi32 (UYVY1, shuffle); /* U2 V2 U3 V3 Y2 Z2 Y3 Z3 */
|
||||
|
||||
UV = _mm_unpacklo_epi32(UYVY0, UYVY1); /* U0 V0 U2 V2 U1 V1 U3 V3 */
|
||||
YZ = _mm_unpackhi_epi32(UYVY0, UYVY1); /* Y0 Z0 Y2 Z2 Y1 Z1 Y3 Z3 */
|
||||
|
||||
Z = _mm_madd_epi16(YZ, Y2RGB); /* Z0' Z2' Z1' Z3' */
|
||||
Y = _mm_madd_epi16(YZ, _mm_srli_si128(Y2RGB, 2)); /* Y0' Y2' Y1' Y3' */
|
||||
|
||||
UV_R = _mm_madd_epi16(UV, UV2R);
|
||||
UV_G = _mm_madd_epi16(UV, UV2G);
|
||||
UV_B = _mm_madd_epi16(UV, UV2B);
|
||||
|
||||
R = _mm_srai_epi32(_mm_add_epi32(Y, UV_R), 8);
|
||||
G = _mm_srai_epi32(_mm_add_epi32(Y, UV_G), 8);
|
||||
B = _mm_srai_epi32(_mm_add_epi32(Y, UV_B), 8);
|
||||
|
||||
RB0 = _mm_packs_epi32(R, B);
|
||||
GA0 = _mm_packs_epi32(G, A32);
|
||||
|
||||
R = _mm_srai_epi32(_mm_add_epi32(Z, UV_R), 8);
|
||||
G = _mm_srai_epi32(_mm_add_epi32(Z, UV_G), 8);
|
||||
B = _mm_srai_epi32(_mm_add_epi32(Z, UV_B), 8);
|
||||
|
||||
RB1 = _mm_packs_epi32(R, B);
|
||||
GA1 = _mm_packs_epi32(G, A32);
|
||||
|
||||
R = _mm_unpacklo_epi16(RB0, RB1); /* R0 R1 R4 R5 R2 R3 R6 R7 */
|
||||
R = _mm_shuffle_epi32 (R, shuffle);/* R0 R1 R2 R3 R4 R5 R6 R7 */
|
||||
B = _mm_unpackhi_epi16(RB0, RB1);
|
||||
B = _mm_shuffle_epi32 (B, shuffle);
|
||||
G = _mm_unpacklo_epi16(GA0, GA1);
|
||||
G = _mm_shuffle_epi32 (G, shuffle);
|
||||
A = _mm_unpackhi_epi16(GA0, GA1); /* no need to shuffle, since A0=A1=...=255 */
|
||||
|
||||
RB0= _mm_unpacklo_epi16(R, B);
|
||||
RB1= _mm_unpackhi_epi16(R, B);
|
||||
RB0= _mm_packus_epi16 (RB0, RB1); /* R0 B0 R1 B1 R2 B2 R3 B3 R4 B4 R5 B5 R6 B6 R7 B7 */
|
||||
|
||||
GA0= _mm_unpacklo_epi16(G, A);
|
||||
GA1= _mm_unpackhi_epi16(G, A);
|
||||
GA0= _mm_packus_epi16 (GA0, GA1);
|
||||
|
||||
_mm_stream_si128(rgba_p++, _mm_unpacklo_epi8(RB0, GA0));
|
||||
_mm_stream_si128(rgba_p++, _mm_unpackhi_epi8(RB0, GA0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* convert RGB24 to YUV422 */
|
||||
void UYVY_to_RGB_SSE2(const unsigned char *yuvdata,
|
||||
size_t size,
|
||||
unsigned char *rgbdata)
|
||||
{
|
||||
const __m128i *yuv_p = (const __m128i*)yuvdata; /* 4*2 YUV pixels */
|
||||
|
||||
const __m128i Y2RGB = _mm_set_epi16(YUV2RGB_11,0,YUV2RGB_11,0,YUV2RGB_11,0,YUV2RGB_11,0);
|
||||
const __m128i UV2R = _mm_set_epi16(YUV2RGB_13, YUV2RGB_12, YUV2RGB_13, YUV2RGB_12,
|
||||
YUV2RGB_13, YUV2RGB_12, YUV2RGB_13, YUV2RGB_12);
|
||||
const __m128i UV2G = _mm_set_epi16(YUV2RGB_23, YUV2RGB_22, YUV2RGB_23, YUV2RGB_22,
|
||||
YUV2RGB_23, YUV2RGB_22, YUV2RGB_23, YUV2RGB_22);
|
||||
const __m128i UV2B = _mm_set_epi16(YUV2RGB_33, YUV2RGB_32, YUV2RGB_33, YUV2RGB_32,
|
||||
YUV2RGB_33, YUV2RGB_32, YUV2RGB_33, YUV2RGB_32);
|
||||
const __m128i offset= _mm_set_epi16(Y_OFFSET, UV_OFFSET, Y_OFFSET, UV_OFFSET,
|
||||
Y_OFFSET, UV_OFFSET, Y_OFFSET, UV_OFFSET);
|
||||
const __m128i A32 = _mm_set_epi32(255, 255, 255, 255);
|
||||
const __m128i all = _mm_set_epi8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
/* nomenclatura:
|
||||
* lower-case letters denote 8bit values (like "r" is red, 8bit)
|
||||
* upper-case letters denote 16bit (or 32bit) values (like "G" is green, 16bit)
|
||||
*/
|
||||
|
||||
__m128i uyvy, UYVY0, UYVY1;
|
||||
__m128i UV, YZ, Y, Z;
|
||||
__m128i UV_R, UV_G, UV_B;
|
||||
__m128i R, G, B, A;
|
||||
__m128i RB0, RB1, GA0, GA1;
|
||||
|
||||
vector_128 v0, v1;
|
||||
|
||||
const int shuffle = _MM_SHUFFLE(3, 1, 2, 0);
|
||||
|
||||
int i=size>>3; /* we do 2*128bit per cycle: this is 2*4*32bit == 8 pixels */
|
||||
while(i-->0){
|
||||
uyvy=*yuv_p++; /* u0 y0 v0 z0 u1 y1 v1 z1 u2 y2 v2 z2 u3 y3 v3 z3 */
|
||||
|
||||
UYVY0 = _mm_unpacklo_epi8(uyvy, _mm_setzero_si128()); /* U0 Y0 V0 Z0 U1 Y1 V1 Z1 */
|
||||
UYVY1 = _mm_unpackhi_epi8(uyvy, _mm_setzero_si128()); /* U2 Y2 V2 Z2 U3 Y3 V3 Z3 */
|
||||
|
||||
UYVY0 = _mm_sub_epi16(UYVY0, offset);
|
||||
UYVY1 = _mm_sub_epi16(UYVY1, offset);
|
||||
|
||||
UYVY0 = _mm_shufflelo_epi16(UYVY0, shuffle);
|
||||
UYVY0 = _mm_shufflehi_epi16(UYVY0, shuffle);
|
||||
UYVY0 = _mm_shuffle_epi32 (UYVY0, shuffle); /* U0 V0 U1 V1 Y0 Z0 Y1 Z1 */
|
||||
|
||||
UYVY1 = _mm_shufflelo_epi16(UYVY1, shuffle);
|
||||
UYVY1 = _mm_shufflehi_epi16(UYVY1, shuffle);
|
||||
UYVY1 = _mm_shuffle_epi32 (UYVY1, shuffle); /* U2 V2 U3 V3 Y2 Z2 Y3 Z3 */
|
||||
|
||||
UV = _mm_unpacklo_epi32(UYVY0, UYVY1); /* U0 V0 U2 V2 U1 V1 U3 V3 */
|
||||
YZ = _mm_unpackhi_epi32(UYVY0, UYVY1); /* Y0 Z0 Y2 Z2 Y1 Z1 Y3 Z3 */
|
||||
|
||||
Z = _mm_madd_epi16(YZ, Y2RGB); /* Z0' Z2' Z1' Z3' */
|
||||
Y = _mm_madd_epi16(YZ, _mm_srli_si128(Y2RGB, 2)); /* Y0' Y2' Y1' Y3' */
|
||||
|
||||
UV_R = _mm_madd_epi16(UV, UV2R);
|
||||
UV_G = _mm_madd_epi16(UV, UV2G);
|
||||
UV_B = _mm_madd_epi16(UV, UV2B);
|
||||
|
||||
R = _mm_srai_epi32(_mm_add_epi32(Y, UV_R), 8);
|
||||
G = _mm_srai_epi32(_mm_add_epi32(Y, UV_G), 8);
|
||||
B = _mm_srai_epi32(_mm_add_epi32(Y, UV_B), 8);
|
||||
|
||||
RB0 = _mm_packs_epi32(R, G);
|
||||
GA0 = _mm_packs_epi32(B, _mm_setzero_si128());
|
||||
|
||||
R = _mm_srai_epi32(_mm_add_epi32(Z, UV_R), 8);
|
||||
G = _mm_srai_epi32(_mm_add_epi32(Z, UV_G), 8);
|
||||
B = _mm_srai_epi32(_mm_add_epi32(Z, UV_B), 8);
|
||||
|
||||
RB1 = _mm_packs_epi32(R, G);
|
||||
GA1 = _mm_packs_epi32(B, _mm_setzero_si128());
|
||||
|
||||
v0.v= _mm_packus_epi16 (RB0, GA0);
|
||||
v1.v= _mm_packus_epi16 (RB1, GA1);
|
||||
|
||||
rgbdata[chRed ]=v0.c[ 0];
|
||||
rgbdata[chGreen ]=v0.c[ 4];
|
||||
rgbdata[chBlue ]=v0.c[ 8];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v1.c[ 0];
|
||||
rgbdata[chGreen ]=v1.c[ 4];
|
||||
rgbdata[chBlue ]=v1.c[ 8];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v0.c[ 2];
|
||||
rgbdata[chGreen ]=v0.c[ 6];
|
||||
rgbdata[chBlue ]=v0.c[10];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v1.c[ 2];
|
||||
rgbdata[chGreen ]=v1.c[ 6];
|
||||
rgbdata[chBlue ]=v1.c[10];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v0.c[ 1];
|
||||
rgbdata[chGreen ]=v0.c[ 5];
|
||||
rgbdata[chBlue ]=v0.c[ 9];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v1.c[ 1];
|
||||
rgbdata[chGreen ]=v1.c[ 5];
|
||||
rgbdata[chBlue ]=v1.c[ 9];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v0.c[ 3];
|
||||
rgbdata[chGreen ]=v0.c[ 7];
|
||||
rgbdata[chBlue ]=v0.c[11];
|
||||
rgbdata+=3;
|
||||
|
||||
rgbdata[chRed ]=v1.c[ 3];
|
||||
rgbdata[chGreen ]=v1.c[ 7];
|
||||
rgbdata[chBlue ]=v1.c[11];
|
||||
rgbdata+=3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
154
Gem/src/Gem/Properties.cpp
Normal file
154
Gem/src/Gem/Properties.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#include <map>
|
||||
|
||||
#include "Properties.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace gem {
|
||||
|
||||
class Properties::PIMPL {
|
||||
public:
|
||||
std::map<std::string, any> valuemap;
|
||||
std::map<std::string, enum Properties::PropertyType> typemap;
|
||||
|
||||
PIMPL(void) {;}
|
||||
};
|
||||
|
||||
|
||||
Properties::Properties() :
|
||||
pimpl(new PIMPL())
|
||||
{ }
|
||||
|
||||
Properties::Properties(const gem::Properties&org) :
|
||||
pimpl(new PIMPL())
|
||||
{
|
||||
assign(org);
|
||||
}
|
||||
|
||||
|
||||
Properties::~Properties() {
|
||||
delete pimpl;
|
||||
}
|
||||
#if 0
|
||||
any&Properties::operator[](const std::string&key) {
|
||||
return pimpl->valuemap[key];
|
||||
}
|
||||
#endif
|
||||
|
||||
any Properties::get(const std::string&key) const {
|
||||
return pimpl->valuemap[key];
|
||||
}
|
||||
|
||||
void Properties::set(const std::string&key, gem::any value) {
|
||||
const std::type_info*typ=&value.get_type();
|
||||
PropertyType pt = UNKNOWN;
|
||||
|
||||
double d=0;
|
||||
std::string s;
|
||||
|
||||
#define ISTYPE(type) (*typ == typeid(type))
|
||||
|
||||
if (value.empty()) {
|
||||
pt = NONE;
|
||||
} else if(ISTYPE(char)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<char>(value);
|
||||
} else if(ISTYPE(unsigned char)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<unsigned char>(value);
|
||||
|
||||
} else if(ISTYPE(short)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<short>(value);
|
||||
} else if(ISTYPE(unsigned short)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<unsigned short>(value);
|
||||
|
||||
} else if(ISTYPE(int)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<int>(value);
|
||||
} else if(ISTYPE(unsigned int)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<unsigned int>(value);
|
||||
#if 0
|
||||
/* "long"s cannot be stored in "double"s without loosing precision... */
|
||||
} else if(ISTYPE(long)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<long>(value);
|
||||
} else if(ISTYPE(unsigned long)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<unsigned long>(value);
|
||||
#endif
|
||||
} else if(ISTYPE(float)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<float>(value);
|
||||
} else if(ISTYPE(double)) {
|
||||
pt = DOUBLE;
|
||||
d=any_cast<double>(value);
|
||||
|
||||
} else if(ISTYPE(char*)) {
|
||||
pt = STRING;
|
||||
s=std::string(any_cast<char*>(value));
|
||||
#ifdef SETSYMBOL
|
||||
/* only use this, if compiled with Pd... */
|
||||
} else if(ISTYPE(t_symbol*)) {
|
||||
pt = STRING;
|
||||
s=std::string((any_cast<t_symbol*>(value))->s_name);
|
||||
#endif
|
||||
} else if(ISTYPE(std::string)) {
|
||||
pt = STRING;
|
||||
s=any_cast<std::string>(value);
|
||||
}
|
||||
|
||||
switch(pt) {
|
||||
case NONE:
|
||||
pimpl->valuemap[key]=value;
|
||||
pimpl->typemap[key]=NONE;
|
||||
break;
|
||||
case DOUBLE:
|
||||
pimpl->valuemap[key]=d;
|
||||
pimpl->typemap[key]=DOUBLE;
|
||||
break;
|
||||
case STRING:
|
||||
pimpl->valuemap[key]=s;
|
||||
pimpl->typemap[key]=STRING;
|
||||
break;
|
||||
default:
|
||||
pimpl->valuemap[key]=value;
|
||||
pimpl->typemap[key]=UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>Properties::keys() const {
|
||||
std::vector<std::string>result;
|
||||
std::map<std::string,gem::any>::iterator it;
|
||||
for(it = pimpl->valuemap.begin(); it != pimpl->valuemap.end(); ++it)
|
||||
result.push_back(it->first);
|
||||
return result;
|
||||
}
|
||||
|
||||
enum Properties::PropertyType Properties::type(std::string key) const {
|
||||
std::map<std::string, enum Properties::PropertyType>::iterator it=pimpl->typemap.find(key);
|
||||
if(pimpl->typemap.end() == it)
|
||||
return UNSET;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Properties::erase(std::string key) {
|
||||
pimpl->typemap.erase(key);
|
||||
pimpl->valuemap.erase(key);
|
||||
}
|
||||
void Properties::clear() {
|
||||
pimpl->typemap.clear();
|
||||
pimpl->valuemap.clear();
|
||||
}
|
||||
|
||||
Properties& Properties::assign(const Properties&org) {
|
||||
pimpl->valuemap=org.pimpl->valuemap;
|
||||
pimpl->typemap =org.pimpl->typemap;
|
||||
|
||||
return(*this);
|
||||
}
|
||||
};
|
||||
110
Gem/src/Gem/Properties.h
Normal file
110
Gem/src/Gem/Properties.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
*
|
||||
* map that stores "any"thing
|
||||
*
|
||||
* USAGE:
|
||||
*
|
||||
* Properties am; // create a new Properties
|
||||
* am["a"] = 42; // assign value "42" to key "a"
|
||||
* int i=0;
|
||||
* try { i=any_cast<int>am["a"]; } catch(bad_any_cast ex) { ; } // retrieve value from key "a"; might throw a bad_any_cast exception
|
||||
* am.get("a", i); // retrieve value at key "a"; if there was an error (e.g. typeof(i) does not match, then i is left untouched and "false" is returned
|
||||
*
|
||||
* NOTE:
|
||||
* this simplilstic approach has some problems with type-conversion
|
||||
* e.g. this will fail:
|
||||
* am["a"]=12.0f; any_cast<int>am["a"];
|
||||
*/
|
||||
|
||||
#ifndef GEM_PROPERTIES_H
|
||||
#define GEM_PROPERTIES_H
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
#include "Utils/any.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace gem
|
||||
{
|
||||
class GEM_EXTERN Properties {
|
||||
private:
|
||||
class PIMPL;
|
||||
PIMPL*pimpl;
|
||||
|
||||
public:
|
||||
enum PropertyType {
|
||||
UNSET=-1, /* not set, in-existent */
|
||||
NONE, /* "bang" */
|
||||
DOUBLE, /* double */
|
||||
STRING, /* std::string */
|
||||
UNKNOWN /* all the rest */
|
||||
};
|
||||
|
||||
Properties(void);
|
||||
Properties(const gem::Properties&); /* copy constructor */
|
||||
|
||||
virtual ~Properties(void);
|
||||
|
||||
#if 0
|
||||
/* array/hashmap like access:
|
||||
* e.g.: prop["width"]=640;
|
||||
*/
|
||||
virtual gem::any&operator[](const std::string&key);
|
||||
#endif
|
||||
|
||||
/* get the value of a property
|
||||
* e.g.: double w=any_cast<double>prop.at("width")
|
||||
*/
|
||||
virtual gem::any get(const std::string&key) const;
|
||||
|
||||
/* check whether the given key exists
|
||||
* if the key was in the property-map, return the type of the property
|
||||
* if no key of the given value exists, return <code>PropertyType::UNSET</code>
|
||||
*/
|
||||
virtual enum PropertyType type(const std::string) const;
|
||||
|
||||
/* set a property
|
||||
* e.g.: double w=640; prop.set("width", w);
|
||||
*/
|
||||
virtual void set(const std::string&key, gem::any value);
|
||||
|
||||
/* get a property
|
||||
* e.g.: double w=320; prop.get("width", w);
|
||||
* NOTE: if no property of the given name exists or the existing property
|
||||
* is of a different (incompatible) type, "value" will not be changed
|
||||
*/
|
||||
template<class Class>
|
||||
bool get(const std::string&key, Class&value) const {
|
||||
try {
|
||||
value=gem::any_cast<Class>(get(key));
|
||||
} catch (gem::bad_any_cast e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/* get all keys
|
||||
*/
|
||||
virtual std::vector<std::string>keys(void) const;
|
||||
|
||||
/*
|
||||
* delete a given key from the Properties
|
||||
*/
|
||||
virtual void erase(const std::string);
|
||||
/*
|
||||
* delete all keys from the Properties
|
||||
*/
|
||||
virtual void clear(void);
|
||||
|
||||
|
||||
/*
|
||||
* assign Properties from another set
|
||||
*/
|
||||
virtual gem::Properties& assign(const gem::Properties&);
|
||||
gem::Properties& operator= (const gem::Properties&org) { return assign(org); }
|
||||
|
||||
};
|
||||
};
|
||||
#endif /* GEM_PROPERTIES_H */
|
||||
29
Gem/src/Gem/RTE.h
Normal file
29
Gem/src/Gem/RTE.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
include Realtime-Environments headers
|
||||
|
||||
Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_RTE_H_
|
||||
#define _INCLUDE__GEM_GEM_RTE_H_
|
||||
|
||||
#if defined _MSC_VER
|
||||
/* data conversion with possible loss of data */
|
||||
# pragma warning( push )
|
||||
# pragma warning( disable : 4091 )
|
||||
#endif
|
||||
|
||||
#include "m_pd.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _INCLUDE__GEM_GEM_RTE_H_ */
|
||||
48
Gem/src/Gem/Rectangle.cpp
Normal file
48
Gem/src/Gem/Rectangle.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2012 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "Rectangle.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Rectangle
|
||||
//
|
||||
namespace gem {
|
||||
Rectangle :: Rectangle(void) :
|
||||
x1(0.f), y1(0.f), x2(1.f), y2(1.f)
|
||||
{
|
||||
}
|
||||
|
||||
#define CLAMP01(x) if(x<0.)x=0.;else if(x>1.)x=1.;
|
||||
Rectangle Rectangle :: createNormalized(float x1, float y1, float x2, float y2) {
|
||||
Rectangle result;
|
||||
|
||||
float minX=(x1<x2)?x1:x2;
|
||||
float maxX=(x1>x2)?x1:x2;
|
||||
float minY=(y1<y2)?y1:y2;
|
||||
float maxY=(y1>y2)?y1:y2;
|
||||
CLAMP01(minX);
|
||||
CLAMP01(maxX);
|
||||
CLAMP01(minY);
|
||||
CLAMP01(maxY);
|
||||
|
||||
result.x1=minX;
|
||||
result.x2=maxX;
|
||||
result.y1=minY;
|
||||
result.y2=maxY;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
44
Gem/src/Gem/Rectangle.h
Normal file
44
Gem/src/Gem/Rectangle.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
an abstract rectangle representation
|
||||
|
||||
Copyright (c) 1997-1999 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_RECTANGLE_H_
|
||||
#define _INCLUDE__GEM_GEM_RECTANGLE_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
Rectangle
|
||||
|
||||
abstract rectangle class (to be used e.g. as ROI)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
namespace gem {
|
||||
class GEM_EXTERN Rectangle
|
||||
{
|
||||
public:
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
Rectangle(void);
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
static Rectangle createNormalized(float x1, float y1, float x2, float y2);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
315
Gem/src/Gem/Settings.cpp
Normal file
315
Gem/src/Gem/Settings.cpp
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
// load settings from a file (or get them via env-variables)
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "Gem/GemConfig.h"
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
#include "Settings.h"
|
||||
#include "Files.h"
|
||||
|
||||
#include <map>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define GEM_SETTINGS_FILE "gem.conf"
|
||||
static const char*s_configdir[] = {
|
||||
#ifdef __linux__
|
||||
"/etc/pd",
|
||||
"~/.config/pure-data",
|
||||
#elif defined __APPLE__
|
||||
"/Library/Pd",
|
||||
"~/Library/Pd",
|
||||
#elif defined _WIN32
|
||||
"%CommonProgramFiles%\\Pd",
|
||||
"%AppData%\\Pd",
|
||||
#endif
|
||||
0 /* $(pwd)/gem.conf */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* this is ripped from m_imp.h */
|
||||
struct _gemclass
|
||||
{
|
||||
t_symbol *c_name; /* name (mostly for error reporting) */
|
||||
t_symbol *c_helpname; /* name of help file */
|
||||
t_symbol *c_externdir; /* directory extern was loaded from */
|
||||
/* ... */ /* the real t_class continues here... */
|
||||
};
|
||||
# define t_gemclass struct _gemclass
|
||||
|
||||
|
||||
namespace {
|
||||
struct PIMPL {
|
||||
// dictionary for setting values
|
||||
std::map <std::string, t_atom> data;
|
||||
|
||||
virtual t_atom*get(std::string name) {
|
||||
std::map<std::string, t_atom>::iterator it=data.find(name);
|
||||
if(it==data.end())
|
||||
return NULL;
|
||||
return &it->second;
|
||||
}
|
||||
virtual void set(std::string name, t_atom*value) {
|
||||
// LATER: we should expand envvariables
|
||||
if(value) {
|
||||
data[name]= *value;
|
||||
} else {
|
||||
data.erase(name);
|
||||
}
|
||||
}
|
||||
|
||||
void set(std::string name, int i) {
|
||||
t_atom a;
|
||||
SETFLOAT(&a, i);
|
||||
set(name, &a);
|
||||
}
|
||||
void set(std::string name, float f) {
|
||||
t_atom a;
|
||||
SETFLOAT(&a, f);
|
||||
set(name, &a);
|
||||
}
|
||||
void set(std::string name, double f) {
|
||||
t_atom a;
|
||||
SETFLOAT(&a, f);
|
||||
set(name, &a);
|
||||
}
|
||||
void set(std::string name, std::string s) {
|
||||
t_atom a;
|
||||
SETSYMBOL(&a, gensym(s.c_str()));
|
||||
set(name, &a);
|
||||
}
|
||||
|
||||
// std::string expandEnv(std::string , bool bashfilename=false);
|
||||
|
||||
|
||||
bool open(const char*filename, const char*dirname=NULL) {
|
||||
t_binbuf*bb=binbuf_new();
|
||||
int r=0;
|
||||
if(NULL==filename)
|
||||
return false;
|
||||
|
||||
|
||||
if(dirname) {
|
||||
r=binbuf_read(bb, (char*)filename, const_cast<char*>(gem::files::expandEnv(dirname, true).c_str()), 1);
|
||||
if(0==r)verbose(1, "found Gem-settings '%s' in '%s'", filename, dirname);
|
||||
} else {
|
||||
r=binbuf_read_via_path(bb, (char*)filename, (char*)".", 1);
|
||||
if(0==r)verbose(1, "found Gem-settings '%s'", filename);
|
||||
}
|
||||
|
||||
if(r){
|
||||
binbuf_free(bb);
|
||||
return false;
|
||||
}
|
||||
|
||||
int ac=binbuf_getnatom(bb);
|
||||
t_atom*av=binbuf_getvec(bb);
|
||||
|
||||
std::string s;
|
||||
t_atom*a=NULL;
|
||||
int state=0; /* 0=(next is ID); 1=(next is value); 2=(next is ignored) */
|
||||
|
||||
while(ac--) {
|
||||
if (av->a_type == A_SEMI) {
|
||||
// done
|
||||
if(!s.empty()) {
|
||||
set(s, a);
|
||||
}
|
||||
state=0;
|
||||
s.clear();
|
||||
} else {
|
||||
switch (state) {
|
||||
case 0:
|
||||
s=atom_getsymbol(av)->s_name;
|
||||
state=1;
|
||||
break;
|
||||
case 1:
|
||||
a=av;
|
||||
state=2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
av++;
|
||||
}
|
||||
|
||||
binbuf_free(bb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void print(void) {
|
||||
std::map <std::string , t_atom>::iterator it;
|
||||
for(it = data.begin();
|
||||
it != data.end();
|
||||
it++)
|
||||
{
|
||||
if(!it->first.empty()) {
|
||||
startpost("key ['%s']: '", it->first.c_str());
|
||||
postatom(1, &it->second);
|
||||
|
||||
post("'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PIMPL(void)
|
||||
{
|
||||
int i=0;
|
||||
#ifdef GEM_DEFAULT_FONT
|
||||
set("font.face", GEM_DEFAULT_FONT);
|
||||
#endif
|
||||
|
||||
setEnv("settings.file", "GEM_SETTINGS");
|
||||
t_atom*a=NULL;
|
||||
a=get("settings.file");
|
||||
if(a) {
|
||||
std::string s=atom_getsymbol(a)->s_name;
|
||||
open(gem::files::expandEnv(s.c_str(), true).c_str(), ".");
|
||||
} else {
|
||||
while(s_configdir[i]) {
|
||||
open(GEM_SETTINGS_FILE, s_configdir[i]);
|
||||
i++;
|
||||
}
|
||||
open(GEM_SETTINGS_FILE, ".");
|
||||
}
|
||||
|
||||
/* legacy settings via environmental variables */
|
||||
setEnv("texture.rectangle", "GEM_RECTANGLE_TEXTURE");
|
||||
setEnv("singlecontext", "GEM_SINGLE_CONTEXT"); // hmm, what's a better new name for this?
|
||||
setEnv("font.face", "GEM_DEFAULT_FONT");
|
||||
|
||||
|
||||
t_gemclass *c = (t_gemclass*)class_new(gensym("Gem"), 0, 0, 0, 0, A_NULL);
|
||||
set("gem.path", c->c_externdir->s_name);
|
||||
|
||||
// print();
|
||||
}
|
||||
|
||||
~PIMPL(void) {
|
||||
|
||||
}
|
||||
|
||||
void setEnv(std::string key, const std::string env) {
|
||||
if(env.empty())return;
|
||||
if(key.empty())return;
|
||||
|
||||
char*result=getenv(env.c_str());
|
||||
if(NULL==result) {
|
||||
return;
|
||||
}
|
||||
|
||||
t_atom a;
|
||||
errno=0;
|
||||
|
||||
/* try integer */
|
||||
long l=strtol(result, NULL, 0);
|
||||
if(0==errno) {
|
||||
SETFLOAT(&a, l);
|
||||
set(key, &a);
|
||||
}
|
||||
|
||||
/* try float */
|
||||
double d=strtod(result, NULL);
|
||||
if(0==errno) {
|
||||
SETFLOAT(&a, d);
|
||||
set(key, &a);
|
||||
}
|
||||
|
||||
/* try symbol */
|
||||
SETSYMBOL(&a, gensym(result));
|
||||
set(key, &a);
|
||||
|
||||
// we ignore lists and other complex things for now
|
||||
}
|
||||
};
|
||||
static PIMPL*settings=NULL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* gem::Settings: the public API */
|
||||
|
||||
|
||||
/* public static functions */
|
||||
void gem::Settings::init() {
|
||||
if(settings)return;
|
||||
settings=new PIMPL();
|
||||
}
|
||||
void gem::Settings::print() {
|
||||
if(!settings)return;
|
||||
settings->print();
|
||||
}
|
||||
void gem::Settings::save() {
|
||||
if(!settings)return;
|
||||
post("gem::Settings: save not yet implemented!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
t_atom*gem::Settings::get(const std::string s) {
|
||||
if(NULL==settings) init();
|
||||
return settings->get(s.c_str());
|
||||
}
|
||||
void gem::Settings::set(const std::string s, t_atom*v) {
|
||||
settings->set(s.c_str(), v);
|
||||
}
|
||||
|
||||
|
||||
void gem::Settings::get(const std::string key, int&value) {
|
||||
t_atom*a=get(key);
|
||||
if(a && A_FLOAT==a->a_type) {
|
||||
value=atom_getint(a);
|
||||
}
|
||||
}
|
||||
void gem::Settings::get(const std::string key, float&value) {
|
||||
t_atom*a=get(key);
|
||||
if(a && A_FLOAT==a->a_type) {
|
||||
value=atom_getfloat(a);
|
||||
}
|
||||
}
|
||||
void gem::Settings::get(const std::string key, double&value) {
|
||||
t_atom*a=get(key);
|
||||
if(a && A_FLOAT==a->a_type) {
|
||||
value=atom_getfloat(a);
|
||||
}
|
||||
}
|
||||
|
||||
void gem::Settings::get(const std::string key, std::string&value) {
|
||||
t_atom*a=get(key);
|
||||
if(a) {
|
||||
value=atom_getsymbol(a)->s_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>gem::Settings::keys(void) {
|
||||
std::vector<std::string>result;
|
||||
if(NULL==settings) init();
|
||||
if(NULL!=settings) {
|
||||
std::map<std::string, t_atom>::iterator it=settings->data.begin();
|
||||
while(settings->data.end() != it) {
|
||||
result.push_back(it->first);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
35
Gem/src/Gem/Settings.h
Normal file
35
Gem/src/Gem/Settings.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
- Runtime Configuration of Gem
|
||||
|
||||
Copyright (c) 2009-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_SETTINGS_H_
|
||||
#define _INCLUDE__GEM_GEM_SETTINGS_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef struct _atom t_atom;
|
||||
namespace gem { namespace Settings {
|
||||
void init(void);
|
||||
void print(void);
|
||||
void save(void);
|
||||
|
||||
t_atom*get(const std::string key);
|
||||
void set(const std::string key, t_atom*value=NULL);
|
||||
|
||||
void get(const std::string key, int&value);
|
||||
void get(const std::string key, float&value);
|
||||
void get(const std::string key, double&value);
|
||||
void get(const std::string key, std::string&value);
|
||||
|
||||
std::vector<std::string> keys();
|
||||
}; };
|
||||
#endif
|
||||
245
Gem/src/Gem/Setup.cpp
Normal file
245
Gem/src/Gem/Setup.cpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-2000 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/* OLDNAMES.lib pd.lib opengl32.lib glu32.lib freetype235mt.lib FTGL_static.lib libcpmt.lib msvcrt.lib msvcprt.lib ws2_32.lib pthreadVC.lib
|
||||
* pd.lib freetype235mt.lib FTGL_static.lib opengl32.lib glu32.lib ws2_32.lib pthreadVC.lib (?)
|
||||
|
||||
* OLDNAMES.lib: _close, _open, _strdup
|
||||
* pd.lib
|
||||
* opengl32.lib
|
||||
* glu32.lib: gluFunctions (sphere, cylinder, lookat,...)
|
||||
* freetype235mt.lib FTGL_static.lib
|
||||
* libcpmt.lib: std::cerr,...
|
||||
* msvcrt.lib: typeinfo,...
|
||||
* ws2_32.lib
|
||||
* pthreadVC.lib
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "Gem/GemConfig.h"
|
||||
/* -------------------------- setup function ------------------------------ */
|
||||
|
||||
#include "Gem/Manager.h"
|
||||
#include "Gem/Version.h"
|
||||
#include "Gem/Files.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
# define snprintf _snprintf
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define _open open
|
||||
# define _close close
|
||||
#endif
|
||||
|
||||
|
||||
static const char GEM_MAINTAINER[] = "IOhannes m zmoelnig";
|
||||
|
||||
static const char *GEM_AUTHORS[] = {
|
||||
"Chris Clepper",
|
||||
"Cyrille Henry",
|
||||
"IOhannes m zmoelnig"
|
||||
};
|
||||
|
||||
static const char GEM_OTHERAUTHORS[] =
|
||||
"Guenter Geiger, Daniel Heckenberg, James Tittle, Hans-Christoph Steiner, et al.";
|
||||
|
||||
extern "C" {
|
||||
#if defined HAVE_S_STUFF_H
|
||||
# include "s_stuff.h"
|
||||
|
||||
# ifndef _WIN32
|
||||
/* MSVC/MinGW cannot really handle these exported symbols */
|
||||
# define GEM_ADDPATH
|
||||
# endif
|
||||
|
||||
#endif /* HAVE_S_STUFF_H */
|
||||
|
||||
/* this is ripped from m_imp.h */
|
||||
struct _gemclass
|
||||
{
|
||||
t_symbol *c_name; /* name (mostly for error reporting) */
|
||||
t_symbol *c_helpname; /* name of help file */
|
||||
t_symbol *c_externdir; /* directory extern was loaded from */
|
||||
/* ... */ /* the real t_class continues here... */
|
||||
};
|
||||
# define t_gemclass struct _gemclass
|
||||
} // for extern "C"
|
||||
|
||||
|
||||
|
||||
namespace Gem {
|
||||
static bool checkVersion(const char*dirname, const char*filename, int flags) {
|
||||
t_binbuf*bb=binbuf_new();
|
||||
if(binbuf_read(bb, const_cast<char*>(filename), const_cast<char*>(dirname), flags)) {
|
||||
/* couldn't find the file */
|
||||
return true;
|
||||
}
|
||||
|
||||
int argc = binbuf_getnatom(bb);
|
||||
t_atom*argv=binbuf_getvec(bb);
|
||||
|
||||
const t_symbol* _X=gensym("#X");
|
||||
const t_symbol* _text=gensym("text");
|
||||
const t_symbol* _version=gensym("VERSION");
|
||||
|
||||
std::string gotversion;
|
||||
|
||||
int i;
|
||||
/* search for: "#X text <num> <num> VERSION <string>;" */
|
||||
// #X text 10 30 VERSION 0.93 \;
|
||||
|
||||
for(i=0; i<argc; i++) {
|
||||
if(A_SYMBOL!=argv[i].a_type)continue;
|
||||
if((_X==atom_getsymbol(argv+i)) && (i+6<argc)) {
|
||||
t_atom*ap=argv+i+1;
|
||||
if(_text ==atom_getsymbol(ap+0) &&
|
||||
_version==atom_getsymbol(ap+3) &&
|
||||
A_FLOAT == ap[1].a_type &&
|
||||
A_FLOAT == ap[2].a_type
|
||||
) {
|
||||
char buf[MAXPDSTRING];
|
||||
|
||||
if(A_SYMBOL==ap[4].a_type) {
|
||||
gotversion=std::string(atom_getsymbol(ap+4)->s_name);
|
||||
} else {
|
||||
snprintf(buf, MAXPDSTRING-1, "%g", atom_getfloat(ap+4));
|
||||
gotversion=std::string(buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
binbuf_free(bb);
|
||||
|
||||
int major, minor;
|
||||
sscanf(gotversion.c_str(), "%d.%d", &major, &minor);
|
||||
|
||||
bool result=gem::Version::versionCheck(major,minor);
|
||||
if(!result) {
|
||||
error("Gem binary/abstractions version mismatch!");
|
||||
verbose(0, "Gem binary is %d.%d, but Gem abstractions are %s", GEM_VERSION_MAJOR, GEM_VERSION_MINOR, gotversion.c_str());
|
||||
verbose(0, "This usually means that you have a path to another version of Gem stored in your startup preferences");
|
||||
verbose(0, "Consider removing the wrong path!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void addownpath(const char*filename) {
|
||||
char buf[MAXPDSTRING];
|
||||
char*bufptr=NULL;
|
||||
int fd=-1;
|
||||
|
||||
int flags=O_RDONLY;
|
||||
#ifdef _WIN32
|
||||
flags |= _O_BINARY;
|
||||
#endif
|
||||
|
||||
/* check whether we can find the abstractions (because they are already in Pd's path) */
|
||||
if ((fd=canvas_open(NULL, filename, "", buf, &bufptr, MAXPDSTRING, 1))>=0){
|
||||
gem::files::close(fd);
|
||||
checkVersion(buf, filename, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
char*mypath=0;
|
||||
t_gemclass *c = (t_gemclass*)class_new(gensym("Gem"), 0, 0, 0, 0, A_NULL);
|
||||
mypath=c->c_externdir->s_name;
|
||||
|
||||
/* check whether we can find the abstractions in Gem's own path */
|
||||
snprintf(buf, MAXPDSTRING-1, "%s/%s", mypath, filename);
|
||||
buf[MAXPDSTRING-1]=0;
|
||||
if ((fd=_open(buf, flags))>=0){
|
||||
_close(fd);
|
||||
} else {
|
||||
// can't find this abstraction...giving up
|
||||
verbose(0, "please add path to '%s' to your search-path!", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef GEM_ADDPATH
|
||||
verbose(1, "eventually adding Gem path '%s' to search-paths", mypath);
|
||||
sys_searchpath = namelist_append(sys_searchpath, mypath, 0);
|
||||
#else
|
||||
verbose(0, "please manually add '%s' to your search-path!", mypath);
|
||||
#endif
|
||||
|
||||
checkVersion(mypath, filename, flags);
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
namespace gem {
|
||||
namespace plugins { void init(void); };
|
||||
namespace Settings{ void init(void); };
|
||||
};
|
||||
|
||||
namespace Gem {
|
||||
void setup()
|
||||
{
|
||||
// startup GEM
|
||||
post("GEM: Graphics Environment for Multimedia");
|
||||
verbose(-1, "GEM: ver: %s", GemVersion::versionString());
|
||||
verbose(-1, "GEM: compiled: " __DATE__);
|
||||
verbose(-1, "GEM: maintained by %s", GEM_MAINTAINER);
|
||||
verbose(-1, "GEM: Authors :\tMark Danks (original version)");
|
||||
for(unsigned int i=0; i<sizeof(GEM_AUTHORS)/sizeof(*GEM_AUTHORS); i++) {
|
||||
verbose(-1, "GEM:\t\t%s", GEM_AUTHORS[i]);
|
||||
}
|
||||
verbose(-1, "GEM: with help by %s", GEM_OTHERAUTHORS);
|
||||
verbose(-1, "GEM: found a bug? miss a feature? please report it:");
|
||||
verbose(-1, "GEM: \thomepage http://gem.iem.at/");
|
||||
verbose(-1, "GEM: \tbug-tracker http://sourceforge.net/projects/pd-gem/");
|
||||
verbose(-1, "GEM: \tmailing-list http://lists.puredata.info/listinfo/gem-dev/");
|
||||
|
||||
gem::Settings::init();
|
||||
addownpath("Gem-meta.pd");
|
||||
GemMan::initGem();
|
||||
|
||||
|
||||
// initialize some plugins
|
||||
gem::plugins::init();
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
extern "C" {
|
||||
GEM_EXTERN void Gem_setup()
|
||||
{
|
||||
Gem::setup();
|
||||
}
|
||||
|
||||
GEM_EXTERN void gem_setup()
|
||||
{
|
||||
Gem_setup();
|
||||
}
|
||||
|
||||
GEM_EXTERN void GEM_setup()
|
||||
{
|
||||
Gem_setup();
|
||||
}
|
||||
|
||||
} // for extern"C"
|
||||
336
Gem/src/Gem/State.cpp
Normal file
336
Gem/src/Gem/State.cpp
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1999 Mark Danks.
|
||||
// Copyright (c) Günther Geiger.
|
||||
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
//
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include "State.h"
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
/* for GemMan::StackIDs */
|
||||
#include "Gem/Manager.h"
|
||||
#include "Gem/GLStack.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined _MSC_VER
|
||||
/* disable deprecated warnings */
|
||||
# pragma warning( disable : 4996 )
|
||||
#endif
|
||||
|
||||
#define CATCH_ANY(y) catch(gem::bad_any_cast&x) { ::verbose(3, "%s:%d [%s] %d:: %s", __FILE__, __LINE__, __FUNCTION__, (y), x.what().c_str()); }
|
||||
|
||||
using namespace gem;
|
||||
|
||||
class GemStateData {
|
||||
friend class GemState;
|
||||
public:
|
||||
GemStateData(void) : stacks(new GLStack()){}
|
||||
|
||||
~GemStateData(void) {
|
||||
if (NULL==stacks.get()){
|
||||
post("ouch");
|
||||
// const GLStack*dummy=new GLStack();
|
||||
//stacks=dummy;
|
||||
stacks.reset();
|
||||
post("yaroooo!");
|
||||
}
|
||||
}
|
||||
|
||||
GemStateData& copyFrom(const GemStateData*org) {
|
||||
data=org->data;
|
||||
stacks->reset();
|
||||
return (*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
// dictionary for setting values
|
||||
std::map <GemState::key_t, any> data;
|
||||
|
||||
std::auto_ptr<GLStack>stacks;
|
||||
|
||||
static std::map <std::string, int> keys;
|
||||
};
|
||||
std::map <std::string, int> GemStateData::keys;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// GemState
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
GemState :: GemState()
|
||||
: dirty(0), inDisplayList(0), lighting(0), smooth(0), texture(0),
|
||||
image(0), texCoords(0), numTexCoords(0), multiTexUnits(0),
|
||||
tickTime(50.f), drawType(0),
|
||||
VertexDirty(0),
|
||||
VertexArray(0), VertexArraySize(0), VertexArrayStride(0),
|
||||
ColorArray(0), HaveColorArray(0),
|
||||
NormalArray(0), HaveNormalArray(0),
|
||||
TexCoordArray(0), HaveTexCoordArray(0),
|
||||
data(new GemStateData())
|
||||
{
|
||||
|
||||
// std::cout << "GemState" << std::endl;
|
||||
|
||||
stackDepth[GemMan::STACKMODELVIEW]=
|
||||
stackDepth[GemMan::STACKCOLOR]=
|
||||
stackDepth[GemMan::STACKTEXTURE]=
|
||||
stackDepth[GemMan::STACKPROJECTION]=
|
||||
1; // 1 is the current matrix
|
||||
|
||||
set(_DIRTY, (dirty=false));
|
||||
set(_GL_DISPLAYLIST, (inDisplayList=false));
|
||||
|
||||
set(_GL_LIGHTING, (lighting=false));
|
||||
set(_GL_SMOOTH, (smooth=false));
|
||||
set(_GL_TEX_TYPE, (texture=0));
|
||||
// set(_PIX, (image=0));
|
||||
set(_GL_TEX_NUMCOORDS, (numTexCoords=0)); // LATER get rid of this
|
||||
set(_GL_TEX_COORDS, (texCoords=0)); // LATER make this a std::vector
|
||||
set(_GL_TEX_UNITS, (multiTexUnits=0));
|
||||
set(_TIMING_TICK, (tickTime=50.f));
|
||||
set(_GL_DRAWTYPE, (drawType=0));
|
||||
|
||||
set(_GL_STACKS, data->stacks.get());
|
||||
|
||||
/*
|
||||
set("vertex.array.vertex", 0);
|
||||
set("vertex.array.color", 0);
|
||||
set("vertex.array.normal", 0);
|
||||
set("vertex.array.texcoord", 0);
|
||||
*/
|
||||
}
|
||||
|
||||
GemState& GemState::operator=(const GemState&org) {
|
||||
dirty=org.dirty;
|
||||
inDisplayList=org.inDisplayList;
|
||||
lighting=org.lighting;
|
||||
smooth=org.smooth;
|
||||
texture=org.texture;
|
||||
image=org.image;
|
||||
texCoords=org.texCoords;
|
||||
numTexCoords=org.numTexCoords;
|
||||
multiTexUnits=org.multiTexUnits;
|
||||
tickTime=org.tickTime;
|
||||
drawType=org.drawType;
|
||||
VertexArray=org.VertexArray;
|
||||
VertexArraySize=org.VertexArraySize;
|
||||
VertexArrayStride=org.VertexArrayStride;
|
||||
ColorArray=org.ColorArray;
|
||||
HaveColorArray=org.HaveColorArray;
|
||||
NormalArray=org.NormalArray;
|
||||
HaveNormalArray=org.HaveNormalArray;
|
||||
TexCoordArray=org.TexCoordArray;
|
||||
HaveTexCoordArray=org.HaveTexCoordArray;
|
||||
|
||||
data->copyFrom(org.data);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
|
||||
GemState::GemState(const GemState&org) :
|
||||
dirty(org.dirty),
|
||||
inDisplayList(org.inDisplayList),
|
||||
lighting(org.lighting),
|
||||
smooth(org.smooth),
|
||||
texture(org.texture),
|
||||
image(org.image),
|
||||
texCoords(org.texCoords),
|
||||
numTexCoords(org.numTexCoords),
|
||||
multiTexUnits(org.multiTexUnits),
|
||||
tickTime(org.tickTime),
|
||||
drawType(org.drawType),
|
||||
VertexArray(org.VertexArray),
|
||||
VertexArraySize(org.VertexArraySize),
|
||||
VertexArrayStride(org.VertexArrayStride),
|
||||
ColorArray(org.ColorArray),
|
||||
HaveColorArray(org.HaveColorArray),
|
||||
NormalArray(org.NormalArray),
|
||||
HaveNormalArray(org.HaveNormalArray),
|
||||
TexCoordArray(org.TexCoordArray),
|
||||
HaveTexCoordArray(org.HaveTexCoordArray),
|
||||
data(NULL)
|
||||
{
|
||||
data->copyFrom(org.data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void GemState :: reset() {
|
||||
VertexArray = 0;
|
||||
VertexArraySize = 0;
|
||||
ColorArray = 0;
|
||||
NormalArray = 0;
|
||||
TexCoordArray = 0;
|
||||
HaveColorArray = 0;
|
||||
HaveNormalArray = 0;
|
||||
HaveTexCoordArray = 0;
|
||||
drawType = 0;
|
||||
|
||||
if(GemMan::windowExists()) {
|
||||
GLStack *stacks;
|
||||
get(GemState::_GL_STACKS, stacks);
|
||||
stacks->reset();
|
||||
}
|
||||
|
||||
set(GemState::_PIX, (image=0));
|
||||
set(GemState::_GL_TEX_NUMCOORDS, (numTexCoords=0));
|
||||
|
||||
}
|
||||
|
||||
GemState :: ~GemState() {
|
||||
if(data)delete data;data=NULL;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------
|
||||
/* legacy functions */
|
||||
float GemState::texCoordX(int num) const {
|
||||
if (texture && numTexCoords > num)
|
||||
return texCoords[num].s;
|
||||
else return 0.;
|
||||
}
|
||||
|
||||
float GemState::texCoordY(int num) const {
|
||||
if (texture && numTexCoords > num)
|
||||
return texCoords[num].t;
|
||||
else return 0.;
|
||||
}
|
||||
|
||||
|
||||
/* real properties */
|
||||
|
||||
|
||||
/* get a named property */
|
||||
bool GemState::get(const GemState::key_t key, any&value) {
|
||||
std::map<GemState::key_t,any>::iterator it =
|
||||
data->data.find(key);
|
||||
if(it==data->data.end()) {
|
||||
if(key==_PIX) { value=image; return true; }
|
||||
if(key==_GL_TEX_NUMCOORDS) { value=numTexCoords; return true; }
|
||||
|
||||
|
||||
return false; // FIXXME
|
||||
|
||||
if(key==_DIRTY) { value=dirty; return true; }
|
||||
if(key==_GL_DISPLAYLIST) { value=inDisplayList; return true; }
|
||||
|
||||
if(key==_GL_LIGHTING) { value=lighting; return true; }
|
||||
if(key==_GL_SMOOTH) { value=smooth; return true; }
|
||||
if(key==_GL_TEX_TYPE) { value=texture; return true; }
|
||||
if(key==_GL_TEX_COORDS) { if(!texCoords)return false; value=texCoords; return true; }
|
||||
if(key==_GL_TEX_UNITS) { value=multiTexUnits; return true; }
|
||||
if(key==_TIMING_TICK) { value=tickTime; return true; }
|
||||
if(key==_GL_DRAWTYPE) { value=drawType; return true; }
|
||||
|
||||
#if 0
|
||||
//if(key==GemState::_GL_STACKS) { value=stackDepth[4]; return true; }
|
||||
|
||||
if(key=="vertex.dirty") { value=VertexDirty; return true; }
|
||||
if(key=="*VertexArray") { value=*VertexArray; return true; }
|
||||
if(key=="VertexArraySize") { value=VertexArraySize; return true; }
|
||||
if(key=="VertexArrayStride") { value=VertexArrayStride; return true; }
|
||||
if(key=="*ColorArray") { value=*ColorArray; return true; }
|
||||
if(key=="HaveColorArray") { value=HaveColorArray; return true; }
|
||||
if(key=="*NormalArray") { value=*NormalArray; return true; }
|
||||
if(key=="HaveNormalArray") { value=HaveNormalArray; return true; }
|
||||
if(key=="*TexCoordArray") { value=*TexCoordArray; return true; }
|
||||
if(key=="HaveTexCoordArray") { value=HaveTexCoordArray; return true; }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
value=it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* set a named property */
|
||||
bool GemState::set(const GemState::key_t key, any value) {
|
||||
if(value.empty()) {
|
||||
data->data.erase(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* wrapper for DEPRECATED access to member variables */
|
||||
if(1) {
|
||||
try {
|
||||
switch(key) {
|
||||
case(_DIRTY): dirty=gem::any_cast<bool>(value); break;
|
||||
case(_PIX): image=gem::any_cast<pixBlock*>(value); break;
|
||||
case(_GL_TEX_NUMCOORDS): numTexCoords=gem::any_cast<int>(value); break;
|
||||
case(_GL_TEX_COORDS): texCoords=gem::any_cast<TexCoord*>(value); break;
|
||||
case(_GL_LIGHTING): lighting=gem::any_cast<bool>(value); break;
|
||||
case(_GL_SMOOTH): smooth=gem::any_cast<bool>(value); break;
|
||||
case(_GL_TEX_TYPE): texture=gem::any_cast<int>(value); break;
|
||||
case(_GL_TEX_UNITS): multiTexUnits=gem::any_cast<int>(value); break;
|
||||
case(_TIMING_TICK): tickTime=gem::any_cast<float>(value); break;
|
||||
case(_GL_DRAWTYPE): drawType=gem::any_cast<GLenum>(value); break;
|
||||
case(_GL_DISPLAYLIST): inDisplayList=gem::any_cast<bool>(value); break;
|
||||
default: break;
|
||||
}
|
||||
} CATCH_ANY(key);
|
||||
}
|
||||
data->data[key]=value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* remove a named property */
|
||||
bool GemState::remove(const GemState::key_t key) {
|
||||
return (0!=data->data.erase(key));
|
||||
}
|
||||
|
||||
const GemState::key_t GemState::getKey(const std::string&s) {
|
||||
if(GemStateData::keys.empty()) {
|
||||
GemStateData::keys["dirty"]=_DIRTY;
|
||||
GemStateData::keys["timing.tick"]=_TIMING_TICK;
|
||||
GemStateData::keys["pix"]=_PIX;
|
||||
GemStateData::keys["gl.stacks"]=_GL_STACKS;
|
||||
GemStateData::keys["gl.displaylist"]=_GL_DISPLAYLIST;
|
||||
GemStateData::keys["gl.lighting"]=_GL_LIGHTING;
|
||||
GemStateData::keys["gl.smooth"]=_GL_SMOOTH;
|
||||
GemStateData::keys["gl.drawtype"]=_GL_DRAWTYPE;
|
||||
GemStateData::keys["gl.tex.type"]=_GL_TEX_TYPE;
|
||||
GemStateData::keys["gl.tex.coords"]=_GL_TEX_COORDS;
|
||||
GemStateData::keys["gl.tex.numcoords"]=_GL_TEX_NUMCOORDS;
|
||||
GemStateData::keys["gl.tex.units"]=_GL_TEX_UNITS;
|
||||
GemStateData::keys["gl.tex.orientation"]=_GL_TEX_ORIENTATION;
|
||||
GemStateData::keys["gl.tex.basecoord"]=_GL_TEX_BASECOORD;
|
||||
}
|
||||
|
||||
key_t result=_ILLEGAL;
|
||||
|
||||
std::map<std::string, int>::iterator it = GemStateData::keys.find(s);
|
||||
|
||||
if(it == GemStateData::keys.end()) {
|
||||
result=(key_t)it->second;
|
||||
} else {
|
||||
result=(key_t)GemStateData::keys.size();
|
||||
GemStateData::keys[s]=result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
231
Gem/src/Gem/State.h
Normal file
231
Gem/src/Gem/State.h
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*-----------------------------------------------------------------
|
||||
LOG
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
The state to pass among GEM objects
|
||||
|
||||
Copyright (c) 1997-2000 Mark Danks. mark@danks.org
|
||||
Copyright (c) Günther Geiger. geiger@epy.co.at
|
||||
Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE__GEM_GEM_STATE_H_
|
||||
#define _INCLUDE__GEM_GEM_STATE_H_
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
#include "Gem/GemGL.h"
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
#include "Utils/any.h"
|
||||
|
||||
struct pixBlock;
|
||||
class TexCoord;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
TexCoord
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
class GEM_EXTERN TexCoord
|
||||
{
|
||||
public:
|
||||
TexCoord() : s(0.f), t(0.f) { }
|
||||
TexCoord(float s_, float t_) : s(s_), t(t_) { }
|
||||
float s;
|
||||
float t;
|
||||
};
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
GemState
|
||||
|
||||
The state to pass among GEM objects
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
class GemStateData;
|
||||
class GEM_EXTERN GemState
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
_ILLEGAL=-1,
|
||||
_DIRTY, /* "dirty" */
|
||||
_TIMING_TICK, /* "timing.tick" */
|
||||
_PIX, /* "pix" */
|
||||
_GL_STACKS, /* "stacks" */
|
||||
_GL_DISPLAYLIST, /* */
|
||||
_GL_LIGHTING, /* */
|
||||
_GL_SMOOTH, /* */
|
||||
_GL_DRAWTYPE, /* */
|
||||
_GL_TEX_TYPE, /* "tex.type" */
|
||||
_GL_TEX_COORDS, /* "tex.coords" */
|
||||
_GL_TEX_NUMCOORDS, /* "tex.numcoords" */
|
||||
_GL_TEX_UNITS, /* "tex.units" <int> # of texUnits */
|
||||
_GL_TEX_ORIENTATION, /* "tex.orientation" <bool> false=bottomleft; true=topleft */
|
||||
_GL_TEX_BASECOORD, /* "tex.basecoords" <TexCoord> width/height of texture */
|
||||
|
||||
|
||||
|
||||
|
||||
_LAST
|
||||
} key_t;
|
||||
|
||||
//////////
|
||||
// Has something changed since the last time?
|
||||
// deprecated: use property 'dirty' instead
|
||||
GEM_DEPRECATED bool dirty;
|
||||
|
||||
//////////
|
||||
// Are we in a display list creation?
|
||||
// deprecated: use property 'gl.displaylist' instead
|
||||
GEM_DEPRECATED bool inDisplayList;
|
||||
|
||||
//////////
|
||||
// Lighting on?
|
||||
// deprecated: use property 'gl.lighting' instead
|
||||
GEM_DEPRECATED bool lighting;
|
||||
|
||||
//////////
|
||||
// Smooth shading (flat is other type)
|
||||
// deprecated: use property 'gl.smooth' instead
|
||||
GEM_DEPRECATED bool smooth;
|
||||
|
||||
//////////
|
||||
// Texture mapping on?
|
||||
// 0..off
|
||||
// 1..normalized texture
|
||||
// 2..rectangle texture
|
||||
// deprecated: use property 'gl.tex.type' instead
|
||||
GEM_DEPRECATED int texture;
|
||||
|
||||
//////////
|
||||
// The image to texture map
|
||||
// deprecated: use property 'pix' instead
|
||||
GEM_DEPRECATED pixBlock *image;
|
||||
|
||||
//////////
|
||||
// Texture coordinates.
|
||||
// This can be NULL if there aren't any coordinates
|
||||
// deprecated: use property 'gl.tex.coords' instead
|
||||
GEM_DEPRECATED TexCoord *texCoords;
|
||||
|
||||
//////////
|
||||
// The number of TexCoords
|
||||
// deprecated: use property 'gl.tex.numcoords' instead
|
||||
GEM_DEPRECATED int numTexCoords;
|
||||
|
||||
//////////
|
||||
// The number of multiTexUnits
|
||||
// default = 0, max = 7
|
||||
// deprecated: use property 'gl.tex.units' instead
|
||||
GEM_DEPRECATED int multiTexUnits;
|
||||
|
||||
//////////
|
||||
// Milliseconds since last frame
|
||||
// If in Stereoscopic mode, then it is the same number for both left
|
||||
// and right renderings
|
||||
// deprecated: use property 'timing.tick' instead
|
||||
GEM_DEPRECATED float tickTime;
|
||||
|
||||
//////////////////
|
||||
// the default draw-type (might be overridden within a Geo)
|
||||
// deprecated: use property 'gl.drawtype' instead
|
||||
GEM_DEPRECATED GLenum drawType;
|
||||
|
||||
//////////
|
||||
// how deep is the current stack /* 4 fields for the 4 stacks */
|
||||
// deprecated: use property 'gl.stacks' instead
|
||||
GEM_DEPRECATED int stackDepth[4];
|
||||
|
||||
////////////
|
||||
//vertex-array data
|
||||
// deprecated: use property 'vertex.dirty' instead
|
||||
GEM_DEPRECATED int VertexDirty; // the vertex-arrays has changed
|
||||
// deprecated: use property 'vertex.array.vertex' instead
|
||||
GEM_DEPRECATED GLfloat *VertexArray;
|
||||
// deprecated: use property 'vertex.array.vertex' instead
|
||||
GEM_DEPRECATED int VertexArraySize;
|
||||
// deprecated: use property 'vertex.array.vertex' instead
|
||||
GEM_DEPRECATED int VertexArrayStride;
|
||||
|
||||
// deprecated: use property 'vertex.array.color' instead
|
||||
GEM_DEPRECATED GLfloat *ColorArray;
|
||||
// deprecated: use property 'vertex.array.color' instead
|
||||
GEM_DEPRECATED bool HaveColorArray;
|
||||
|
||||
// deprecated: use property 'vertex.array.normal' instead
|
||||
GEM_DEPRECATED GLfloat *NormalArray;
|
||||
// deprecated: use property 'vertex.array.normal' instead
|
||||
GEM_DEPRECATED bool HaveNormalArray;
|
||||
|
||||
// deprecated: use property 'vertex.array.texcoord' instead
|
||||
GEM_DEPRECATED GLfloat *TexCoordArray;
|
||||
// deprecated: use property 'vertex.array.texcoord' instead
|
||||
GEM_DEPRECATED bool HaveTexCoordArray;
|
||||
|
||||
//////////
|
||||
// Constructor
|
||||
GemState(void);
|
||||
GemState(const GemState&);
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~GemState(void);
|
||||
|
||||
float texCoordX(int num) const;
|
||||
|
||||
float texCoordY(int num) const;
|
||||
|
||||
/* reset (parts of?) the GemState: to be called from [gemhead] */
|
||||
void reset(void);
|
||||
|
||||
|
||||
/* get a named property */
|
||||
/* if the property exists (as the given type),
|
||||
* the value of the 2nd argument is set accordingly and <code>true</code> is returned
|
||||
* if the key does not exist (or the type is wrong) the value is not touched and <code>false</code> is returned instead
|
||||
*/
|
||||
virtual bool get(const key_t key, gem::any&value);
|
||||
|
||||
template<class T>
|
||||
bool get(const key_t key, T&value) {
|
||||
try {
|
||||
gem::any val;
|
||||
if(!get(key,val)) {
|
||||
// key not found
|
||||
return false;
|
||||
}
|
||||
value=gem::any_cast<T>(val);
|
||||
return true;
|
||||
} catch (gem::bad_any_cast&x) {
|
||||
::verbose(3, "%s:%d [%s] %d :: %s", __FILE__, __LINE__, __FUNCTION__, key, x.what().c_str());
|
||||
// type problem
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/* set a named property */
|
||||
virtual bool set(const key_t key, gem::any value);
|
||||
/* remove a named property */
|
||||
virtual bool remove(const key_t key);
|
||||
|
||||
// Copy assignment
|
||||
GemState& operator=(const GemState&);
|
||||
|
||||
static const key_t getKey(const std::string&);
|
||||
|
||||
protected:
|
||||
GemStateData*data;
|
||||
};
|
||||
|
||||
#endif // for header file
|
||||
19
Gem/src/Gem/Version.h
Normal file
19
Gem/src/Gem/Version.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef GEM_VERSION_H
|
||||
#define GEM_VERSION_H
|
||||
|
||||
#include "Gem/ExportDef.h"
|
||||
|
||||
#define GEM_VERSION_MAJOR 0
|
||||
#define GEM_VERSION_MINOR 93
|
||||
|
||||
namespace gem {
|
||||
class GEM_EXTERN Version {
|
||||
public:
|
||||
const static char* versionString(void);
|
||||
static bool versionCheck(int major, int minor);
|
||||
}; };
|
||||
|
||||
#define GemVersion gem::Version
|
||||
|
||||
#endif
|
||||
|
||||
12
Gem/src/Gem/configDarwin.h
Normal file
12
Gem/src/Gem/configDarwin.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/* Gem/configDarwin.h. Generated by configure. */
|
||||
|
||||
/* font rendering */
|
||||
#define HAVE_LIBFTGL 1
|
||||
|
||||
/* image loading / saving */
|
||||
/* #undef HAVE_LIBMAGICKPLUSPLUS */
|
||||
|
||||
/* types, structures, compiler characteristics, ... */
|
||||
#define SIZEOF_VOID_P 4
|
||||
#define SIZEOF_UNSIGNED_INT 4
|
||||
|
||||
2
Gem/src/Gem/configLinux.h
Normal file
2
Gem/src/Gem/configLinux.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/* configLinux.h : dummy file to be included if there is no autoconf-generated config.h file */
|
||||
|
||||
9
Gem/src/Gem/configNT.h
Normal file
9
Gem/src/Gem/configNT.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* configuration for Windows M$VC
|
||||
*
|
||||
* this file should get included if _MSC_VER is defined
|
||||
* for default-defines on _MSC_VER see
|
||||
* see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_predir_predefined_macros.asp for available macros
|
||||
*
|
||||
*
|
||||
* this file is empty as all the settings are done via property pages
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue