godot/drivers/theoraplayer/src/TheoraAsync.cpp
Juan Linietsky 8cab401d08 3D Physics Rework, Other Stuff
-=-=-=-=-=-=-=-=-=-=-=-=-=-

3D Physics:
-Fixed "Bounce" parameter in 3D
-Fixed bug affecting Area (sometims it would not detect properly)
-Vehicle Body has seen heavy work
-Added Query API for doing space queries in 3D. Needs some docs though.
-Added JOINTS! Adapted Bullet Joints: and created easy gizmos for setting them up:
   -PinJoint
   -HingeJoint (with motor)
   -SliderJoint
   -ConeTwistJoint
   -Generic6DOFJoint
-Added OBJECT PICKING! based on the new query API. Any physics object now (Area or Body) has the following signals and virtual functions:
    -input_event (mouse or multitouch input over the body)
    -mouse_enter (mouse entered the body area)
    -mouse_exit (mouse exited body area)
   For Area it needs to be activated manually, as it isn't by default (ray goes thru).

Other:

-Begun working on Windows 8 (RT) port. Compiles but does not work yet.
-Added TheoraPlayer library for improved to-texture and portable video support.
-Fixed a few bugs in the renderer, collada importer, collada exporter, etc.
2014-09-15 11:33:30 -03:00

254 lines
4.8 KiB
C++

/************************************************************************************
This source file is part of the Theora Video Playback Library
For latest info, see http://libtheoraplayer.googlecode.com
*************************************************************************************
Copyright (c) 2008-2014 Kresimir Spes (kspes@cateia.com)
This program is free software; you can redistribute it and/or modify it under
the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause
*************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <pthread.h>
#endif
#include "TheoraAsync.h"
#include "TheoraUtil.h"
#ifdef _WINRT
#include <wrl.h>
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
// Mutex
///////////////////////////////////////////////////////////////////////////////////////////////////
TheoraMutex::TheoraMutex()
{
#ifdef _WIN32
#ifndef _WINRT // WinXP does not have CreateTheoraMutexEx()
mHandle = CreateMutex(0, 0, 0);
#else
mHandle = CreateMutexEx(NULL, NULL, 0, SYNCHRONIZE);
#endif
#else
mHandle = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init((pthread_mutex_t*)mHandle, 0);
#endif
}
TheoraMutex::~TheoraMutex()
{
#ifdef _WIN32
CloseHandle(mHandle);
#else
pthread_mutex_destroy((pthread_mutex_t*)mHandle);
free((pthread_mutex_t*)mHandle);
mHandle = NULL;
#endif
}
void TheoraMutex::lock()
{
#ifdef _WIN32
WaitForSingleObjectEx(mHandle, INFINITE, FALSE);
#else
pthread_mutex_lock((pthread_mutex_t*)mHandle);
#endif
}
void TheoraMutex::unlock()
{
#ifdef _WIN32
ReleaseMutex(mHandle);
#else
pthread_mutex_unlock((pthread_mutex_t*)mHandle);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Thread
///////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _WINRT
using namespace Windows::Foundation;
using namespace Windows::System::Threading;
#endif
#ifdef _WIN32
unsigned long WINAPI theoraAsyncCall(void* param)
#else
void* theoraAsyncCall(void* param)
#endif
{
TheoraThread* t = (TheoraThread*)param;
t->execute();
#ifdef _WIN32
return 0;
#else
pthread_exit(NULL);
return NULL;
#endif
}
#ifdef _WINRT
struct TheoraAsyncActionWrapper
{
public:
IAsyncAction^ mAsyncAction;
TheoraAsyncActionWrapper(IAsyncAction^ asyncAction)
{
mAsyncAction = asyncAction;
}
};
#endif
TheoraThread::TheoraThread() : mRunning(false), mId(0)
{
#ifndef _WIN32
mId = (pthread_t*)malloc(sizeof(pthread_t));
#endif
}
TheoraThread::~TheoraThread()
{
if (mRunning)
{
stop();
}
if (mId != NULL)
{
#ifdef _WIN32
#ifndef _WINRT
CloseHandle(mId);
#else
delete mId;
#endif
#else
free((pthread_t*)mId);
#endif
mId = NULL;
}
}
void TheoraThread::start()
{
mRunning = true;
#ifdef _WIN32
#ifndef _WINRT
mId = CreateThread(0, 0, &theoraAsyncCall, this, 0, 0);
#else
mId = new TheoraAsyncActionWrapper(ThreadPool::RunAsync(
ref new WorkItemHandler([&](IAsyncAction^ work_item)
{
execute();
}),
WorkItemPriority::Normal, WorkItemOptions::TimeSliced));
#endif
#else
pthread_create((pthread_t*)mId, NULL, &theoraAsyncCall, this);
#endif
}
bool TheoraThread::isRunning()
{
bool ret;
mRunningMutex.lock();
ret = mRunning;
mRunningMutex.unlock();
return ret;
}
void TheoraThread::join()
{
mRunningMutex.lock();
mRunning = false;
mRunningMutex.unlock();
#ifdef _WIN32
#ifndef _WINRT
WaitForSingleObject(mId, INFINITE);
if (mId != NULL)
{
CloseHandle(mId);
mId = NULL;
}
#else
IAsyncAction^ action = ((TheoraAsyncActionWrapper*)mId)->mAsyncAction;
int i = 0;
while (action->Status != AsyncStatus::Completed &&
action->Status != AsyncStatus::Canceled &&
action->Status != AsyncStatus::Error &&
i < 100)
{
_psleep(50);
++i;
}
if (i >= 100)
{
i = 0;
action->Cancel();
while (action->Status != AsyncStatus::Completed &&
action->Status != AsyncStatus::Canceled &&
action->Status != AsyncStatus::Error &&
i < 100)
{
_psleep(50);
++i;
}
}
#endif
#else
pthread_join(*((pthread_t*)mId), 0);
#endif
}
void TheoraThread::resume()
{
#ifdef _WIN32
#ifndef _WINRT
ResumeThread(mId);
#else
// not available in WinRT
#endif
#endif
}
void TheoraThread::pause()
{
#ifdef _WIN32
#ifndef _WINRT
SuspendThread(mId);
#else
// not available in WinRT
#endif
#endif
}
void TheoraThread::stop()
{
if (mRunning)
{
mRunningMutex.lock();
mRunning = false;
mRunningMutex.unlock();
#ifdef _WIN32
#ifndef _WINRT
TerminateThread(mId, 0);
#else
((TheoraAsyncActionWrapper*)mId)->mAsyncAction->Cancel();
#endif
#elif defined(_ANDROID)
pthread_kill(*((pthread_t*)mId), 0);
#else
pthread_cancel(*((pthread_t*)mId));
#endif
}
}