#include "stdafx.h"
#include "sdl_application_intf.h"
#include "sdl_application.h"
#include <future>
cSDLAppService);
#define LIMIT_FRAMERATE true
#define RECTS_PER_SECOND 5000
{
{
adtf::streaming::tStreamImageFormat::operator=(oCopyFrom);
return *this;
}
uint32_t Rmask = 0;
uint32_t Gmask = 0;
uint32_t Bmask = 0;
uint32_t Amask = 0;
unsigned int nBitsPerPixel = 0;
};
tInternalFormat& sFormatToSet)
{
sFormatToSet = sFormat;
{
if (!stream_image_format_is_generic_greyscale(sFormat))
{
}
{
}
sFormatToSet.Rmask = 0xFF;
sFormatToSet.Gmask = 0xFF;
sFormatToSet.Bmask = 0xFF;
sFormatToSet.Amask = 0xFF;
sFormatToSet.nBitsPerPixel = 8;
}
}
class cSDLDrawRect : public ISDLApplication::ISDLCanvas
{
SDL_Surface* m_pGlobalScreen;
ISDLApplication::ISDLDrawer* m_pDrawerRef;
tInternalFormat m_sCurrentFormat;
protected:
cSDLDrawRect() = default;
public:
cSDLDrawRect(SDL_Surface* pSurface, ISDLApplication::ISDLDrawer& oDrawer)
{
m_pGlobalScreen = pSurface;
m_pDrawerRef = &oDrawer;
}
bool Check(ISDLApplication::ISDLDrawer& oDrawer)
{
return (m_pDrawerRef == &oDrawer);
}
const void* pData, size_t ) override
{
if (m_sCurrentFormat != sFormat)
{
}
SDL_Surface* pSurface = NULL;
void* pDataNonConst = const_cast<void*>(pData);
pSurface = SDL_CreateRGBSurfaceFrom(
pDataNonConst,
m_sCurrentFormat.m_ui32Width,
m_sCurrentFormat.m_ui32Height,
m_sCurrentFormat.nBitsPerPixel,
static_cast<int>(m_sCurrentFormat.m_szMaxByteSize) / m_sCurrentFormat.m_ui32Height,
m_sCurrentFormat.Rmask, m_sCurrentFormat.Gmask, m_sCurrentFormat.Bmask, m_sCurrentFormat.Amask);
if (nullptr == pSurface)
{
}
SDL_Rect rectDest;
rectDest.x = rectDest.y = 0;
constexpr auto dest_type_min = std::numeric_limits<decltype(rectDest.w)>::min();
constexpr auto dest_type_max = std::numeric_limits<decltype(rectDest.w)>::max();
(void)dest_type_min;
(void)dest_type_max;
assert(m_pGlobalScreen->w >= dest_type_min && m_pGlobalScreen->w <= dest_type_max);
assert(m_pGlobalScreen->h >= dest_type_min && m_pGlobalScreen->h <= dest_type_max);
rectDest.w = static_cast<Uint16>(m_pGlobalScreen->w);
rectDest.h = static_cast<Uint16>(m_pGlobalScreen->h);
SDL_BlitSurface(pSurface, &rectDest, m_pGlobalScreen, &m_pGlobalScreen->clip_rect);
SDL_UpdateRects(m_pGlobalScreen, 1, &rectDest);
SDL_FreeSurface(pSurface);
}
{
}
};
class cSDLAppService::cSDLAppServicePrivate : public adtf_util::d_ptr_impl<cSDLAppService, cSDLAppService::cSDLAppServicePrivate>
{
friend class cSDLAppService;
protected:
std::vector<cSDLDrawRect*> m_lstDrawRects;
SDL_Surface* m_pScreen = nullptr;
std::atomic_bool m_bExit;
std::recursive_mutex m_oListSynch;
};
cSDLAppService::cSDLAppService()
{
_d->m_bExit = false;
m_ui32SetWidth.SetDescription("Specified width for Sample dimension.");
RegisterPropertyVariable("width", m_ui32SetWidth);
m_ui32SetHeight.SetDescription("Specified height for Sample dimension.");
RegisterPropertyVariable("height", m_ui32SetHeight);
m_ui32PixelDepth.SetDescription("The bit depth in pixel.");
RegisterPropertyVariable("pixel", m_ui32PixelDepth);
SetDescription("Use this System Service to provide a simple graphics application based on SDL.");
SetHelpLink("$(ADTF_DIR)/doc/adtf_html/page_demo_sdl_application.html");
}
tResult cSDLAppService::ServiceInit()
{
srand( (unsigned)time( NULL ) );
if (0 != SDL_Init(SDL_INIT_VIDEO))
{
}
_d->m_pScreen = SDL_SetVideoMode(m_ui32SetWidth, m_ui32SetHeight, m_ui32PixelDepth, 0);
if (nullptr == _d->m_pScreen)
{
}
SDL_WM_SetCaption("ADTF SDL Demo Application", NULL);
}
tResult cSDLAppService::ServiceShutdown()
{
SDL_Quit();
}
{
_d->m_bExit = true;
}
{
if (pClock)
{
}
else
{
return adtf_util::cSystem::GetTime();
}
}
struct tJobAndPromise
{
std::unique_ptr<std::promise<void>> pFinished;
};
{
if (nullptr == _d->m_pScreen)
{
}
object_ptr<adtf::services::IReferenceClock> pClock;
SDL_Event sEvent;
tTimeStamp tmLastUpdate = get_current_time(pClock.Get());
tTimeStamp tmFrameCount = get_current_time(pClock.Get());
int nFrameCount = 0;
_d->m_bExit = false;
while (!_d->m_bExit)
{
while (0 != SDL_PollEvent(&sEvent) && !_d->m_bExit)
{
switch (sEvent.type)
{
case SDL_MOUSEBUTTONDOWN:
{
LOG_INFO(adtf_util::cString::Format(
"mouse down' ").GetPtr());
break;
}
case SDL_KEYDOWN:
{
LOG_INFO(adtf_util::cString::Format(
"pressed key '%s' ", SDL_GetKeyName(sEvent.key.keysym.sym)).GetPtr());
break;
}
case SDL_QUIT:
{
_d->m_bExit = true;
break;
}
case SDL_USEREVENT:
{
if (sEvent.user.code == 1)
{
auto pJobAndFuture = static_cast<tJobAndPromise*>(sEvent.user.data1);
pJobAndFuture->pJob->Run(get_current_time(pClock.Get()), IRunnable::RUN_JOB, nullptr, 0);
sEvent.user.data1 = nullptr;
if (pJobAndFuture->pFinished)
{
pJobAndFuture->pFinished->set_value();
}
else
{
delete pJobAndFuture;
}
}
break;
}
default:
break;
}
}
if (!_d->m_bExit)
{
tmCurrent = get_current_time(pClock.Get());
tmElapsed = tmCurrent-tmLastUpdate;
Paint();
SDL_Flip(_d->m_pScreen);
tmLastUpdate = tmCurrent;
if (LIMIT_FRAMERATE && tmElapsed < 10000)
{
adtf_util::cSystem::Sleep(10000 - tmElapsed);
}
nFrameCount++;
if (tmCurrent - tmFrameCount >= 1000000)
{
nFrameCount = 0;
tmFrameCount = tmCurrent;
}
}
}
}
{
SDL_Event user_event;
auto pJobAndFuture = new tJobAndPromise;
pJobAndFuture->pJob = pJob;
if (bWait)
{
pJobAndFuture->pFinished.reset(new std::promise<void>());
}
user_event.type = SDL_USEREVENT;
user_event.user.code = 1;
user_event.user.data1 = pJobAndFuture;
user_event.user.data2 = nullptr;
int nRes = SDL_PushEvent(&user_event);
if (nRes != 0)
{
delete pJobAndFuture;
}
if (bWait)
{
pJobAndFuture->pFinished->get_future().wait();
delete pJobAndFuture;
}
}
tResult cSDLAppService::RegisterSDLDrawer(ISDLDrawer& oDrawer)
{
_d->m_oListSynch.lock();
if (_d->m_lstDrawRects.size() > 0)
{
}
cSDLDrawRect* pDrawRect = new cSDLDrawRect(_d->m_pScreen, oDrawer);
_d->m_lstDrawRects.push_back(pDrawRect);
_d->m_oListSynch.unlock();
}
tResult cSDLAppService::UnregisterSDLDrawer(ISDLDrawer& oDrawer)
{
_d->m_oListSynch.lock();
for (std::vector<cSDLDrawRect*>::iterator it = _d->m_lstDrawRects.begin();
it != _d->m_lstDrawRects.end();
it++)
{
if ((*it)->Check(oDrawer))
{
_d->m_lstDrawRects.erase(it);
_d->m_oListSynch.unlock();
}
}
_d->m_oListSynch.unlock();
}
{
std::lock_guard<std::recursive_mutex> oG(_d->m_oListSynch);
for (auto it : _d->m_lstDrawRects)
{
(*it).Paint();
}
}
#define ADTF_PLUGIN(__plugin_identifier,...)
The ADTF Plugin Macro will add the code of a adtf::ucom::ant::IPlugin implementation.
#define LOG_INFO(...)
Logs an info message.
tInt64 tTimeStamp
type definition for a time value.
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
#define RETURN_IF_FAILED(s)
Return if expression is failed, which requires the calling function's return type to be tResult.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
#define RETURN_ERROR(code)
Return specific error code, which requires the calling function's return type to be tResult.
virtual tTimeStamp GetTime() const =0
Retrieves the current reference time.
virtual tResult GetObject(iobject_ptr< IObject > &pObject, const char *strNameOID) const =0
Get registered object from object registry.
Object pointer implementation used for reference counting on objects of type IObject.
#define A_UTILS_D_CREATE(__classname_)
helper macro for d-pattern usage.
uint32_t stream_image_format_get_generic_mask(const char *strChannel, const tStreamImageFormat &strFormat)
Retrieves the pixelsize by a Generic Pixel Format.
bool stream_image_format_is_generic_rgb(const tStreamImageFormat &strFormat)
Check if R, G and B components are available in Generic Pixel Format.
unsigned int stream_image_format_get_generic_pixel_size(const tStreamImageFormat &strFormat)
Retrieves the pixelsize by a Generic Pixel Format.
Namespace for the ADTF Streaming SDK.
adtf::ucom::IRuntime * _runtime
Global Runtime Pointer to reference to the current runtime.