From c285c99b53bd2a98694598b5baac722de6593250 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 24 Jun 2007 18:26:35 +0000 Subject: [PATCH] Added S60 port. --- README.Symbian | 32 + docs.html | 3 + include/SDL_config.h.default | 2 + include/SDL_config.h.in | 3 - include/SDL_config_symbian.h | 146 ++ include/SDL_stdinc.h | 2 + include/SDL_thread.h | 2 +- include/begin_code.h | 10 +- src/SDL.c | 2 +- src/audio/SDL_audio.c | 5 +- src/audio/SDL_sysaudio.h | 3 + src/audio/symbian/SDL_epocaudio.cpp | 614 +++++++++ src/audio/symbian/SDL_epocaudio.h | 37 + src/audio/symbian/streamplayer.cpp | 279 ++++ src/audio/symbian/streamplayer.h | 89 ++ src/events/SDL_events.c | 2 +- src/file/SDL_rwops.c | 4 +- src/main/symbian/EKA1/SDL_main.cpp | 152 +++ src/main/symbian/EKA2/SDL_main.cpp | 1035 ++++++++++++++ src/main/symbian/EKA2/sdlexe.cpp | 809 +++++++++++ src/main/symbian/EKA2/sdllib.cpp | 12 + src/main/symbian/EKA2/vectorbuffer.cpp | 62 + src/main/symbian/EKA2/vectorbuffer.h | 240 ++++ src/stdlib/SDL_getenv.c | 2 +- src/thread/SDL_thread_c.h | 4 +- src/thread/symbian/SDL_sysmutex.cpp | 130 ++ src/thread/symbian/SDL_syssem.cpp | 214 +++ src/thread/symbian/SDL_systhread.cpp | 146 ++ src/thread/symbian/SDL_systhread_c.h | 30 + src/timer/symbian/SDL_systimer.cpp | 114 ++ src/video/symbian/EKA1/SDL_epocevents.cpp | 626 +++++++++ src/video/symbian/EKA1/SDL_epocvideo.cpp | 1356 +++++++++++++++++++ src/video/symbian/EKA1/SDL_epocvideo.h | 34 + src/video/symbian/EKA2/SDL_epocevents.cpp | 521 +++++++ src/video/symbian/EKA2/SDL_epocvideo.cpp | 594 ++++++++ src/video/symbian/EKA2/SDL_epocvideo.h | 51 + src/video/symbian/EKA2/dsa.cpp | 1504 +++++++++++++++++++++ src/video/symbian/EKA2/dsa_new.cpp | 1443 ++++++++++++++++++++ src/video/symbian/EKA2/dsa_old.cpp | 1075 +++++++++++++++ src/video/symbian/SDL_epocevents_c.h | 60 + 40 files changed, 11434 insertions(+), 15 deletions(-) create mode 100644 README.Symbian create mode 100644 include/SDL_config_symbian.h create mode 100644 src/audio/symbian/SDL_epocaudio.cpp create mode 100644 src/audio/symbian/SDL_epocaudio.h create mode 100644 src/audio/symbian/streamplayer.cpp create mode 100644 src/audio/symbian/streamplayer.h create mode 100644 src/main/symbian/EKA1/SDL_main.cpp create mode 100644 src/main/symbian/EKA2/SDL_main.cpp create mode 100644 src/main/symbian/EKA2/sdlexe.cpp create mode 100644 src/main/symbian/EKA2/sdllib.cpp create mode 100644 src/main/symbian/EKA2/vectorbuffer.cpp create mode 100644 src/main/symbian/EKA2/vectorbuffer.h create mode 100644 src/thread/symbian/SDL_sysmutex.cpp create mode 100644 src/thread/symbian/SDL_syssem.cpp create mode 100644 src/thread/symbian/SDL_systhread.cpp create mode 100644 src/thread/symbian/SDL_systhread_c.h create mode 100644 src/timer/symbian/SDL_systimer.cpp create mode 100644 src/video/symbian/EKA1/SDL_epocevents.cpp create mode 100644 src/video/symbian/EKA1/SDL_epocvideo.cpp create mode 100644 src/video/symbian/EKA1/SDL_epocvideo.h create mode 100644 src/video/symbian/EKA2/SDL_epocevents.cpp create mode 100644 src/video/symbian/EKA2/SDL_epocvideo.cpp create mode 100644 src/video/symbian/EKA2/SDL_epocvideo.h create mode 100644 src/video/symbian/EKA2/dsa.cpp create mode 100644 src/video/symbian/EKA2/dsa_new.cpp create mode 100644 src/video/symbian/EKA2/dsa_old.cpp create mode 100644 src/video/symbian/SDL_epocevents_c.h diff --git a/README.Symbian b/README.Symbian new file mode 100644 index 000000000..d1f2a4ae0 --- /dev/null +++ b/README.Symbian @@ -0,0 +1,32 @@ +============================================================================== +Using the Simple DirectMedia Layer with S60 3.x / Symbian 9.x +============================================================================== + +These instuctions are for people developing for S60 3.x. S60 3.x +uses Symbian OS so you need S60 SDK. + +extract "symbian.zip" into this folder. + +go to symbian folder + +bldmake bldfiles +abld build + +That produces WINSCW and ARMV5 versions of sdl.dll runtime library +and sdl.lib for development. + +Eaudiolib.lib and dll are generated as well, and must be delivered +along SDL as it uses it for audio. + +There are certain problems with GCC compiler when building for +target, it may compile or binaries are buggy - please use RVCT +compiler as it works and produces far more effient code. + +Its likely that SDL application should be integrated into S60 +work and behave well there. So there is CSDL class (sdlepocapi.h) +to make this easy. If you do porting from other system, then +implement a S60 application and use CSDL class, they you may +not need to modify original SDL code at all! + + + diff --git a/docs.html b/docs.html index 08e0d3a2d..8c55e52b0 100644 --- a/docs.html +++ b/docs.html @@ -46,6 +46,9 @@

General Notes

Support for Nokia 9210 "EPOC" driver has been removed from the main SDL code.

+

+ Unofficial support for the S60/SymbianOS platform has been added. +

Unix Notes

diff --git a/include/SDL_config.h.default b/include/SDL_config.h.default index cc5ab6574..c82f42adf 100644 --- a/include/SDL_config.h.default +++ b/include/SDL_config.h.default @@ -32,6 +32,8 @@ #include "SDL_config_macos.h" #elif defined(__MACOSX__) #include "SDL_config_macosx.h" +#elif defined(__SYMBIAN32__) +#include "SDL_config_symbian.h" /* must be before win32! */ #elif defined(__WIN32__) #include "SDL_config_win32.h" #elif defined(__OS2__) diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index c2a76950d..abb1b447d 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -224,7 +224,6 @@ /* Enable various threading systems */ #undef SDL_THREAD_BEOS #undef SDL_THREAD_DC -#undef SDL_THREAD_EPOC #undef SDL_THREAD_OS2 #undef SDL_THREAD_PTH #undef SDL_THREAD_PTHREAD @@ -237,7 +236,6 @@ #undef SDL_TIMER_BEOS #undef SDL_TIMER_DC #undef SDL_TIMER_DUMMY -#undef SDL_TIMER_EPOC #undef SDL_TIMER_MACOS #undef SDL_TIMER_MINT #undef SDL_TIMER_OS2 @@ -255,7 +253,6 @@ #undef SDL_VIDEO_DRIVER_DIRECTFB #undef SDL_VIDEO_DRIVER_DRAWSPROCKET #undef SDL_VIDEO_DRIVER_DUMMY -#undef SDL_VIDEO_DRIVER_EPOC #undef SDL_VIDEO_DRIVER_FBCON #undef SDL_VIDEO_DRIVER_GAPI #undef SDL_VIDEO_DRIVER_GEM diff --git a/include/SDL_config_symbian.h b/include/SDL_config_symbian.h new file mode 100644 index 000000000..acb49abf0 --- /dev/null +++ b/include/SDL_config_symbian.h @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2006 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + +Symbian version Markus Mertama + +*/ + + +#ifndef _SDL_CONFIG_SYMBIAN_H +#define _SDL_CONFIG_SYMBIAN_H + +#include "SDL_platform.h" + +/* This is the minimal configuration that can be used to build SDL */ + + +#include +#include + + +#ifdef __GCCE__ +#define SYMBIAN32_GCCE +#endif + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#endif + +#ifndef _INTPTR_T_DECLARED +typedef unsigned int uintptr_t; +#endif + +#ifndef _INT8_T_DECLARED +typedef signed char int8_t; +#endif + +#ifndef _UINT8_T_DECLARED +typedef unsigned char uint8_t; +#endif + +#ifndef _INT16_T_DECLARED +typedef signed short int16_t; +#endif + +#ifndef _UINT16_T_DECLARED +typedef unsigned short uint16_t; +#endif + +#ifndef _INT32_T_DECLARED +typedef signed int int32_t; +#endif + +#ifndef _UINT32_T_DECLARED +typedef unsigned int uint32_t; +#endif + +#ifndef _INT64_T_DECLARED +typedef signed long long int64_t; +#endif + +#ifndef _UINT64_T_DECLARED +typedef unsigned long long uint64_t; +#endif + +#define SDL_AUDIO_DRIVER_EPOCAUDIO 1 + + +/* Enable the stub cdrom driver (src/cdrom/dummy/\*.c) */ +#define SDL_CDROM_DISABLED 1 + +/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */ +#define SDL_JOYSTICK_DISABLED 1 + +/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DISABLED 1 + +#define SDL_THREAD_SYMBIAN 1 + +#define SDL_VIDEO_DRIVER_EPOC 1 + +#define SDL_VIDEO_OPENGL 0 + +#define SDL_HAS_64BIT_TYPE 1 + +#define HAVE_LIBC 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STRING_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 + +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +//#define HAVE_ALLOCA 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE__STRUPR 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_ITOA 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE__STRICMP 1 +#define HAVE__STRNICMP 1 +#define HAVE_SSCANF 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDDEF_H 1 + + + +#endif /* _SDL_CONFIG_SYMBIAN_H */ diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index 53d1288f0..21a86794a 100644 --- a/include/SDL_stdinc.h +++ b/include/SDL_stdinc.h @@ -91,7 +91,9 @@ typedef uint32_t Uint32; #ifdef SDL_HAS_64BIT_TYPE typedef int64_t Sint64; +#ifndef SYMBIAN32_GCCE typedef uint64_t Uint64; +#endif #else /* This is really just a hack to prevent the compiler from complaining */ typedef struct { diff --git a/include/SDL_thread.h b/include/SDL_thread.h index e0a35b1ab..403ee4620 100644 --- a/include/SDL_thread.h +++ b/include/SDL_thread.h @@ -45,7 +45,7 @@ struct SDL_Thread; typedef struct SDL_Thread SDL_Thread; /* Create a thread */ -#if (defined(__WIN32__) && !defined(HAVE_LIBC)) || defined(__OS2__) +#if ((defined(__WIN32__) && !defined(HAVE_LIBC)) || defined(__OS2__)) && !defined(__SYMBIAN32__) /* We compile SDL into a DLL on OS/2. This means, that it's the DLL which creates a new thread for the calling process with the SDL_CreateThread() diff --git a/include/begin_code.h b/include/begin_code.h index 88fbc2f3d..b03787f4a 100644 --- a/include/begin_code.h +++ b/include/begin_code.h @@ -83,11 +83,15 @@ #endif #endif /* SDLCALL */ -/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */ #ifdef __SYMBIAN32__ +#ifndef EKA2 #undef DECLSPEC #define DECLSPEC -#endif /* __SYMBIAN32__ */ +#elif !defined(__WINS__) +#undef DECLSPEC +#define DECLSPEC __declspec(dllexport) +#endif //EKA2 +#endif //__SYMBIAN32__ /* Force structure packing at 4 byte alignment. This is necessary if the header is included in code which has structure @@ -116,7 +120,7 @@ #if defined(_MSC_VER) || defined(__BORLANDC__) || \ defined(__DMC__) || defined(__SC__) || \ defined(__WATCOMC__) || defined(__LCC__) || \ - defined(__DECC) + defined(__DECC) || defined(__EABI__) #ifndef __inline__ #define __inline__ __inline #endif diff --git a/src/SDL.c b/src/SDL.c index 64a3e93dc..353d1a575 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -323,7 +323,7 @@ unsigned _System LibMain(unsigned hmod, unsigned termination) } #endif /* __WATCOMC__ */ -#elif defined(__WIN32__) +#elif defined(__WIN32__) && !defined(__SYMBIAN32__) #if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL)) /* Need to include DllMain() on Watcom C for some reason.. */ diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 91d6945ed..81e890aaf 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -106,6 +106,9 @@ static AudioBootStrap *bootstrap[] = { #endif #if SDL_AUDIO_DRIVER_DART &DART_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_EPOCAUDIO + &EPOCAudio_bootstrap, #endif NULL }; @@ -545,7 +548,7 @@ int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) switch (audio->opened) { case 1: /* Start the audio thread */ -#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) +#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__) #undef SDL_CreateThread audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL); #else diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index b73748aab..0fdd3ae10 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -171,6 +171,9 @@ extern AudioBootStrap MMEAUDIO_bootstrap; #if SDL_AUDIO_DRIVER_DART extern AudioBootStrap DART_bootstrap; #endif +#if SDL_AUDIO_DRIVER_EPOCAUDIO +extern AudioBootStrap EPOCAudio_bootstrap; +#endif /* This is the current audio device */ extern SDL_AudioDevice *current_audio; diff --git a/src/audio/symbian/SDL_epocaudio.cpp b/src/audio/symbian/SDL_epocaudio.cpp new file mode 100644 index 000000000..6c36671bc --- /dev/null +++ b/src/audio/symbian/SDL_epocaudio.cpp @@ -0,0 +1,614 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocaudio.cpp + Epoc based SDL audio driver implementation + + Markus Mertama +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_epocaudio.c,v 0.0.0.0 2001/06/19 17:19:56 hercules Exp $"; +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "epoc_sdl.h" + +#include + + +extern "C" { +#include "SDL_audio.h" +#include "SDL_error.h" +#include "SDL_audiomem.h" +#include "SDL_audio_c.h" +#include "SDL_timer.h" +#include "SDL_audiodev_c.h" +} + +#include "SDL_epocaudio.h" + +#include "streamplayer.h" + + +//#define DEBUG_AUDIO + + +/* Audio driver functions */ + +static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec); +static void EPOC_WaitAudio(SDL_AudioDevice *thisdevice); +static void EPOC_PlayAudio(SDL_AudioDevice *thisdevice); +static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice *thisdevice); +static void EPOC_CloseAudio(SDL_AudioDevice *thisdevice); +static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice); + +static int Audio_Available(void); +static SDL_AudioDevice *Audio_CreateDevice(int devindex); +static void Audio_DeleteDevice(SDL_AudioDevice *device); + + +//void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len); + +#ifdef __WINS__ +#define DODUMP +#endif + +#ifdef DODUMP +NONSHARABLE_CLASS(TDump) + { + public: + TInt Open(); + void Close(); + void Dump(const TDesC8& aDes); + private: + RFile iFile; + RFs iFs; + }; + +TInt TDump::Open() + { + TInt err = iFs.Connect(); + if(err == KErrNone) + { +#ifdef __WINS__ +_LIT(target, "C:\\sdlau.raw"); +#else +_LIT(target, "E:\\sdlau.raw"); +#endif + err = iFile.Replace(iFs, target, EFileWrite); + } + return err; + } +void TDump::Close() + { + iFile.Close(); + iFs.Close(); + } +void TDump::Dump(const TDesC8& aDes) + { + iFile.Write(aDes); + } +#endif + + +NONSHARABLE_CLASS(CSimpleWait) : public CTimer + { + public: + void Wait(TTimeIntervalMicroSeconds32 aWait); + static CSimpleWait* NewL(); + private: + CSimpleWait(); + void RunL(); + }; + + +CSimpleWait* CSimpleWait::NewL() + { + CSimpleWait* wait = new (ELeave) CSimpleWait(); + CleanupStack::PushL(wait); + wait->ConstructL(); + CleanupStack::Pop(); + return wait; + } + +void CSimpleWait::Wait(TTimeIntervalMicroSeconds32 aWait) + { + After(aWait); + CActiveScheduler::Start(); + } + +CSimpleWait::CSimpleWait() : CTimer(CActive::EPriorityStandard) + { + CActiveScheduler::Add(this); + } + +void CSimpleWait::RunL() + { + CActiveScheduler::Stop(); + } + +const TInt KAudioBuffers(2); + + +NONSHARABLE_CLASS(CEpocAudio) : public CBase, public MStreamObs, public MStreamProvider + { + public: + static void* NewL(TInt BufferSize, TInt aFill); + inline static CEpocAudio& Current(SDL_AudioDevice* thisdevice); + + static void Free(SDL_AudioDevice* thisdevice); + + void Wait(); + void Play(); + // void SetBuffer(const TDesC8& aBuffer); + void ThreadInitL(TAny* aDevice); + void Open(TInt iRate, TInt iChannels, TUint32 aType, TInt aBytes); + ~CEpocAudio(); + TUint8* Buffer(); + TBool SetPause(TBool aPause); + #ifdef DODUMP + void Dump(const TDesC8& aBuf) {iDump.Dump(aBuf);} + #endif + private: + CEpocAudio(TInt aBufferSize); + void Complete(TInt aState, TInt aError); + TPtrC8 Data(); + void ConstructL(TInt aFill); + private: + TInt iBufferSize; + CStreamPlayer* iPlayer; + TInt iBufferRate; + TInt iRate; + TInt iChannels; + TUint32 iType; + TInt iPosition; + TThreadId iTid; + TUint8* iAudioPtr; + TUint8* iBuffer; + // TTimeIntervalMicroSeconds iStart; + TTime iStart; + TInt iTune; + CSimpleWait* iWait; + #ifdef DODUMP + TDump iDump; + #endif + }; + +inline CEpocAudio& CEpocAudio::Current(SDL_AudioDevice* thisdevice) + { + return *static_cast((void*)thisdevice->hidden); + } + +/* + +TBool EndSc(TAny*) + { + CActiveScheduler::Stop(); + } + +LOCAL_C void CleanScL() + { + CIdle* d = CIdle::NewLC(CActive:::EPriorityIdle); + d->Start(TCallBack(EndSc)); + CActiveScheduler::Start(); + + } +*/ + +void CEpocAudio::Free(SDL_AudioDevice* thisdevice) + { + CEpocAudio* ea = static_cast((void*)thisdevice->hidden); + if(ea) + { + ASSERT(ea->iTid == RThread().Id()); + delete ea; + thisdevice->hidden = NULL; + + CActiveScheduler* as = CActiveScheduler::Current(); + ASSERT(as->StackDepth() == 0); + delete as; + CActiveScheduler::Install(NULL); + } + ASSERT(thisdevice->hidden == NULL); + } + +CEpocAudio::CEpocAudio(TInt aBufferSize) : iBufferSize(aBufferSize), iPosition(-1) + { + } + +void* CEpocAudio::NewL(TInt aBufferSize, TInt aFill) + { + CEpocAudio* eAudioLib = new (ELeave) CEpocAudio(aBufferSize); + CleanupStack::PushL(eAudioLib); + eAudioLib->ConstructL(aFill); + CleanupStack::Pop(); + return eAudioLib; + } + +void CEpocAudio::ConstructL(TInt aFill) + { + iBuffer = (TUint8*) User::AllocL(KAudioBuffers * iBufferSize); + memset(iBuffer, aFill, KAudioBuffers * iBufferSize); + iAudioPtr = iBuffer; + } + + +TBool CEpocAudio::SetPause(TBool aPause) + { + if(aPause && iPosition >= 0) + { + iPosition = -1; + if(iPlayer != NULL) + iPlayer->Stop(); + } + if(!aPause && iPosition < 0) + { + iPosition = 0; + if(iPlayer != NULL) + iPlayer->Start(); + } + return iPosition < 0; + } + +void CEpocAudio::ThreadInitL(TAny* aDevice) + { + iTid = RThread().Id(); + CActiveScheduler* as = new (ELeave) CActiveScheduler(); + CActiveScheduler::Install(as); + + EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem((TSdlCleanupOperation)EPOC_CloseAudio, aDevice)); + + iWait = CSimpleWait::NewL(); + + iPlayer = new (ELeave) CStreamPlayer(*this, *this); + iPlayer->ConstructL(); + iPlayer->OpenStream(iRate, iChannels, iType); + + #ifdef DODUMP + User::LeaveIfError(iDump.Open()); + #endif + } + + + +TUint8* CEpocAudio::Buffer() + { + iStart.UniversalTime(); +// iStart = iPlayer->Position(); + return iAudioPtr; + + } + +CEpocAudio::~CEpocAudio() + { + if(iWait != NULL) + iWait->Cancel(); + delete iWait; + if(iPlayer != NULL) + iPlayer->Close(); + delete iPlayer; + delete iBuffer; + } + +void CEpocAudio::Complete(TInt aState, TInt aError) + { + if(aState == MStreamObs::EClose) + { + } + if(iPlayer->Closed()) + return; + switch(aError) + { + case KErrUnderflow: + case KErrInUse: + iPlayer->Start(); + break; + case KErrAbort: + iPlayer->Open(); + } + } + + +void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len) + { +#ifdef DODUMP + const TPtrC8 buf((TUint8*)data, len); + CEpocAudio::Current(thisdevice).Dump(buf); +#endif + } + +const TInt KClip(256); + +TPtrC8 CEpocAudio::Data() + { + if(iPosition < 0) + return KNullDesC8(); + + TPtrC8 data(iAudioPtr + iPosition, KClip); + +#ifdef DODUMP + iDump.Dump(data); +#endif + + iPosition += KClip; + if(iPosition >= iBufferSize) + { + +/* if(iAudioPtr == iBuffer) + iAudioPtr = iBuffer + iBufferSize; + else + iAudioPtr = iBuffer; +*/ + iAudioPtr += iBufferSize; + + if((iAudioPtr - iBuffer) >= KAudioBuffers * iBufferSize) + iAudioPtr = iBuffer; + + iPosition = -1; + if(iWait->IsActive()) + { + iWait->Cancel(); + CActiveScheduler::Stop(); + } + } + return data; + } + + + + +void CEpocAudio::Play() + { + iPosition = 0; + } + +void CEpocAudio::Wait() + { + if(iPosition >= 0 /*&& iPlayer->Playing()*/) + { + const TInt64 bufMs = TInt64(iBufferSize - KClip) * TInt64(1000000); + const TInt64 specTime = bufMs / TInt64(iRate * iChannels * 2); + iWait->After(specTime); + + CActiveScheduler::Start(); + TTime end; + end.UniversalTime(); + const TTimeIntervalMicroSeconds delta = end.MicroSecondsFrom(iStart); + + +// const TTimeIntervalMicroSeconds end = iPlayer->Position(); + + + + + const TInt diff = specTime - delta.Int64(); + + if(diff > 0 && diff < 200000) + { + User::After(diff); + } + + } + else + { + User::After(10000); +// iWait->Wait(10000); //just give some time... + } + } + +void CEpocAudio::Open(TInt aRate, TInt aChannels, TUint32 aType, TInt aBytes) + { + iRate = aRate; + iChannels = aChannels; + iType = aType; + iBufferRate = iRate * iChannels * aBytes; //1/x + } + + +/* Audio driver bootstrap functions */ + +AudioBootStrap EPOCAudio_bootstrap = { + "epoc\0\0\0", + "EPOC streaming audio\0\0\0", + Audio_Available, + Audio_CreateDevice +}; + + +static SDL_AudioDevice *Audio_CreateDevice(int /*devindex*/) +{ + SDL_AudioDevice *thisdevice; + + /* Initialize all variables that we clean on shutdown */ + thisdevice = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); + if ( thisdevice ) { + memset(thisdevice, 0, (sizeof *thisdevice)); + thisdevice->hidden = NULL; /*(struct SDL_PrivateAudioData *) + malloc((sizeof thisdevice->hidden)); */ + } + if ( (thisdevice == NULL) /*|| (thisdevice->hidden == NULL) */) { + SDL_OutOfMemory(); + if ( thisdevice ) { + free(thisdevice); + } + return(0); + } +// memset(thisdevice->hidden, 0, (sizeof *thisdevice->hidden)); + + /* Set the function pointers */ + thisdevice->OpenAudio = EPOC_OpenAudio; + thisdevice->WaitAudio = EPOC_WaitAudio; + thisdevice->PlayAudio = EPOC_PlayAudio; + thisdevice->GetAudioBuf = EPOC_GetAudioBuf; + thisdevice->CloseAudio = EPOC_CloseAudio; + thisdevice->ThreadInit = EPOC_ThreadInit; + thisdevice->free = Audio_DeleteDevice; + + return thisdevice; +} + + +static void Audio_DeleteDevice(SDL_AudioDevice *device) + { + //free(device->hidden); + free(device); + } + +static int Audio_Available(void) +{ + return(1); // Audio stream modules should be always there! +} + + +static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec) +{ + SDL_TRACE("SDL:EPOC_OpenAudio"); + + + TUint32 type = KMMFFourCCCodePCM16; + TInt bytes = 2; + + switch(spec->format) + { + case AUDIO_U16LSB: + type = KMMFFourCCCodePCMU16; + break; + case AUDIO_S16LSB: + type = KMMFFourCCCodePCM16; + break; + case AUDIO_U16MSB: + type = KMMFFourCCCodePCMU16B; + break; + case AUDIO_S16MSB: + type = KMMFFourCCCodePCM16B; + break; + //8 bit not supported! + case AUDIO_U8: + case AUDIO_S8: + default: + spec->format = AUDIO_S16LSB; + }; + + + + if(spec->channels > 2) + spec->channels = 2; + + spec->freq = CStreamPlayer::ClosestSupportedRate(spec->freq); + + + /* Allocate mixing buffer */ + const TInt buflen = spec->size;// * bytes * spec->channels; +// audiobuf = NULL; + + TRAPD(err, thisdevice->hidden = static_cast(CEpocAudio::NewL(buflen, spec->silence))); + if(err != KErrNone) + return -1; + + CEpocAudio::Current(thisdevice).Open(spec->freq, spec->channels, type, bytes); + + CEpocAudio::Current(thisdevice).SetPause(ETrue); + + // isSDLAudioPaused = 1; + + thisdevice->enabled = 0; /* enable only after audio engine has been initialized!*/ + + /* We're ready to rock and roll. :-) */ + return(0); +} + + +static void EPOC_CloseAudio(SDL_AudioDevice* thisdevice) + { +#ifdef DEBUG_AUDIO + SDL_TRACE("Close audio\n"); +#endif + + CEpocAudio::Free(thisdevice); + } + + +static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice) + { + SDL_TRACE("SDL:EPOC_ThreadInit"); + CEpocAudio::Current(thisdevice).ThreadInitL(thisdevice); + RThread().SetPriority(EPriorityMore); + thisdevice->enabled = 1; + } + +/* This function waits until it is possible to write a full sound buffer */ +static void EPOC_WaitAudio(SDL_AudioDevice* thisdevice) +{ +#ifdef DEBUG_AUDIO + SDL_TRACE1("wait %d audio\n", CEpocAudio::AudioLib().StreamPlayer(KSfxChannel).SyncTime()); + TInt tics = User::TickCount(); +#endif + + CEpocAudio::Current(thisdevice).Wait(); + +#ifdef DEBUG_AUDIO + TInt ntics = User::TickCount() - tics; + SDL_TRACE1("audio waited %d\n", ntics); + SDL_TRACE1("audio at %d\n", tics); +#endif +} + + + +static void EPOC_PlayAudio(SDL_AudioDevice* thisdevice) + { + if(CEpocAudio::Current(thisdevice).SetPause(SDL_GetAudioStatus() == SDL_AUDIO_PAUSED)) + SDL_Delay(500); //hold on the busy loop + else + CEpocAudio::Current(thisdevice).Play(); + +#ifdef DEBUG_AUDIO + SDL_TRACE("buffer has audio data\n"); +#endif + + +#ifdef DEBUG_AUDIO + SDL_TRACE1("Wrote %d bytes of audio data\n", buflen); +#endif +} + +static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice* thisdevice) + { + return CEpocAudio::Current(thisdevice).Buffer(); + } + + + diff --git a/src/audio/symbian/SDL_epocaudio.h b/src/audio/symbian/SDL_epocaudio.h new file mode 100644 index 000000000..d08c4c24f --- /dev/null +++ b/src/audio/symbian/SDL_epocaudio.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_epocaudio.h,v 1.1.2.2 2001/02/10 07:20:03 hercules Exp $"; +#endif + +#ifndef _SDL_EPOCAUDIO_H +#define _SDL_EPOCAUDIO_H + +extern "C" { +#include "SDL_sysaudio.h" +} + + +#endif /* _SDL_EPOCAUDIO_H */ diff --git a/src/audio/symbian/streamplayer.cpp b/src/audio/symbian/streamplayer.cpp new file mode 100644 index 000000000..dd733a1d1 --- /dev/null +++ b/src/audio/symbian/streamplayer.cpp @@ -0,0 +1,279 @@ +#include "streamplayer.h" +#include + + + +const TInt KMaxVolume(256); + +LOCAL_C TInt GetSampleRate(TInt aRate) + { + switch(aRate) + { + case 8000: return TMdaAudioDataSettings::ESampleRate8000Hz; + case 11025: return TMdaAudioDataSettings::ESampleRate11025Hz; + case 12000: return TMdaAudioDataSettings::ESampleRate12000Hz; + case 16000: return TMdaAudioDataSettings::ESampleRate16000Hz; + case 22050: return TMdaAudioDataSettings::ESampleRate22050Hz; + case 24000: return TMdaAudioDataSettings::ESampleRate24000Hz; + case 32000: return TMdaAudioDataSettings::ESampleRate32000Hz; + case 44100: return TMdaAudioDataSettings::ESampleRate44100Hz; + case 48000: return TMdaAudioDataSettings::ESampleRate48000Hz; + case 96000: return TMdaAudioDataSettings::ESampleRate96000Hz; + case 64000: return TMdaAudioDataSettings::ESampleRate64000Hz; + } + return KErrNotFound; + } + +LOCAL_C TInt GetChannels(TInt aChannels) + { + switch(aChannels) + { + case 1: return TMdaAudioDataSettings::EChannelsMono; + case 2: return TMdaAudioDataSettings::EChannelsStereo; + } + return KErrNotFound; + } + +TInt CStreamPlayer::ClosestSupportedRate(TInt aRate) + { + if(aRate > 96000) + return 96000; + TInt rate = aRate; + while(GetSampleRate(rate) == KErrNotFound) + { + ++rate; + } + return rate; + } + +CStreamPlayer::CStreamPlayer(MStreamProvider& aProvider, MStreamObs& aObs) : + iProvider(aProvider), iObs(aObs), iVolume(KMaxVolume) + { + } + +CStreamPlayer::~CStreamPlayer() + { + iState |= EDied; + if(iState & EInited) + Close(); + User::After(100000); //wait buffer to be flushed + ASSERT(iPtr.Length() == 0); + delete iStream; + } + + +void CStreamPlayer::ConstructL() + { + iStream = CMdaAudioOutputStream::NewL(*this, EMdaPriorityMax); + iSilence.SetMax(); + iSilence.FillZ(); + } + + +TInt CStreamPlayer::OpenStream(TInt aRate, TInt aChannels, TUint32 aType) + { + Close(); + + iType = aType; + + iRate = GetSampleRate(aRate); + if(iRate == KErrNotFound) + return KErrNotSupported; + + iChannels = GetChannels(aChannels); + if(iChannels == KErrNotFound) + return KErrNotSupported; + + Open(); + + return KErrNone; + } + + +TInt CStreamPlayer::MaxVolume() const + { + return KMaxVolume; + } + +void CStreamPlayer::SetVolume(TInt aNew) + { + + const TInt maxi = MaxVolume(); + if(aNew > maxi) + return; + if(aNew < 0) + return; + + iVolume = aNew; + + iState |= EVolumeChange; + } + + TInt CStreamPlayer::Volume() const + { + return iVolume; + } + +void CStreamPlayer::Open() + { + TMdaAudioDataSettings audioSettings; + audioSettings.Query(); + audioSettings.iCaps = TMdaAudioDataSettings::ERealTime | + TMdaAudioDataSettings::ESampleRateFixed; + audioSettings.iSampleRate = iRate; + audioSettings.iChannels = iChannels; + audioSettings.iFlags = TMdaAudioDataSettings::ENoNetworkRouting; + audioSettings.iVolume = 0; + + iState &= ~EStopped; + iStream->Open(&audioSettings); + } + +void CStreamPlayer::Stop() + { + if(iState & (EStarted | EInited)) + { + Close(); + iState |= EStopped; + } + } + +void CStreamPlayer::Start() + { + if(iPtr.Length() == 0) + { + iState |= EStarted; + if(iState & EInited) + { + Request(); + } + else if(iState & EStopped) + { + Open(); + } + } + } + +void CStreamPlayer::Close() + { + iState &= ~EInited; + iStream->Stop(); + iState &= ~EStarted; + } + +void CStreamPlayer::Request() + { + if(iState & EInited) + { + iPtr.Set(KNullDesC8); + + if(iState & EVolumeChange) + { + const TReal newVol = iVolume; + const TReal newMax = MaxVolume(); + const TInt maxVol = iStream->MaxVolume(); + const TReal max = static_cast(maxVol); + const TReal newvolume = (newVol * max) / newMax; + const TInt vol = static_cast(newvolume); + iStream->SetVolume(vol); + iState &= ~EVolumeChange; + } + + if(iState & EStarted) + { + iPtr.Set(iProvider.Data()); + } + if(iPtr.Length() == 0) + { + iPtr.Set(iSilence); + } + TRAPD(err, iStream->WriteL(iPtr)); + if(err != KErrNone) + { + iObs.Complete(MStreamObs::EWrite, err); + } + /* else + { + iProvider.Written(iPtr.Length()); + }*/ + } + } + + +void CStreamPlayer::SetCapsL() + { + iStream->SetDataTypeL(iType); + iStream->SetAudioPropertiesL(iRate, iChannels); + } + +void CStreamPlayer::MaoscOpenComplete(TInt aError) + { + if(aError == KErrNone) + { + TRAPD(err, SetCapsL()); + if(err == KErrNone) + { + iStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime); + iState |= EInited; + + + SetVolume(Volume()); + + if(iState & EStarted) + { + Request(); + } + + } + aError = err; + } + if(!(iState & EDied)) + iObs.Complete(MStreamObs::EInit, aError); + } + +void CStreamPlayer::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/) + { + iPtr.Set(KNullDesC8); + if(aError == KErrNone) + { + if(iState & EInited) + Request(); + else + iStream->Stop(); + } + else if(!(iState & EDied)) + iObs.Complete(MStreamObs::EPlay, aError); + } + +void CStreamPlayer::MaoscPlayComplete(TInt aError) + { + iPtr.Set(KNullDesC8); + iState &= ~EStarted; + if(!(iState & EDied)) + iObs.Complete(MStreamObs::EClose, aError); + } + +TBool CStreamPlayer::Playing() const + { + return (iState & EInited) && (iState & EStarted); + } + +TBool CStreamPlayer::Closed() const + { + return !(iState & EInited) && !(iState & EDied); + } + + /* +void CStreamPlayer::Request() + { + SetActive(); + TRequestStatus* s = &iStatus; + User::RequestComplete(s, KErrNone); + } + // iTimer.After(0); + */ + + + + + diff --git a/src/audio/symbian/streamplayer.h b/src/audio/symbian/streamplayer.h new file mode 100644 index 000000000..8c6e74f92 --- /dev/null +++ b/src/audio/symbian/streamplayer.h @@ -0,0 +1,89 @@ +#ifndef STREAMPLAYER_H +#define STREAMPLAYER_H + +#include + +const TInt KSilenceBuffer = 256; + +class MStreamObs + { + public: + enum + { + EInit, + EPlay, + EWrite, + EClose, + }; + virtual void Complete(TInt aState, TInt aError) = 0; + }; + +class MStreamProvider + { + public: + virtual TPtrC8 Data() = 0; + }; + +NONSHARABLE_CLASS(CStreamPlayer) : public CBase, public MMdaAudioOutputStreamCallback + { + public: + CStreamPlayer(MStreamProvider& aProvider, MStreamObs& aObs); + ~CStreamPlayer(); + void ConstructL(); + + static TInt ClosestSupportedRate(TInt aRate); + + TInt OpenStream(TInt aRate, TInt aChannels, TUint32 aType = KMMFFourCCCodePCM16); + + void SetVolume(TInt aNew); + TInt Volume() const; + TInt MaxVolume() const; + + void Stop(); + void Start(); + void Open(); + void Close(); + + TBool Playing() const; + TBool Closed() const; + + private: + + void MaoscOpenComplete(TInt aError) ; + void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer); + void MaoscPlayComplete(TInt aError); + + private: + void Request(); + void SetCapsL(); + + private: + MStreamProvider& iProvider; + MStreamObs& iObs; + TInt iVolume; + + CMdaAudioOutputStream* iStream; + + TInt iRate; + TInt iChannels; + TUint32 iType; + + enum + { + ENone = 0, + EInited = 0x1, + EStarted = 0x2, + EStopped = 0x4, + EVolumeChange = 0x8, + EDied = 0x10 + }; + + TInt iState; + TBuf8 iSilence; + TPtrC8 iPtr; + + }; + + +#endif + diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 1a51dbd7e..e246fb78b 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -169,7 +169,7 @@ static int SDL_StartEventThread(Uint32 flags) /* The event thread will handle timers too */ SDL_SetTimerThreaded(2); -#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) +#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__) #undef SDL_CreateThread SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL, NULL, NULL); #else diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index add218fd2..c47f43862 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -29,7 +29,7 @@ #include "SDL_rwops.h" -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__SYMBIAN32__) /* Functions to read/write Win32 API file pointers */ /* Will not use it on WinCE because stdio is buffered, it means @@ -372,7 +372,7 @@ SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) return NULL; } -#if defined(__WIN32__) +#if defined(__WIN32__) && !defined(__SYMBIAN32__) rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ diff --git a/src/main/symbian/EKA1/SDL_main.cpp b/src/main/symbian/EKA1/SDL_main.cpp new file mode 100644 index 000000000..a3296e43a --- /dev/null +++ b/src/main/symbian/EKA1/SDL_main.cpp @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_main.cpp + The Epoc executable startup functions + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL_error.h" + +#if defined(__WINS__) +#include +IMPORT_C void RegisterWsExe(const TDesC &aName); +#endif + +/* The prototype for the application's main() function */ +#define main SDL_main +extern "C" int main (int argc, char *argv[], char *envp[]); +extern "C" void exit (int ret); + + +/* Epoc main function */ + +#ifdef __WINS__ + + +void GetCmdLine(int& aArgc, char**& aArgv) + { + RChunk chunk; + + if(chunk.OpenGlobal(RThread().Name(), ETrue) != KErrNone) + return; + + TUint* ptr = (TUint*) chunk.Base(); + if(ptr != NULL) + { + aArgc = (int) *(ptr); // count + aArgv = (char**) *(ptr + 1); + } + chunk.Close(); + } + +#endif + + +TInt E32Main() + { + /* Get the clean-up stack */ + CTrapCleanup* cleanup = CTrapCleanup::New(); + + /* Arrange for multi-threaded operation */ + SpawnPosixServerThread(); + + /* Get args and environment */ + int argc=0; + char** argv=0; + char** envp=0; + +#ifndef __WINS__ + __crt0(argc,argv,envp); +#else + GetCmdLine(argc, argv); +#endif + /* Start the application! */ + + /* Create stdlib */ + _REENT; + + /* Set process and thread priority and name */ + + RThread currentThread; + RProcess thisProcess; + TParse exeName; + exeName.Set(thisProcess.FileName(), NULL, NULL); + currentThread.Rename(exeName.Name()); + currentThread.SetProcessPriority(EPriorityLow); + currentThread.SetPriority(EPriorityMuchLess); + + /* Call stdlib main */ + int ret = main(argc, argv, envp); /* !! process exits here if there is "exit()" in main! */ + + /* Call exit */ + //exit(ret); /* !! process exits here! */ + //Markus: I do not understand above + //I commented it at let this function + //to return ret value - was it purpose + //that cleanup below is not called at all - why? + + /* Free resources and return */ + + _cleanup(); //this is normally called at exit, I call it here, Markus + + CloseSTDLIB(); + delete cleanup; +#ifdef __WINS__ +// User::Panic(_L("exit"), ret); + // RThread().Kill(ret); //Markus get rid of this thread + // RThread().RaiseException(EExcKill); +#endif + return ret;//Markus, or exit(ret); ?? + //return(KErrNone); + } + + +#ifdef __WINS__ +EXPORT_C TInt WinsMain() + { + return E32Main(); + // return WinsMain(0, 0, 0); + } +#endif + +/* Epoc dll entry point */ +#if defined(__WINS__) +GLDEF_C TInt E32Dll(TDllReason) + { + return(KErrNone); + } +#endif + + diff --git a/src/main/symbian/EKA2/SDL_main.cpp b/src/main/symbian/EKA2/SDL_main.cpp new file mode 100644 index 000000000..3dc69d4aa --- /dev/null +++ b/src/main/symbian/EKA2/SDL_main.cpp @@ -0,0 +1,1035 @@ +/* + SDL_Main.cpp + Symbian OS services for SDL + + Markus Mertama +*/ + + +#include "epoc_sdl.h" + +#include"sdlepocapi.h" +#include +#include +#include +#include + +#include "vectorbuffer.h" +#include +#include +#include +#include "SDL_epocevents_c.h" +#include "SDL_keysym.h" +#include "dsa.h" + + +#ifdef SYMBIANC +#include +#endif + +//Markus Mertama + + +extern SDLKey* KeyMap(); +extern void ResetKeyMap(); + +class CCurrentAppUi; + +//const TUid KSDLUid = { 0xF01F3D69 }; + +NONSHARABLE_CLASS(EnvUtils) + { + public: + static void DisableKeyBlocking(); + static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus); + }; + +TInt Panic(TInt aErr, TInt aLine) + { + TBuf<64> b; + b.Format(_L("Main at %d"), aLine); + User::Panic(b, aErr); + return 0; + } + + +NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi + { + public: + static CCurrentAppUi* Cast(CEikAppUi* aUi); + void DisableKeyBlocking(); + }; + + +CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi) + { + return static_cast(aUi); + } + +void CCurrentAppUi::DisableKeyBlocking() + { + SetKeyBlockMode(ENoKeyBlock); + } + + +class CEventQueue : public CBase, public MEventQueue + { + public: + static CEventQueue* NewL(); + ~CEventQueue(); + public: + TInt Append(const TWsEvent& aEvent); + const TWsEvent& Shift(); + void Lock(); + void Unlock(); + TBool HasData(); + private: + TVector iVector; + RCriticalSection iCS; + }; + + CEventQueue* CEventQueue::NewL() + { + CEventQueue* q = new (ELeave) CEventQueue(); + CleanupStack::PushL(q); + User::LeaveIfError(q->iCS.CreateLocal()); + CleanupStack::Pop(); + return q; + } + +CEventQueue::~CEventQueue() + { + iCS.Close(); + } + +TInt CEventQueue::Append(const TWsEvent& aEvent) + { + iCS.Wait(); + const TInt err = iVector.Append(aEvent); + iCS.Signal(); + return err; + } + + +TBool CEventQueue::HasData() + { + return iVector.Size() > 0; + } + + +void CEventQueue::Lock() + { + iCS.Wait(); + } + +void CEventQueue::Unlock() + { + iCS.Signal(); + } + +const TWsEvent& CEventQueue::Shift() + { + const TWsEvent& event = iVector.Shift(); + return event; + } + + +TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) : +iOperation(aOperation), iItem(aItem), iThread(RThread().Id()) + { + } + +class CEikonEnv; +class CSdlAppServ; + + +NONSHARABLE_CLASS(EpocSdlEnvData) + { + public: + void Free(); + CEventQueue* iEventQueue; + TMainFunc iMain; + TInt iEpocEnvFlags; + int iArgc; + char** iArgv; + CDsa* iDsa; + CSdlAppServ* iAppSrv; + TThreadId iId; + CArrayFix* iCleanupItems; + CEikAppUi* iAppUi; + CSDL* iSdl; + }; + + +EpocSdlEnvData* gEpocEnv; + +#define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;} + +MAINFUNC(1) +MAINFUNC(2) +MAINFUNC(3) +MAINFUNC(4) +MAINFUNC(5) +MAINFUNC(6) + +EXPORT_C TMainFunc::TMainFunc() + { + Mem::FillZ(iMainFunc, sizeof(iMainFunc)); + } + + +const void* TMainFunc::operator[](TInt aIndex) const + { + return iMainFunc[aIndex]; + } + + +NONSHARABLE_CLASS(CSdlAppServ) : public CActive + { + public: + enum + { + EAppSrvNoop = CDsa::ELastDsaRequest, + EAppSrvWindowWidth, + EAppSrvWindowHeight, + EAppSrvWindowDisplayMode, + EAppSrvWindowPointerCursorMode, + EAppSrvDsaStatus, + EAppSrvStopThread, + EAppSrvWaitDsa + }; + CSdlAppServ(); + void ConstructL(); + ~CSdlAppServ(); + TInt Request(TInt aService); + TInt RequestValue(TInt aService); + void Init(); + void PanicMain(TInt aReason); + void PanicMain(const TDesC& aInfo, TInt aReason); + void SetObserver(MSDLObserver* aObserver); + TInt ObserverEvent(TInt aEvent, TInt aParam); + void SetParam(TInt aParam); + void HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread); + MSDLObserver* Observer(); + private: + void RunL(); + void DoCancel(); + private: + const TThreadId iMainId; + RThread iAppThread; + TInt iService; + TInt iReturnValue; + RSemaphore iSema; + MSDLObserver* iObserver; + TRequestStatus* iStatusPtr; + }; + +CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id()) + { + } + + + +MSDLObserver* CSdlAppServ::Observer() + { + return iObserver; + } + + +void CSdlAppServ::SetObserver(MSDLObserver* aObserver) + { + iObserver = aObserver; + } + +TInt CSdlAppServ::ObserverEvent(TInt aEvent, TInt aParam) + { + if(iObserver != NULL) + { + if(RThread().Id() == gEpocEnv->iId) + { + return iObserver->SdlThreadEvent(aEvent, aParam); + } + else if(RThread().Id() == iMainId) + { + return iObserver->SdlEvent(aEvent, aParam); + } + PANIC(KErrNotSupported); + } + return 0; + } + +void CSdlAppServ::PanicMain(TInt aReason) + { + iAppThread.Panic(RThread().Name(), aReason); + } + +void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason) + { + iAppThread.Panic(aInfo, aReason); + } + +void CSdlAppServ::ConstructL() + { + CActiveScheduler::Add(this); + User::LeaveIfError(iSema.CreateLocal(1)); + iStatus = KRequestPending; + iStatusPtr = &iStatus; + SetActive(); + } + + CSdlAppServ::~CSdlAppServ() + { + Cancel(); + if(iSema.Handle() != NULL) + iSema.Signal(); + iSema.Close(); + iAppThread.Close(); + } + +TInt CSdlAppServ::Request(TInt aService) + { + if(RThread().Id() != iAppThread.Id()) + { + iSema.Wait(); + iService = aService; + iAppThread.RequestComplete(iStatusPtr, KErrNone); + return KErrNone; + } + return KErrBadHandle; + } + +TInt CSdlAppServ::RequestValue(TInt aService) + { + Request(aService); + Request(EAppSrvNoop); + return iReturnValue; + } + +void CSdlAppServ::Init() + { + PANIC_IF_ERROR(iAppThread.Open(iMainId)); + } + +void CSdlAppServ::SetParam(TInt aParam) + { + iReturnValue = aParam; + } + +void CSdlAppServ::HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread) + { + if(iObserver != NULL && aMainThread) + { + switch(aService) + { + case MSDLObserver::EEventScreenSizeChanged: + if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette) + EpocSdlEnv::LockPalette(EFalse); + break; + } + } + if(!aMainThread && aService == MSDLObserver::EEventSuspend) + { + if(iObserver == NULL || + (gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend)) + { + EpocSdlEnv::Suspend(); + } + } + } + +void CSdlAppServ::RunL() + { + if(iStatus == KErrNone) + { + switch(iService) + { + case CSdlAppServ::EAppSrvWaitDsa: + EpocSdlEnv::SetWaitDsa(); + iReturnValue = EpocSdlEnv::IsDsaAvailable(); + // } + // gEpocEnv->iDsa->Stop(); + // gEpocEnv->iDsa->RestartL(); + break; + case CSdlAppServ::EAppSrvStopThread: + gEpocEnv->iDsa->SetSuspend(); + break; + case EpocSdlEnv::EDisableKeyBlocking: + EnvUtils::DisableKeyBlocking(); + break; + + case EAppSrvWindowPointerCursorMode: + iReturnValue = gEpocEnv->iDsa != NULL ? + gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady; + break; + case EAppSrvDsaStatus: + gEpocEnv->iDsa->Stop(); + iReturnValue = KErrNone; + break; + case CDsa::ERequestUpdate: + gEpocEnv->iDsa->UnlockHWSurfaceRequestComplete(); + break; + case EAppSrvNoop: + break; + case MSDLObserver::EEventResume: + case MSDLObserver::EEventSuspend: + case MSDLObserver::EEventScreenSizeChanged: + case MSDLObserver::EEventWindowReserved: + case MSDLObserver::EEventKeyMapInit: + case MSDLObserver::EEventWindowNotAvailable: + case MSDLObserver::EEventMainExit: + iReturnValue = ObserverEvent(iService, iReturnValue); + HandleObserverValue(iService, iReturnValue, ETrue); + break; + default: + PANIC(KErrNotSupported); + } + iStatus = KRequestPending; + iStatusPtr = &iStatus; + SetActive(); + } + iSema.Signal(); + } + +void CSdlAppServ::DoCancel() + { + iSema.Wait(); + TRequestStatus* s = &iStatus; + iAppThread.RequestComplete(s, KErrCancel); + } + + + +MEventQueue& EpocSdlEnv::EventQueue() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return *gEpocEnv->iEventQueue; + } + + +TBool EpocSdlEnv::Flags(TInt aFlag) + { + const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag; + return flag == aFlag; + } + +TInt EpocSdlEnv::Argc() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iArgc; + } + + +char** EpocSdlEnv::Argv() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iArgv; + } + + +TBool EpocSdlEnv::IsDsaAvailable() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable(); + } + + +void EpocSdlEnv::WaitDsaAvailable() + { + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0); + gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread); + if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) + { + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0); + } + } + +void EpocSdlEnv::Suspend() + { + if(gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) + { + // gEpocEnv->iDsa->ReleaseStop(); + gEpocEnv->iDsa->SetSuspend(); + RThread().Suspend(); + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0); + } + } + +void EpocSdlEnv::SetWaitDsa() + { + if(!IsDsaAvailable()) + { + RThread th; + th.Open(gEpocEnv->iId); + th.Suspend(); + th.Close(); + gEpocEnv->iDsa->SetSuspend(); + } + } + +void EpocSdlEnv::Resume() + { + gEpocEnv->iDsa->Resume(); + RThread th; + th.Open(gEpocEnv->iId); + th.Resume(); + th.Close(); + + const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0); + gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue); + } + + +TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode) + { + return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode); + } + +TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode) + { + return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode); + } + + +void EpocSdlEnv::UnlockHwSurface() + { + gEpocEnv->iDsa->UnlockHwSurface(); + } + +TUint8* EpocSdlEnv::LockHwSurface() + { + return gEpocEnv->iDsa->LockHwSurface(); + } + + +void EpocSdlEnv::UpdateSwSurface() + { + gEpocEnv->iDsa->UpdateSwSurface(); + } + +TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect) + { + return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect); + } + +void EpocSdlEnv::Request(TInt aService) + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + gEpocEnv->iAppSrv->Request(aService); + } + + +TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize) + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + if(EpocSdlEnv::Flags(CSDL::EAllowImageResize) && gEpocEnv->iDsa->WindowSize() != aRequestedSize) + { + TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize)); + } + return gEpocEnv->iDsa->WindowSize(); + } + + TSize EpocSdlEnv::WindowSize() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iDsa->WindowSize(); + } + +TDisplayMode EpocSdlEnv::DisplayMode() + { + return gEpocEnv->iDsa->DisplayMode(); + } + +TPointerCursorMode EpocSdlEnv::PointerMode() + { + return static_cast + (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode)); + } + +TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette) + { + return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette); + } + +void EpocSdlEnv::PanicMain(TInt aErr) + { + gEpocEnv->iAppSrv->PanicMain(aErr); + } + + +TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem) + { + TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem)); + return err; + } + +void EpocSdlEnv::RemoveCleanupItem(TAny* aItem) + { + for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++) + { + if(gEpocEnv->iCleanupItems->At(i).iItem == aItem) + gEpocEnv->iCleanupItems->Delete(i); + } + } + +void EpocSdlEnv::CleanupItems() + { + const TThreadId id = RThread().Id(); + TInt last = gEpocEnv->iCleanupItems->Count() - 1; + TInt i; + for(i = last; i >= 0 ; i--) + { + TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); + if(item.iThread == id) + { + item.iThread = TThreadId(0); + item.iOperation(item.iItem); + } + } + last = gEpocEnv->iCleanupItems->Count() - 1; + for(i = last; i >= 0 ; i--) + { + TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); + if(item.iThread == TThreadId(0)) + { + gEpocEnv->iCleanupItems->Delete(i); + } + } + } + +void EpocSdlEnv::FreeSurface() + { + Request(CSdlAppServ::EAppSrvDsaStatus); + gEpocEnv->iDsa->Free(); + } + +void EpocSdlEnv::LockPalette(TBool aLock) + { + gEpocEnv->iDsa->LockPalette(aLock); + } + +void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam) + { + const TBool sdlThread = RThread().Id() == gEpocEnv->iId; + const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam); + gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread); + if(sdlThread) + { + gEpocEnv->iAppSrv->SetParam(aParam); + const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService); + gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse); + } + } + + +TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint) + { + return gEpocEnv->iDsa->WindowCoordinates(aPoint); + } + +void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr) + { + gEpocEnv->iAppSrv->PanicMain(aInfo, aErr); + } +//Dsa is a low priority ao, it has to wait if its pending event, but ws +//event has been prioritized before it +//this is not called from app thread! +void EpocSdlEnv::WaitDeviceChange() + { + LockPalette(ETrue); + gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa); + const TSize sz = WindowSize(); + const TInt param = reinterpret_cast(&sz); + ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param); + + // RThread().Suspend(); + } + +LOCAL_C TBool CheckSdl() + { + TInt isExit = ETrue; + RThread sdl; + if(sdl.Open(gEpocEnv->iId) == KErrNone) + { + if(sdl.ExitType() == EExitPending) + { + isExit = EFalse; + } + sdl.Close(); + } + return isExit; + } + +void EpocSdlEnvData::Free() + { + if(RThread().Id() == gEpocEnv->iId) + { + iDsa->Free(); + return; + } + + __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady)); + + for(TInt i = 0; i < iArgc; i++) + User::Free( iArgv[i] ); + + User::Free(iArgv); + + + delete iEventQueue; + + if(iDsa != NULL) + iDsa->Free(); + + delete iDsa; + delete iAppSrv; + } + +_LIT(KSDLMain, "SDLMain"); + +LOCAL_C int MainL() + { + gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat(8); + + char** envp=0; + /* !! process exits here if there is "exit()" in main! */ + int ret = 0; + for(TInt i = 0; i < 6; i++) + { + void* f = (void*) gEpocEnv->iMain[i]; + if(f != NULL) + { + switch(i) + { + case 0: + ret = ((mainfunc1)f)(); + return ret; + case 3: + ((mainfunc1)f)(); + return ret; + case 1: + ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); + return ret; + case 4: + ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); + return ret; + case 2: + ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); + return ret; + case 5: + ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); + return ret; + } + } + } + PANIC(KErrNotFound); + return 0; + } + +LOCAL_C TInt DoMain(TAny* /*aParam*/) + { + + + CTrapCleanup* cleanup = CTrapCleanup::New(); + + TBool fbsconnected = EFalse; + if(RFbsSession::GetSession() == NULL) + { + PANIC_IF_ERROR(RFbsSession::Connect()); + fbsconnected = ETrue; + } + + gEpocEnv->iAppSrv->Init(); + +#ifdef SYMBIANC + // Create stdlib + _REENT; +#endif + + // Call stdlib main + int ret = 0; + + //completes waiting rendesvous + RThread::Rendezvous(KErrNone); + + TRAPD(err, err = MainL()); + + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err); + + // Free resources and return + + EpocSdlEnv::CleanupItems(); + + gEpocEnv->iCleanupItems->Reset(); + delete gEpocEnv->iCleanupItems; + gEpocEnv->iCleanupItems = NULL; + + gEpocEnv->Free(); //free up in thread resources + +#ifdef SYMBIANC + _cleanup(); //this is normally called at exit, I call it here +#endif + + if(fbsconnected) + RFbsSession::Disconnect(); + +#ifdef SYMBIANC + CloseSTDLIB(); +#endif + + // delete as; + delete cleanup; + + return err == KErrNone ? ret : err;; + } + + + +EXPORT_C CSDL::~CSDL() + { + gEpocEnv->Free(); + User::Free(gEpocEnv); + gEpocEnv->iSdl = NULL; + } + +EXPORT_C CSDL* CSDL::NewL(TInt aFlags) + { + __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists)); + gEpocEnv = (EpocSdlEnvData*) User::AllocL(sizeof(EpocSdlEnvData)); + Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData)); + + gEpocEnv->iEpocEnvFlags = aFlags; + gEpocEnv->iEventQueue = CEventQueue::NewL(); + + gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ(); + gEpocEnv->iAppSrv->ConstructL(); + + CSDL* sdl = new (ELeave) CSDL(); + + gEpocEnv->iSdl = sdl; + + return sdl; + } + + /* +EXPORT_C void CSDL::ReInitL(TFlags aFlags) + { + const TFlags prevFlags = gEpocEnv->iEpocEnvFlags; + gEpocEnv->iEpocEnvFlags = aFlags; + TInt err = KErrNone; + if(((prevFlags & EDrawModeDSB) != (aFlags & EDrawModeDSB)) && gEpocEnv->iDsa) + { + delete gEpocEnv->iDsa; + gEpocEnv->iDsa = NULL; + gEpocEnv->iDsa = CDsa::RecreateL(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)); + } + } + */ + + +EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice) + { + if(gEpocEnv->iDsa == NULL) + gEpocEnv->iDsa = CDsa::CreateL(aSession); + gEpocEnv->iDsa->ConstructL(aWindow, aDevice); + } + + +EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, TInt aFlags, TInt aStackSize) + { + ASSERT(gEpocEnv != NULL); + gEpocEnv->iMain = aFunc; + const TBool args = aArg != NULL; + + gEpocEnv->iArgc = aArg->Count() + 1; + gEpocEnv->iArgv = (char**) User::AllocL(sizeof(char*) * (gEpocEnv->iArgc + 1)); + + TInt k = 0; + const TFileName processName = RProcess().FileName(); + const TInt len = processName.Length(); + gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); + Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len); + gEpocEnv->iArgv[k][len] = 0; + + for(TInt i = 0; args && (i < aArg->Count()); i++) + { + k++; + const TInt len = aArg->MdcaPoint(i).Length(); + gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); + Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len); + gEpocEnv->iArgv[k][len] = 0; + } + + gEpocEnv->iArgv[gEpocEnv->iArgc] = NULL; + + RThread thread; + User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL)); + + if(aStatus != NULL) + { + thread.Logon(*aStatus); + } + + gEpocEnv->iId = thread.Id(); + thread.SetPriority(EPriorityLess); + if((aFlags & CSDL::ERequestResume) == 0) + { + thread.Resume(); + } + thread.Close(); + return gEpocEnv->iId; + } + +EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent) + { + return EpocSdlEnv::EventQueue().Append(aEvent); + } + +EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr) + { + EpocSdlEnv::PanicMain(aInfo, aErr); + } + +EXPORT_C TInt CSDL::GetSDLCode(TInt aScanCode) + { + if(aScanCode < 0) + return MAX_SCANCODE; + if(aScanCode >= MAX_SCANCODE) + return -1; + return KeyMap()[aScanCode]; + } + +EXPORT_C TInt CSDL::SDLCodesCount() const + { + return MAX_SCANCODE; + } + +EXPORT_C void CSDL::ResetSDLCodes() + { + ResetKeyMap(); + } + +EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode) + { + gEpocEnv->iDsa->SetOrientation(aMode); + } + +EXPORT_C TInt CSDL::SetSDLCode(TInt aScanCode, TInt aSDLCode) + { + const TInt current = GetSDLCode(aScanCode); + if(aScanCode >= 0 && aScanCode < MAX_SCANCODE) + KeyMap()[aScanCode] = static_cast(aSDLCode); + return current; + } + + +EXPORT_C MSDLObserver* CSDL::Observer() + { + return gEpocEnv->iAppSrv->Observer(); + } + +EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver) + { + gEpocEnv->iAppSrv->SetObserver(aObserver); + } + +EXPORT_C void CSDL::Resume() + { + EpocSdlEnv::Resume(); + } + +EXPORT_C void CSDL::Suspend() + { + gEpocEnv->iDsa->DoStop(); + } + +EXPORT_C CSDL::CSDL() + { + } + +EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const + { + gEpocEnv->iAppUi = &aAppUi; + EnvUtils::DisableKeyBlocking(); + } + +EXPORT_C TInt CSDL::SetBlitter(MBlitter* aBlitter) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + gEpocEnv->iDsa->SetBlitter(aBlitter); + return KErrNone; + } + return KErrNotReady; + } + + +EXPORT_C TInt CSDL::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->AppendOverlay(aOverlay, aPriority); + } + return KErrNotReady; + } + +EXPORT_C TInt CSDL::RemoveOverlay(MOverlay& aOverlay) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->RemoveOverlay(aOverlay); + } + return KErrNotReady; + } + +EXPORT_C TInt CSDL::RedrawRequest() + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->RedrawRequest(); + } + return KErrNotReady; + } + +/* +EXPORT_C CSDL* CSDL::Current() + { + return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL; + } + + +EXPORT_C TInt CSDL::SetVolume(TInt aVolume) + { + return EpocSdlEnv::SetVolume(aVolume); + } + +EXPORT_C TInt CSDL::Volume() const + { + return EpocSdlEnv::Volume(); + } + +EXPORT_C TInt CSDL::MaxVolume() const + { + return EpocSdlEnv::MaxVolume(); + } +*/ + +void EnvUtils::DisableKeyBlocking() + { + if(gEpocEnv->iAppUi != NULL) + return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking(); + } + +TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus) + { + if(gEpocEnv->iId != TThreadId(0) && + aThread.Open(gEpocEnv->iId) && + aThread.ExitType() == EExitPending) + { + aThread.Rendezvous(aStatus); + return ETrue; + } + return EFalse; + } + + + diff --git a/src/main/symbian/EKA2/sdlexe.cpp b/src/main/symbian/EKA2/sdlexe.cpp new file mode 100644 index 000000000..bb160c409 --- /dev/null +++ b/src/main/symbian/EKA2/sdlexe.cpp @@ -0,0 +1,809 @@ +// INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +// FORWARD DECLARATIONS +class CApaDocument; + + +//const TUid KSDLUID = { 0xF01F605E }; + +LOCAL_C void MakeCCmdLineL(const TDesC8& aParam, CDesC8Array& aArray) + { + + const TChar dq('\"'); + + TLex8 lex(aParam); + TBool in = EFalse; + + lex.SkipSpaceAndMark(); + + while(!lex.Eos()) + { + TPtrC8 ptr; + if(in) + { + const TPtrC8 rem = lex.RemainderFromMark(); + const TInt pos = rem.Locate(dq); + if(pos > 0) + { + lex.Inc(pos); + ptr.Set(lex.MarkedToken()); + lex.SkipAndMark(1); + } + else + { + ptr.Set(rem); + } + in = EFalse; + } + else + { + ptr.Set(lex.NextToken()); + const TInt pos = ptr.Locate(dq); + if(pos == 0) + { + lex.UnGetToMark(); + lex.SkipAndMark(1); + in = ETrue; + continue; // back to in brace + } + else + lex.SkipSpaceAndMark(); + } + + aArray.AppendL(ptr); + + } + } + +NONSHARABLE_CLASS(TVirtualCursor) : public MOverlay + { + public: + TVirtualCursor(); + void Set(const TRect& aRect, CFbsBitmap* aBmp, CFbsBitmap* aAlpha); + void Move(TInt aX, TInt aY); + void MakeEvent(TWsEvent& aEvent, const TPoint& aBasePos) const; + void Toggle(); + TBool IsOn() const; + private: + void Draw(CBitmapContext& aGc, const TRect& aTargetRect, const TSize& aSize); + private: + TRect iRect; + TPoint iInc; + TPoint iPos; + TBool iIsOn; + CFbsBitmap* iCBmp; + CFbsBitmap* iAlpha; + }; + + +TVirtualCursor::TVirtualCursor() : iInc(0, 0), iIsOn(EFalse), iCBmp(NULL) + { + } + +const TInt KMaxMove = 10; + +void TVirtualCursor::Move(TInt aX, TInt aY) + { + if(aX > 0 && iInc.iX > 0) + ++iInc.iX; + else if(aX < 0 && iInc.iX < 0) + --iInc.iX; + else + iInc.iX = aX; + + if(aY > 0 && iInc.iY > 0) + ++iInc.iY; + else if(aY < 0 && iInc.iY < 0) + --iInc.iY; + else + iInc.iY = aY; + + iInc.iX = Min(KMaxMove, iInc.iX); + + iInc.iX = Max(-KMaxMove, iInc.iX); + + iInc.iY = Min(KMaxMove, iInc.iY); + + iInc.iY =Max(-KMaxMove, iInc.iY); + + const TPoint pos = iPos + iInc; + if(iRect.Contains(pos)) + { + iPos = pos; + } + else + { + iInc = TPoint(0, 0); + } + } + + +void TVirtualCursor::Toggle() + { + iIsOn = !iIsOn; + } + + +TBool TVirtualCursor::IsOn() const + { + return iIsOn; + } + +void TVirtualCursor::Set(const TRect& aRect, CFbsBitmap* aBmp, CFbsBitmap* aAlpha) + { + iRect = aRect; + iCBmp = aBmp; + iAlpha = aAlpha; + } + + +void TVirtualCursor::MakeEvent(TWsEvent& aEvent, const TPoint& aBasePos) const + { + aEvent.SetType(EEventPointer), + aEvent.SetTimeNow(); + TPointerEvent& pointer = *aEvent.Pointer(); + pointer.iType = TPointerEvent::EButton1Down; + pointer.iPosition = iPos; + pointer.iParentPosition = aBasePos; + } + + +void TVirtualCursor::Draw(CBitmapContext& aGc, const TRect& /*aTargetRect*/, const TSize& /*aSize*/) + { + if(iIsOn && iCBmp != NULL) + { + const TRect rect(TPoint(0, 0), iCBmp->SizeInPixels()); + aGc.AlphaBlendBitmaps(iPos, iCBmp, rect, iAlpha, TPoint(0, 0)); + } + + } + +NONSHARABLE_CLASS(TSdlClass) + { + public: + TSdlClass(); + void SetMain(const TMainFunc& aFunc, TInt aFlags, MSDLMainObs* aObs, TInt aExeFlags); + TInt SdlFlags() const; + const TMainFunc& Main() const; + void SendEvent(TInt aEvent, TInt aParam, CSDL* aSDL); + TInt AppFlags() const; + void AppFlags(TInt aFlags); + private: + TMainFunc iFunc; + TInt iSdlFlags; + TInt iExeFlags; + MSDLMainObs* iObs; + }; + + +void TSdlClass::AppFlags(TInt aFlags) + { + iExeFlags |= aFlags; + } + +void TSdlClass::SendEvent(TInt aEvent, TInt aParam, CSDL* aSDL) + { + if(iObs != NULL) + iObs->SDLMainEvent(aEvent, aParam, aSDL); + } + +TInt TSdlClass::AppFlags() const + { + return iExeFlags; + } + +void TSdlClass::SetMain(const TMainFunc& aFunc, TInt aFlags, MSDLMainObs* aObs, TInt aExeFlags) + { + iFunc = aFunc; + iSdlFlags = aFlags; + iExeFlags = aExeFlags; + iObs = aObs; + } + +const TMainFunc& TSdlClass::Main() const + { + return iFunc; + } + + + TInt TSdlClass::SdlFlags() const + { + return iSdlFlags; + } + + + +TSdlClass::TSdlClass() + { + Mem::FillZ(this, sizeof(this)); + } + +TSdlClass gSDLClass; + + +//////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CSDLApplication) : public CAknApplication + { + public: + CSDLApplication(); + private: + CApaDocument* CreateDocumentL(); + TFileName ResourceFileName() const; + TUid AppDllUid() const; + void FindMeL(); + TUid iUid; + }; + +NONSHARABLE_CLASS(CSDLDocument) : public CEikDocument + { + public: + CSDLDocument(CEikApplication& aApp); + private: + CEikAppUi* CreateAppUiL(); + + }; + + //////////////////////////////////////////////////////////////////// + + +NONSHARABLE_CLASS(MExitWait) + { + public: + virtual void DoExit(TInt aErr) = 0; + }; + +///////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CExitWait) : public CActive + { + public: + CExitWait(MExitWait& aWait); + ~CExitWait(); + private: + void RunL(); + void DoCancel(); + private: + MExitWait& iWait; + TRequestStatus* iStatusPtr; + }; + +//////////////////////////////////////////////////////////////////////// + + +NONSHARABLE_CLASS(CSDLWin) : public CCoeControl + { + public: + void ConstructL(const TRect& aRect); + RWindow& GetWindow() const; + void SetNoDraw(); + private: + void Draw(const TRect& aRect) const; + private: + TBool iNoDraw; + }; + + +//////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CSDLAppUi) : public CAknAppUi, public MExitWait, MSDLObserver + { + public: + ~CSDLAppUi(); + private: // New functions + void ConstructL(); + void HandleCommandL(TInt aCommand); + void HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination); + void HandleResourceChangeL(TInt aType); + + void DoExit(TInt aErr); + + TInt SdlEvent(TInt aEvent, TInt aParam); + TInt SdlThreadEvent(TInt aEvent, TInt aParam); + + void StartL(); + static TBool StartL(TAny* aThis); + + TBool ParamEditorL(TDes& aCheat); + + TBool ProcessCommandParametersL(CApaCommandLine &aCommandLine); + + void PrepareToExit(); + void HandleConsoleWindowL(); + void HandleConsoleWindow(); + void HandleForegroundEventL(TBool aForeground); + + static TBool IdleRequestL(TAny* aThis); + + TBool HandleKeyL(const TWsEvent& aEvent); + + + private: + CExitWait* iWait; + CSDLWin* iSDLWin; + CSDL* iSdl; + CIdle* iStarter; + TBool iExitRequest; + CDesC8Array* iParams; + TInt iResOffset; + CIdle* iIdle; + TInt iStdOut; + TVirtualCursor iCursor; + CFbsBitmap* iCBmp; + CFbsBitmap* iAlpha; + // TTime iLastPress; + // CSDL::TOrientationMode iOrientation; + }; + +////////////////////////////////////////////////////////////////////////////////////////7 + +CApaDocument* CSDLApplication::CreateDocumentL() + { + return new (ELeave) CSDLDocument(*this); + } + +TUid CSDLApplication::AppDllUid() const + { + return iUid; + } + + +CSDLApplication::CSDLApplication() + { + TRAPD(err, FindMeL()); + ASSERT(err == KErrNone); + } + +void CSDLApplication::FindMeL() + { + RApaLsSession apa; + User::LeaveIfError(apa.Connect()); + CleanupClosePushL(apa); + User::LeaveIfError(apa.GetAllApps()); + TFileName name = RProcess().FileName(); + TApaAppInfo info; + while(apa.GetNextApp(info) == KErrNone) + { + if(info.iFullName.CompareF(name) == 0) + { + iUid = info.iUid; + break; + } + } + CleanupStack::PopAndDestroy(); + } + +TFileName CSDLApplication::ResourceFileName() const + { + return KNullDesC(); + } + +/////////////////////////////////////////////////////////////////////////////////////////// + +CExitWait::CExitWait(MExitWait& aWait) : CActive(CActive::EPriorityStandard), iWait(aWait) + { + CActiveScheduler::Add(this); + SetActive(); + iStatusPtr = &iStatus; + } + +CExitWait::~CExitWait() + { + Cancel(); + } + +void CExitWait::RunL() + { + if(iStatusPtr != NULL ) + iWait.DoExit(iStatus.Int()); + } + +void CExitWait::DoCancel() + { + if(iStatusPtr != NULL ) + User::RequestComplete(iStatusPtr , KErrCancel); + } + + +////////////////////////////////////////////////////////////////////////////////////////////// + +CSDLDocument::CSDLDocument(CEikApplication& aApp) : CEikDocument(aApp) + {} + +CEikAppUi* CSDLDocument::CreateAppUiL() + { + return new (ELeave) CSDLAppUi; + } + +/////////////////////////////////////////////////////////////////////////// + +void CSDLWin:: ConstructL(const TRect& aRect) + { + CreateWindowL(); + SetRect(aRect); + ActivateL(); + } + + +RWindow& CSDLWin::GetWindow() const + { + return Window(); + } + + +void CSDLWin::Draw(const TRect& /*aRect*/) const + { + if(!iNoDraw) + { + CWindowGc& gc = SystemGc(); + gc.SetPenStyle(CGraphicsContext::ESolidPen); + gc.SetPenColor(KRgbGray); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetBrushColor(0xaaaaaa); + gc.DrawRect(Rect()); + } + } + +void CSDLWin::SetNoDraw() + { + iNoDraw = ETrue; + } + +///////////////////////////////////////////////////////////////////////// + +CSDLAppUi::~CSDLAppUi() + { + if(iIdle) + iIdle->Cancel(); + delete iIdle; + if(iStarter != NULL) + iStarter->Cancel(); + delete iStarter; + delete iWait; + delete iSdl; + delete iSDLWin; + delete iParams; + delete iCBmp; + delete iAlpha; + } + + +void CSDLAppUi::ConstructL() + { + BaseConstructL(ENoAppResourceFile | ENoScreenFurniture); + + + RLibrary lib; + User::LeaveIfError(lib.Load(_L("sdlexe.dll"))); + TFileName name = lib.FileName(); + lib.Close(); + name.Replace(3, name.Length() - 3, _L("resource\\apps\\sdlexe.rsc")); + BaflUtils::NearestLanguageFile(iEikonEnv->FsSession(), name); + iResOffset = iCoeEnv->AddResourceFileL(name); + + name.Replace(name.Length() - 3, 3, _L("mbm")); + + TEntry e; + const TInt err = iEikonEnv->FsSession().Entry(name, e); + + iCBmp = iEikonEnv->CreateBitmapL(name, 0); + iAlpha = iEikonEnv->CreateBitmapL(name, 1); + + iIdle = CIdle::NewL(CActive::EPriorityIdle); + + iSDLWin = new (ELeave) CSDLWin; + iSDLWin->ConstructL(ApplicationRect()); + + iSdl = CSDL::NewL(gSDLClass.SdlFlags()); + + gSDLClass.SendEvent(MSDLMainObs::ESDLCreated, 0, iSdl); + + iSdl->SetObserver(this); + iSdl->DisableKeyBlocking(*this); + iSdl->SetContainerWindowL( + iSDLWin->GetWindow(), + iEikonEnv->WsSession(), + *iEikonEnv->ScreenDevice()); + iSdl->AppendOverlay(iCursor, 0); + + iCursor.Set(TRect(TPoint(0, 0), iSDLWin->Size()), iCBmp, iAlpha); + + iStarter = CIdle::NewL(CActive::EPriorityLow); + iStarter->Start(TCallBack(StartL, this)); + + + } + + + +TBool CSDLAppUi::StartL(TAny* aThis) + { + static_cast(aThis)->StartL(); + return EFalse; + } + + +void CSDLAppUi::PrepareToExit() + { + CAknAppUiBase::PrepareToExit(); //aknappu::PrepareToExit crashes + iCoeEnv->DeleteResourceFile(iResOffset); + } + +TBool CSDLAppUi::ProcessCommandParametersL(CApaCommandLine &aCommandLine) + { + const TPtrC8 cmdLine = aCommandLine.TailEnd(); + iParams = new (ELeave) CDesC8ArrayFlat(8); + MakeCCmdLineL(cmdLine, *iParams); + return EFalse; + } + + + TBool CSDLAppUi::ParamEditorL(TDes& aCheat) + { + CAknTextQueryDialog* query = CAknTextQueryDialog::NewL(aCheat); + CleanupStack::PushL(query); + query->SetPromptL(_L("Enter parameters")); + CleanupStack::Pop(); + return query->ExecuteLD(R_PARAMEDITOR); + } + + void CSDLAppUi::StartL() + { + if(gSDLClass.AppFlags() & SDLEnv::EParamQuery) + { + TBuf8<256> cmd; + RFile file; + TInt err = file.Open(iEikonEnv->FsSession(), _L("sdl_param.txt"),EFileRead); + if(err == KErrNone) + { + file.Read(cmd); + file.Close(); + MakeCCmdLineL(cmd, *iParams); + } + if(err != KErrNone || gSDLClass.AppFlags() & (SDLEnv::EParamQueryDialog ^ SDLEnv::EParamQuery)) + { + TBuf<256> buffer; + if(ParamEditorL(buffer)) + { + cmd.Copy(buffer); + MakeCCmdLineL(cmd, *iParams); + } + } + } + iWait = new (ELeave) CExitWait(*this); + iSdl->CallMainL(gSDLClass.Main(), &iWait->iStatus, iParams, CSDL::ENoParamFlags, 0xA000); + } + +void CSDLAppUi::HandleCommandL(TInt aCommand) + { + switch(aCommand) + { + case EAknSoftkeyBack: + case EAknSoftkeyExit: + case EAknCmdExit: + case EEikCmdExit: + gSDLClass.AppFlags(SDLEnv::EAllowConsoleView); + if(iWait == NULL || !iWait->IsActive() || iSdl == NULL) + { + Exit(); + } + else if(!iExitRequest) + { + iExitRequest = ETrue; //trick how SDL can be closed! + iSdl->Suspend(); + } + break; + } + } + + + +TBool CSDLAppUi::HandleKeyL(const TWsEvent& aEvent) + { + const TInt type = aEvent.Type(); + if(!(type == EEventKey || type == EEventKeyUp || type == EEventKeyDown)) + { + return ETrue; + } + const TKeyEvent& key = *aEvent.Key(); + if((key.iScanCode == EStdKeyYes) && (gSDLClass.AppFlags() & SDLEnv::EVirtualMouse)) + { + if(type == EEventKeyUp) + { + iCursor.Toggle(); + iSdl->RedrawRequest(); + } + return EFalse; + } + if(iCursor.IsOn()) + { + switch(key.iScanCode) + { + case EStdKeyUpArrow: + iCursor.Move(0, -1); + break; + case EStdKeyDownArrow: + iCursor.Move(0, 1); + break; + case EStdKeyLeftArrow: + iCursor.Move(-1, 0); + break; + case EStdKeyRightArrow: + iCursor.Move(1, 0); + break; + case EStdKeyDevice3: + if(type == EEventKeyUp) + { + TWsEvent event; + iCursor.MakeEvent(event, iSDLWin->Position()); + iSdl->AppendWsEvent(event); + } + return EFalse; + default: + return ETrue; + } + iSdl->RedrawRequest(); + return EFalse; + } + return ETrue; + } + + void CSDLAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination) + { + if(iSdl && iWait && HandleKeyL(aEvent)) + iSdl->AppendWsEvent(aEvent); + CAknAppUi::HandleWsEventL(aEvent, aDestination); + } + + void CSDLAppUi::HandleResourceChangeL(TInt aType) + { + CAknAppUi::HandleResourceChangeL(aType); + if(aType == KEikDynamicLayoutVariantSwitch) + { + iSDLWin->SetRect(ApplicationRect()); + iSdl->SetContainerWindowL( + iSDLWin->GetWindow(), + iEikonEnv->WsSession(), + *iEikonEnv->ScreenDevice()); + } + } + + +void CSDLAppUi::DoExit(TInt/*Err*/) + { + iExitRequest = ETrue; + Exit(); + } + + + TInt CSDLAppUi::SdlThreadEvent(TInt aEvent, TInt /*aParam*/) + { + switch(aEvent) + { + case MSDLObserver::EEventResume: + break; + case MSDLObserver::EEventSuspend: + if(iExitRequest) + return MSDLObserver::ESuspendNoSuspend; + break; + case MSDLObserver::EEventWindowReserved: + break; + case MSDLObserver::EEventWindowNotAvailable: + break; + case MSDLObserver::EEventScreenSizeChanged: + break; + } + return MSDLObserver::EParameterNone; + } + +TInt CSDLAppUi::SdlEvent(TInt aEvent, TInt /*aParam*/) + { + switch(aEvent) + { + case MSDLObserver::EEventResume: + break; + case MSDLObserver::EEventSuspend: + if(iExitRequest) + return MSDLObserver::ESuspendNoSuspend; + break; + case MSDLObserver::EEventWindowReserved: + break; + case MSDLObserver::EEventWindowNotAvailable: + { + TRAP_IGNORE(HandleConsoleWindowL()); + } + break; + case MSDLObserver::EEventScreenSizeChanged: + break; + case MSDLObserver::EEventKeyMapInit: + break; + case MSDLObserver::EEventMainExit: + if(iStdOut != 0) + { + gSDLClass.AppFlags(SDLEnv::EAllowConsoleView); + iEikonEnv->WsSession().SetWindowGroupOrdinalPosition(iStdOut, 0); + } + break; + } + return MSDLObserver::EParameterNone; + } + +void CSDLAppUi::HandleForegroundEventL(TBool aForeground) + { + CAknAppUi::HandleForegroundEventL(aForeground); + if(!aForeground) + HandleConsoleWindow(); + } + +void CSDLAppUi::HandleConsoleWindow() + { + if(!iIdle->IsActive()) + iIdle->Start(TCallBack(IdleRequestL, this)); + } + +TBool CSDLAppUi::IdleRequestL(TAny* aThis) + { + static_cast(aThis)->HandleConsoleWindowL(); + return EFalse; + } + +void CSDLAppUi::HandleConsoleWindowL() + { + if(gSDLClass.AppFlags() & SDLEnv::EAllowConsoleView) + { + return; + } + RWsSession& ses = iEikonEnv->WsSession(); + const TInt focus = ses.GetFocusWindowGroup(); + CApaWindowGroupName* name = CApaWindowGroupName::NewLC(ses, focus); + const TPtrC caption = name->Caption(); + if(0 == caption.CompareF(_L("STDOUT"))) + { + iStdOut = focus; + ses.SetWindowGroupOrdinalPosition(iEikonEnv->RootWin().Identifier(), 0); + } + CleanupStack::PopAndDestroy(); //name + } + + +//////////////////////////////////////////////////////////////////////// + + +CApaApplication* NewApplication() + { + return new CSDLApplication(); + } + + +EXPORT_C TInt SDLEnv::SetMain(const TMainFunc& aFunc, TInt aSdlFlags, MSDLMainObs* aObs, TInt aSdlExeFlags) + { + gSDLClass.SetMain(aFunc, aSdlFlags, aObs, aSdlExeFlags); + return EikStart::RunApplication(NewApplication); + } + +////////////////////////////////////////////////////////////////////// + +TInt SDLUiPrint(const TDesC8& /*aInfo*/) + { + return KErrNotFound; + } + + + diff --git a/src/main/symbian/EKA2/sdllib.cpp b/src/main/symbian/EKA2/sdllib.cpp new file mode 100644 index 000000000..7c09996ec --- /dev/null +++ b/src/main/symbian/EKA2/sdllib.cpp @@ -0,0 +1,12 @@ +#include +#include +#include + + +GLREF_C TInt E32Main() + { + return SDLEnv::SetMain(SDL_main, CSDL::EEnableFocusStop | CSDL::EAllowImageResize, + NULL, SDLEnv::EParamQuery | SDLEnv::EVirtualMouse); + } + + \ No newline at end of file diff --git a/src/main/symbian/EKA2/vectorbuffer.cpp b/src/main/symbian/EKA2/vectorbuffer.cpp new file mode 100644 index 000000000..72c3b3e5c --- /dev/null +++ b/src/main/symbian/EKA2/vectorbuffer.cpp @@ -0,0 +1,62 @@ +/* + vectorbuffer.cpp + yet another circle buffer + + Markus Mertama +*/ + +#include"vectorbuffer.h" + + + +void VectorPanic(TInt aErr, TInt aLine) + { + TBuf<64> b; + b.Format(_L("vector buffer at % d "), aLine); + User::Panic(b, aErr); + } + +void TNodeBuffer::TNode::Terminator(TNodeBuffer::TNode* aNode) + { + Mem::Copy(iSucc, &aNode, sizeof(TNode*)); + } + +TInt TNodeBuffer::TNode::Size() const + { + return reinterpret_cast(iSucc) - Ptr(); + } + +const TUint8* TNodeBuffer::TNode::Ptr() const + { + return reinterpret_cast(this) + sizeof(TNode); + } + +TNodeBuffer::TNode* TNodeBuffer::TNode::Empty(TUint8* aBuffer) + { + TNode* node = reinterpret_cast(aBuffer); + node->iSucc = node + 1; + return node; + } + + TNodeBuffer::TNode* TNodeBuffer::TNode::New(TNode* aPred, const TDesC8& aData) + { + TNode* node = aPred->Size() == 0 ? aPred : aPred->iSucc; + + + TUint8* start = reinterpret_cast(node) + sizeof(TNode); + node->iSucc = reinterpret_cast(start + aData.Size()); + node->iSucc->iSucc = NULL; //terminator + + __ASSERT_DEBUG(node->Size() == aData.Size(), VECPANIC(KErrCorrupt)); + + Mem::Copy(start, aData.Ptr(), aData.Size()); + return node; + } + + + + + + + + \ No newline at end of file diff --git a/src/main/symbian/EKA2/vectorbuffer.h b/src/main/symbian/EKA2/vectorbuffer.h new file mode 100644 index 000000000..3d8be58d6 --- /dev/null +++ b/src/main/symbian/EKA2/vectorbuffer.h @@ -0,0 +1,240 @@ +/* + vectorbuffer.cpp + yet another circle buffer + + Markus Mertama +*/ + +#ifndef __VECTORBUFFER_H__ +#define __VECTORBUFFER_H__ + +#include +#define VLOG(x) +#define VECPANIC(x) VectorPanic(x, __LINE__) +void VectorPanic(TInt, TInt); + + +//int DEBUG_INT; + +NONSHARABLE_CLASS(TNodeBuffer) + { + public: + protected: + NONSHARABLE_CLASS(TNode) + { + public: + static TNode* Empty(TUint8* iBuffer); + static TNode* New(TNode* aPrev, const TDesC8& aData); + const TUint8* Ptr() const; + TInt Size() const; + inline TNode* Succ(); + static void SetSucc(TNode*& aNode); + void Terminator(TNode* aNode); + private: + TNode* iSucc; + }; + }; + +inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ() + { + return iSucc; + } + +template +NONSHARABLE_CLASS(TVectorBuffer) : public TNodeBuffer + { + public: + TVectorBuffer(); + TInt Append(const TDesC8& aData); + // TInt AppendOverwrite(const TDesC8& aData); + TPtrC8 Shift(); + TPtrC8 operator[](TInt aIndex) const; + TInt Size() const; + private: + TInt GetRoom(TInt aSize) const; + TInt Unreserved() const; + private: + TNode* iTop; + TNode* iBottom; + TInt iSize; + TUint8 iBuffer[C]; + }; + +template +TVectorBuffer::TVectorBuffer() : iSize(0) + { + Mem::FillZ(iBuffer, C); + iTop = TNode::Empty(iBuffer); //these points to buffer + iBottom = TNode::Empty(iBuffer); + } + +template +TInt TVectorBuffer::Unreserved() const + { + __ASSERT_DEBUG(iBottom < iBottom->Succ(), VECPANIC(KErrCorrupt)); + const TInt bytesbetween = + reinterpret_cast(iBottom->Succ()) - + reinterpret_cast(iTop); + const TInt topsize = sizeof(TNode); + if(bytesbetween > 0) //bytesbetween is room between bottom and top + { //therefore free room is subracted from free space + + const TInt room = C - bytesbetween - topsize; + return room; + } + if(bytesbetween == 0) + { + + if(Size() > 0) + return 0; + else + return C - topsize; + } + const TInt room = -bytesbetween - topsize; //free is space between pointers + return room; + } + +template +TInt TVectorBuffer::GetRoom(TInt aSize) const + { + const TInt bytesnew = sizeof(TNode) + aSize; + const TInt room = Unreserved() - bytesnew; + return room; + } + +template +TInt TVectorBuffer::Append(const TDesC8& aData) //ei ole ok! + { + const TInt len = aData.Length(); + if(GetRoom(len) < 0) + { + return KErrOverflow; + } + if(iBottom->Succ()->Ptr() - iBuffer > (C - (len + TInt(sizeof(TNode))))) + { + VLOG("rc"); + // RDebug::Print(_L("vector: append")); + TNode* p = TNode::Empty(iBuffer); + iBottom->Terminator(p); + iBottom = p; + return Append(aData); + // Append(); + // iBottom = TNode::New(p, aData); //just append something into end + } + + //DEBUG_INT++; + + iBottom = TNode::New(iBottom, aData); + + iSize += len; + return KErrNone; + } + +/* +template +TInt TVectorBuffer::AppendOverwrite(const TDesC8& aData) //ei ole ok! + { + while(Append(aData) == KErrOverflow) + { + if(iTop->Succ() == NULL) + { + return KErrUnderflow; + } + //Shift(); //data is lost + } + return KErrNone; + } +*/ +template +TPtrC8 TVectorBuffer::Shift() + { + __ASSERT_ALWAYS(iTop->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom + TNode* node = iTop; + iTop = iTop->Succ(); + if(iTop > node) + { + // DEBUG_INT--; + iSize -= node->Size(); + return TPtrC8(node->Ptr(), node->Size()); + } + else + { + // RDebug::Print(_L("vector: shift")); + return Shift(); //this happens when buffer is terminated, and data lies in next + } + } + +template +TInt TVectorBuffer::Size() const + { + return iSize; + } + +template +TPtrC8 TVectorBuffer::operator[](TInt aIndex) const + { + TInt index = 0; + TNode* t = iTop->Size() > 0 ? iTop : iTop->Succ(); //eliminate terminator + while(index < aIndex) + { + TNode* nt = t->Succ(); + if(nt < t) + { + nt = nt->Succ(); + } + t = nt; + if(t->Size() > 0) + index++; + __ASSERT_ALWAYS(t->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom + } + return t->Ptr(); + } + + +template +NONSHARABLE_CLASS(TVector) : public TVectorBuffer + { + public: + TVector(); + TInt Append(const T& aData); + const T& Shift(); + TInt Size() const; + const T& operator[](TInt aIndex) const; + }; + +template +TVector::TVector() : TVectorBuffer() + { + } + +template +TInt TVector::Append(const T& aData) + { + const TPckgC data(aData); + return TVectorBuffer::Append(data); + } + +template +const T& TVector::Shift() + { + const TPtrC8 ptr = TVectorBuffer::Shift(); + return *(reinterpret_cast(ptr.Ptr())); + } + + +template +TInt TVector::Size() const + { + return TVectorBuffer::Size() / sizeof(T); + } + +template +const T& TVector::operator[](TInt aIndex) const + { + const TPtrC8 ptr = TVectorBuffer::operator[](aIndex); + return *(reinterpret_cast(ptr.Ptr())); + } + +#endif + + diff --git a/src/stdlib/SDL_getenv.c b/src/stdlib/SDL_getenv.c index 74116cc97..d52707ab5 100644 --- a/src/stdlib/SDL_getenv.c +++ b/src/stdlib/SDL_getenv.c @@ -25,7 +25,7 @@ #ifndef HAVE_GETENV -#if defined(__WIN32__) && !defined(_WIN32_WCE) +#if defined(__WIN32__) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) #define WIN32_LEAN_AND_MEAN #include diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h index 6f83bea46..472d8a071 100644 --- a/src/thread/SDL_thread_c.h +++ b/src/thread/SDL_thread_c.h @@ -31,8 +31,6 @@ #include "beos/SDL_systhread_c.h" #elif SDL_THREAD_DC #include "dc/SDL_systhread_c.h" -#elif SDL_THREAD_EPOC -#include "epoc/SDL_systhread_c.h" #elif SDL_THREAD_OS2 #include "os2/SDL_systhread_c.h" #elif SDL_THREAD_PTH @@ -43,6 +41,8 @@ #include "irix/SDL_systhread_c.h" #elif SDL_THREAD_WIN32 #include "win32/SDL_systhread_c.h" +#elif SDL_THREAD_SYMBIAN +#include "symbian/SDL_systhread_c.h" #else #error Need thread implementation for this platform #include "generic/SDL_systhread_c.h" diff --git a/src/thread/symbian/SDL_sysmutex.cpp b/src/thread/symbian/SDL_sysmutex.cpp new file mode 100644 index 000000000..ac20744a4 --- /dev/null +++ b/src/thread/symbian/SDL_sysmutex.cpp @@ -0,0 +1,130 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_sysmutex.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_sysmutex.c,v 1.1.2.3 2000/06/22 15:25:23 hercules Exp $"; +#endif + +/* Mutex functions using the Win32 API */ + +//#include +//#include + +#include + +#include "epoc_sdl.h" + +#include "SDL_error.h" +#include "SDL_mutex.h" + + +#ifdef EKA2 //??? +struct SDL_mutex + { + TInt handle; + }; +#else +struct _SDL_mutex + { + TInt handle; + }; +#endif + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); + +TInt NewMutex(const TDesC& aName, TAny* aPtr1, TAny*) + { + return ((RMutex*)aPtr1)->CreateGlobal(aName); + } + +void DeleteMutex(TAny* aMutex) + { + SDL_DestroyMutex ((SDL_mutex*) aMutex); + } + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + RMutex rmutex; + + TInt status = CreateUnique(NewMutex, &rmutex, NULL); + if(status != KErrNone) + { + SDL_SetError("Couldn't create mutex"); + } + SDL_mutex* mutex = new /*(ELeave)*/ SDL_mutex; + mutex->handle = rmutex.Handle(); + EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem(DeleteMutex, mutex)); + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) + { + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + if(rmutex.IsHeld()) + { + rmutex.Signal(); + } + rmutex.Close(); + EpocSdlEnv::RemoveCleanupItem(mutex); + delete(mutex); + mutex = NULL; + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Wait(); + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Signal(); + return(0); +} diff --git a/src/thread/symbian/SDL_syssem.cpp b/src/thread/symbian/SDL_syssem.cpp new file mode 100644 index 000000000..55036952b --- /dev/null +++ b/src/thread/symbian/SDL_syssem.cpp @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_syssem.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_syssem.c,v 1.1.2.4 2000/06/22 15:24:48 hercules Exp $"; +#endif + +/* Semaphore functions using the Win32 API */ + +//#include +//#include +#include + +#include "SDL_error.h" +#include "SDL_thread.h" + + +#define SDL_MUTEX_TIMEOUT -2 + +struct SDL_semaphore + { + TInt handle; + TInt count; + }; + + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); +#ifndef EKA2 +extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2); +#endif + +TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + TInt value = *((TInt*) aPtr2); + return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value); + } + +/* Create a semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + RSemaphore s; + TInt status = CreateUnique(NewSema, &s, &initial_value); + if(status != KErrNone) + { + SDL_SetError("Couldn't create semaphore"); + } + SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore; + sem->handle = s.Handle(); + sem->count = initial_value; + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) + { + RSemaphore sema; + sema.SetHandle(sem->handle); + while(--sem->count) + sema.Signal(); + sema.Close(); + delete sem; + sem = NULL; + } +} + +#ifndef EKA2 + + struct TInfo + { + TInfo(TInt aTime, TInt aHandle) : + iTime(aTime), iHandle(aHandle), iVal(0) {} + TInt iTime; + TInt iHandle; + TInt iVal; + }; + + + +TBool ThreadRun(TAny* aInfo) + { + TInfo* info = STATIC_CAST(TInfo*, aInfo); + User::After(info->iTime); + RSemaphore sema; + sema.SetHandle(info->iHandle); + sema.Signal(); + info->iVal = SDL_MUTEX_TIMEOUT; + return 0; + } + +#endif + + +void _WaitAll(SDL_sem *sem) + { + //since SemTryWait may changed the counter. + //this may not be atomic, but hopes it works. + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Wait(); + while(sem->count < 0) + { + sema.Wait(); + } + } + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) + { + _WaitAll(sem); + return SDL_MUTEX_MAXWAIT; + } + +#ifdef EKA2 + + RSemaphore sema; + sema.SetHandle(sem->handle); + if(KErrNone == sema.Wait(timeout)) + return 0; + return -1; +#else + RThread thread; + + TInfo* info = new (ELeave)TInfo(timeout, sem->handle); + + TInt status = CreateUnique(NewThread, &thread, info); + + if(status != KErrNone) + return status; + + thread.Resume(); + + _WaitAll(sem); + + if(thread.ExitType() == EExitPending) + { + thread.Kill(SDL_MUTEX_TIMEOUT); + } + + thread.Close(); + + return info->iVal; +#endif +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + if(sem->count > 0) + { + sem->count--; + } + return SDL_MUTEX_TIMEOUT; +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return sem->count; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + sem->count++; + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Signal(); + return 0; +} diff --git a/src/thread/symbian/SDL_systhread.cpp b/src/thread/symbian/SDL_systhread.cpp new file mode 100644 index 000000000..180391868 --- /dev/null +++ b/src/thread/symbian/SDL_systhread.cpp @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread.cpp + Epoc thread management routines for SDL + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#include "epoc_sdl.h" + +//#include +//#include + + + +extern "C" { +#undef NULL +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_systhread.h" +#include "SDL_thread_c.h" + } + +#include +#include "epoc_sdl.h" + + +static int object_count; + +int RunThread(TAny* data) +{ + CTrapCleanup* cleanup = CTrapCleanup::New(); + TRAPD(err, SDL_RunThread(data)); + EpocSdlEnv::CleanupItems(); + delete cleanup; + return(err); +} + + +TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + return ((RThread*)(aPtr1))->Create(aName, + RunThread, + KDefaultStackSize, + NULL, + aPtr2); + } + +int CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny* aPtr1, TAny* aPtr2) + { + TBuf<16> name; + TInt status = KErrNone; + do + { + object_count++; + name.Format(_L("SDL_%x"), object_count); + status = aFunc(name, aPtr1, aPtr2); + } + while(status == KErrAlreadyExists); + return status; + } + + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + RThread rthread; + + const TInt status = CreateUnique(NewThread, &rthread, args); + if (status != KErrNone) + { + delete(((RThread*)(thread->handle))); + thread->handle = NULL; + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + rthread.Resume(); + thread->handle = rthread.Handle(); + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + RThread current; + const TThreadId id = current.Id(); + return id; +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + SDL_TRACE1("Close thread", thread); + RThread t; + const TInt err = t.Open(thread->threadid); + if(err == KErrNone && t.ExitType() == EExitPending) + { + TRequestStatus status; + t.Logon(status); + User::WaitForRequest(status); + } + t.Close(); + + /* RUndertaker taker; + taker.Create(); + TRequestStatus status; + taker.Logon(status, thread->handle); + User::WaitForRequest(status); + taker.Close();*/ + SDL_TRACE1("Closed thread", thread); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + RThread rthread; + rthread.SetHandle(thread->handle); + rthread.Kill(0); + rthread.Close(); +} diff --git a/src/thread/symbian/SDL_systhread_c.h b/src/thread/symbian/SDL_systhread_c.h new file mode 100644 index 000000000..be8b164c1 --- /dev/null +++ b/src/thread/symbian/SDL_systhread_c.h @@ -0,0 +1,30 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread_c.h + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +typedef int SYS_ThreadHandle; + diff --git a/src/timer/symbian/SDL_systimer.cpp b/src/timer/symbian/SDL_systimer.cpp new file mode 100644 index 000000000..f2fba3214 --- /dev/null +++ b/src/timer/symbian/SDL_systimer.cpp @@ -0,0 +1,114 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systimer.cpp + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) + Markus Mertama +*/ + +#include +#include + +extern "C" { +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_timer_c.h" + +static TUint start = 0; +static TInt tickPeriodMilliSeconds; + + +void SDL_StartTicks(void) + { + /* Set first ticks value */ + start = User::TickCount(); + + TTimeIntervalMicroSeconds32 period; + TInt tmp = UserHal::TickPeriod(period); + tickPeriodMilliSeconds = period.Int() / 1000; + } + +Uint32 SDL_GetTicks(void) + { + TUint deltaTics = User::TickCount() - start; + return(deltaTics * tickPeriodMilliSeconds); + } + +void SDL_Delay(Uint32 ms) + { + User::After(TTimeIntervalMicroSeconds32(ms*1000)); + } + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) + { + while ( timer_alive ) + { + if (SDL_timer_running) + { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(10); + } + return(0); + } + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) + { + if(timer != NULL) + return (-1); + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); + } + +void SDL_SYS_TimerQuit(void) + { + timer_alive = 0; + if ( timer ) + { + SDL_WaitThread(timer, NULL); + timer = NULL; + } + } + +int SDL_SYS_StartTimer(void) + { + SDL_SetError("Internal logic error: Epoc uses threaded timer"); + return(-1); + } + +void SDL_SYS_StopTimer(void) + { + return; + } + +} // extern "C" diff --git a/src/video/symbian/EKA1/SDL_epocevents.cpp b/src/video/symbian/EKA1/SDL_epocevents.cpp new file mode 100644 index 000000000..159193342 --- /dev/null +++ b/src/video/symbian/EKA1/SDL_epocevents.cpp @@ -0,0 +1,626 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents.cpp + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) +*/ + + +#include +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +}; /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include +#include + + +#include + +extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +}; /* extern "C" */ + +TBool isCursorVisible = EFalse; + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { + + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } + + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + TPoint mousePos = pointerEvent->iPosition; + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->EPOC_IsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { +/* + CFbsBitmap* bmp = new (ELeave) CFbsBitmap(); + bmp->Create(Private->EPOC_ScreenSize, Private->EPOC_DisplayMode); + Private->EPOC_WsScreen->CopyScreenToBitmap(bmp); + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + Private->EPOC_WsWindow.BeginRedraw(TRect(Private->EPOC_WsWindow.Size())); + Private->EPOC_WindowGc->BitBlt(TPoint(0, 0), bmp); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + bmp->Save(_L("C:\\scr.mbm")); + delete bmp; +*/ + + Private->EPOC_IsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + RWsSession s; + s.Connect(); + RWindowGroup g(s); + g.Construct(TUint32(&g), EFalse); + g.EnableReceiptOfFocus(EFalse); + RWindow w(s); + w.Construct(g, TUint32(&w)); + w.SetExtent(TPoint(0, 0), Private->EPOC_WsWindow.Size()); + w.SetOrdinalPosition(0); + w.Activate(); + w.Close(); + g.Close(); + s.Close(); + +/* + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(Private->EPOC_WsWindowGroupID, -1); + + + SDL_Delay(500); + TInt focus = -1; + while(focus < 0) + { + const TInt curr = Private->EPOC_WsSession.GetFocusWindowGroup(); + if(curr != Private->EPOC_WsWindowGroupID) + focus = curr; + else + SDL_Delay(500); + } + + if(1 < Private->EPOC_WsSession.GetWindowGroupOrdinalPriority(Private->EPOC_WsWindowGroupID)) + { + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, -1); + SDL_Delay(500); + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, 0); + } +*/ + /*//and the request redraw + TRawEvent redrawEvent; + redrawEvent.Set(TRawEvent::ERedraw); + Private->EPOC_WsSession.SimulateRawEvent(redrawEvent); + Private->EPOC_WsSession.Flush();*/ +#if 0 + //!! Not used + // Wait and eat events until focus is gained again + while (ETrue) { + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + User::WaitForRequest(Private->EPOC_WsEventStatus); + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + TInt eventType = Private->EPOC_WsEvent.Type(); + Private->EPOC_WsEventStatus = KRequestPending; + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + if (eventType == EEventFocusGained) { + RedrawWindowL(_this); + break; + } + } +#endif + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) +{ + int posted = 0; // !! Do we need this? + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + while (Private->EPOC_WsEventStatus != KRequestPending) { + + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + posted = EPOC_HandleWsEvent(_this, Private->EPOC_WsEvent); + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + } +} + + +_LIT(KMapFileName, "C:\\sdl_info\\sdlkeymap.cfg"); +LOCAL_C void ReadL(RFs& aFs, RArray& aArray) + { + TInt drive = -1; + TFileName name(KMapFileName); + for(TInt i = 'z'; drive < 0 && i >= 'a'; i--) + { + name[0] = (TUint16)i; + if(BaflUtils::FileExists(aFs, name)) + drive = i; + } + if(drive < 0) + return; + CLineReader* reader = CLineReader::NewLC(aFs, name); + while(reader->NextL()) + { + TPtrC ln = reader->Current(); + TLex line(ln); + TInt n = 0; + for(;;) + { + const TPtrC token = line.NextToken(); + if(token.Length() == 0) + break; + if((n & 1) != 0) + { + TInt value; + TLex lex(token); + User::LeaveIfError(lex.Val(value)); + User::LeaveIfError(aArray.Append(value)); + } + n++; + } + } + CleanupStack::PopAndDestroy(); + } + + +void EPOC_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the key translation table */ + for ( i=0; i array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close(); + /////////////////////////////////////////////////////////// + + /* !!TODO + EStdKeyNumLock=0x1b, + EStdKeyScrollLock=0x1c, + + EStdKeyNkpForwardSlash=0x84, + EStdKeyNkpAsterisk=0x85, + EStdKeyNkpMinus=0x86, + EStdKeyNkpPlus=0x87, + EStdKeyNkpEnter=0x88, + EStdKeyNkp1=0x89, + EStdKeyNkp2=0x8a, + EStdKeyNkp3=0x8b, + EStdKeyNkp4=0x8c, + EStdKeyNkp5=0x8d, + EStdKeyNkp6=0x8e, + EStdKeyNkp7=0x8f, + EStdKeyNkp8=0x90, + EStdKeyNkp9=0x91, + EStdKeyNkp0=0x92, + EStdKeyNkpFullStop=0x93, + EStdKeyMenu=0x94, + EStdKeyBacklightOn=0x95, + EStdKeyBacklightOff=0x96, + EStdKeyBacklightToggle=0x97, + EStdKeyIncContrast=0x98, + EStdKeyDecContrast=0x99, + EStdKeySliderDown=0x9a, + EStdKeySliderUp=0x9b, + EStdKeyDictaphonePlay=0x9c, + EStdKeyDictaphoneStop=0x9d, + EStdKeyDictaphoneRecord=0x9e, + EStdKeyHelp=0x9f, + EStdKeyOff=0xa0, + EStdKeyDial=0xa1, + EStdKeyIncVolume=0xa2, + EStdKeyDecVolume=0xa3, + EStdKeyDevice0=0xa4, + EStdKeyDevice1=0xa5, + EStdKeyDevice2=0xa6, + EStdKeyDevice3=0xa7, + EStdKeyDevice4=0xa8, + EStdKeyDevice5=0xa9, + EStdKeyDevice6=0xaa, + EStdKeyDevice7=0xab, + EStdKeyDevice8=0xac, + EStdKeyDevice9=0xad, + EStdKeyDeviceA=0xae, + EStdKeyDeviceB=0xaf, + EStdKeyDeviceC=0xb0, + EStdKeyDeviceD=0xb1, + EStdKeyDeviceE=0xb2, + EStdKeyDeviceF=0xb3, + EStdKeyApplication0=0xb4, + EStdKeyApplication1=0xb5, + EStdKeyApplication2=0xb6, + EStdKeyApplication3=0xb7, + EStdKeyApplication4=0xb8, + EStdKeyApplication5=0xb9, + EStdKeyApplication6=0xba, + EStdKeyApplication7=0xbb, + EStdKeyApplication8=0xbc, + EStdKeyApplication9=0xbd, + EStdKeyApplicationA=0xbe, + EStdKeyApplicationB=0xbf, + EStdKeyApplicationC=0xc0, + EStdKeyApplicationD=0xc1, + EStdKeyApplicationE=0xc2, + EStdKeyApplicationF=0xc3, + EStdKeyYes=0xc4, + EStdKeyNo=0xc5, + EStdKeyIncBrightness=0xc6, + EStdKeyDecBrightness=0xc7, + EStdKeyCaseOpen=0xc8, + EStdKeyCaseClose=0xc9 + */ + +} + + + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +}; /* extern "C" */ + + diff --git a/src/video/symbian/EKA1/SDL_epocvideo.cpp b/src/video/symbian/EKA1/SDL_epocvideo.cpp new file mode 100644 index 000000000..b944dfc9a --- /dev/null +++ b/src/video/symbian/EKA1/SDL_epocvideo.cpp @@ -0,0 +1,1356 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Thanks to Peter van Sebille, the author of EMame. It is a great example of + low level graphics coding in Epoc. + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) + Assembler routines by Kimmo Kinnunen +*/ + + + +#include +#include +#include + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +}; + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdl_epocruntime.h" + +#include +#include +#include + +#ifdef SYMBIAN_QUARTZ +SDL_VideoDevice* _thisDevice; +#endif + +_LIT(KLibName, "SDL"); + +/* For debugging */ + +//if old SOS, from 7.x this is public! +class CLockable : public CFbsBitmap + { + public: + static CLockable* Lockable(CFbsBitmap* aBmp) {return static_cast(aBmp);} + void Lock() {LockHeap();} + void Unlock() {UnlockHeap();} + }; +#define LockHeap(x) CLockable::Lockable(x)->Lock() +#define UnlockHeap(x) CLockable::Lockable(x)->Unlock() + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + + +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); + + + +/* !!For 12 bit screen HW. Table for fast conversion from 8 bit to 12 bit */ +// TUint16 is enough, but using TUint32 so we can use better instruction selection on ARMI +static TUint32 EPOC_HWPalette_256_to_Screen[256]; + +VideoBootStrap EPOC_bootstrap = { + "epoc", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + +const TUint32 WindowClientHandle = 9210; //!! const + +/* Epoc video driver bootstrap functions */ + +static int EPOC_Available(void) +{ + return 1; /* Always available */ +} + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) +{ + free(device->hidden); + free(device); +} + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) +{ + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +int GetBpp(TDisplayMode displaymode) +{ + /*TInt numColors = TDisplayModeUtils::NumDisplayModeColors(displaymode); + TInt bitsPerPixel = 1; + for (TInt32 i = 2; i < numColors; i <<= 1, bitsPerPixel++); + return bitsPerPixel;*/ + return TDisplayModeUtils::NumDisplayModeBitsPerPixel(displaymode); +} + + +void DisableKeyBlocking(_THIS) + { + // Disable key blocking + TRawEvent event; + event.Set((TRawEvent::TType)/*EDisableKeyBlock*/51); // !!EDisableKeyBlock not found in epoc32\include! + Private->EPOC_WsSession.SimulateRawEvent(event); + } + +void ConstructWindowL(_THIS) +{ + TInt error; + + SDL_TRACE("SDL:ConstructWindowL"); + error = Private->EPOC_WsSession.Connect(); + User::LeaveIfError(error); + Private->EPOC_WsScreen=new(ELeave) CWsScreenDevice(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsScreen->Construct()); + User::LeaveIfError(Private->EPOC_WsScreen->CreateContext(Private->EPOC_WindowGc)); + + Private->EPOC_WsWindowGroup=RWindowGroup(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsWindowGroup.Construct(WindowClientHandle)); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0); + + // Set window group name (the same as process name)) !!Gives always "EPOC" in WINS + RProcess thisProcess; + TParse exeName; + exeName.Set(thisProcess.FileName(), NULL, NULL); + TBuf<32> winGroupName; + winGroupName.Append(0); + winGroupName.Append(0); + winGroupName.Append(0);// uid + winGroupName.Append(0); + winGroupName.Append(exeName.Name()); // caption + winGroupName.Append(0); + winGroupName.Append(0); //doc name + Private->EPOC_WsWindowGroup.SetName(winGroupName); + + Private->EPOC_WsWindow=RWindow(Private->EPOC_WsSession); + // Markus, it was: + // User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle )); + // but SOS 7.0s debug does not accept same window handle twice + User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle - 1)); + Private->EPOC_WsWindow.SetBackgroundColor(KRgbWhite); + Private->EPOC_WsWindow.Activate(); + Private->EPOC_WsWindow.SetSize(Private->EPOC_WsScreen->SizeInPixels()); + Private->EPOC_WsWindow.SetVisible(ETrue); + + Private->EPOC_WsWindowGroupID = Private->EPOC_WsWindowGroup.Identifier(); + Private->EPOC_IsWindowFocused = EFalse; + + DisableKeyBlocking(_this); //disable key blocking +} + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + // !!TODO:handle leave functions! + + int i; + + SDL_TRACE("SDL:EPOC_VideoInit"); + + /* Initialize all variables that we clean on shutdown */ + + for ( i=0; iSDL_modelist[i] = (SDL_Rect *)malloc(sizeof(SDL_Rect)); + Private->SDL_modelist[i]->x = Private->SDL_modelist[i]->y = 0; + } + + /* Modes sorted largest to smallest */ + Private->SDL_modelist[0]->w = 800; Private->SDL_modelist[0]->h = 250; + Private->SDL_modelist[1]->w = 640; Private->SDL_modelist[1]->h = 480; + Private->SDL_modelist[2]->w = 480; Private->SDL_modelist[2]->h = 600; + Private->SDL_modelist[3]->w = 640; Private->SDL_modelist[3]->h = 400; + Private->SDL_modelist[4]->w = 352; Private->SDL_modelist[4]->h = 416; + Private->SDL_modelist[5]->w = 416; Private->SDL_modelist[5]->h = 352; + Private->SDL_modelist[6]->w = 416; Private->SDL_modelist[6]->h = 312; + Private->SDL_modelist[7]->w = 352; Private->SDL_modelist[7]->h = 264; + Private->SDL_modelist[8]->w = 800; Private->SDL_modelist[8]->h = 240; //for doom all these.. + Private->SDL_modelist[9]->w = 640; Private->SDL_modelist[9]->h = 240; + Private->SDL_modelist[10]->w = 480; Private->SDL_modelist[10]->h = 240; + Private->SDL_modelist[11]->w = 640; Private->SDL_modelist[11]->h = 240; + Private->SDL_modelist[12]->w = 352; Private->SDL_modelist[12]->h = 240; + Private->SDL_modelist[13]->w = 416; Private->SDL_modelist[13]->h = 240; + Private->SDL_modelist[14]->w = 416; Private->SDL_modelist[14]->h = 240; + Private->SDL_modelist[15]->w = 352; Private->SDL_modelist[15]->h = 240; + Private->SDL_modelist[16]->w = 640; Private->SDL_modelist[16]->h = 200; + Private->SDL_modelist[17]->w = 320; Private->SDL_modelist[17]->h = 240; //...for doom, currently engine renders no-higher windows :-(, propably should get fixed + Private->SDL_modelist[18]->w = 320; Private->SDL_modelist[18]->h = 200; + Private->SDL_modelist[19]->w = 256; Private->SDL_modelist[19]->h = 192; + Private->SDL_modelist[20]->w = 176; Private->SDL_modelist[20]->h = 208; + Private->SDL_modelist[21]->w = 208; Private->SDL_modelist[21]->h = 176; // Rotated + Private->SDL_modelist[22]->w = 160; Private->SDL_modelist[22]->h = 144; + + Private->SDL_modelist[23]->w = 640; Private->SDL_modelist[2]->h = 200; //s80 some new modes + Private->SDL_modelist[24]->w = 640; Private->SDL_modelist[2]->h = 320; //s90 modes are added + Private->SDL_modelist[25]->w = 640; Private->SDL_modelist[2]->h = 240; //here + Private->SDL_modelist[26]->w = 640; Private->SDL_modelist[4]->h = 200; //now + + Private->SDL_modelist[27] = NULL; + + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + TDisplayMode displayMode = Private->EPOC_WsScreen->DisplayMode(); + +#if !defined(__WINS__) && !defined(TEST_BM_DRAW) + + TScreenInfoV01 screenInfo; + TPckg sInfo(screenInfo); + UserSvr::ScreenInfo(sInfo); + + Private->EPOC_ScreenSize = screenInfo.iScreenSize; + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = screenInfo.iScreenAddressValid; + Private->EPOC_FrameBuffer = Private->EPOC_HasFrameBuffer ? (TUint8*) screenInfo.iScreenAddress : NULL; + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + + Private->EPOC_BytesPerScanLine = screenInfo.iScreenSize.iWidth * Private->EPOC_BytesPerPixel; + Private->EPOC_BytesPerScreen = Private->EPOC_BytesPerScanLine * Private->EPOC_ScreenSize.iHeight; + + SDL_TRACE1("Screen width %d", screenInfo.iScreenSize.iWidth); + SDL_TRACE1("Screen height %d", screenInfo.iScreenSize.iHeight); + SDL_TRACE1("Screen dmode %d", displayMode); + SDL_TRACE1("Screen valid %d", screenInfo.iScreenAddressValid); + + SDL_TRACE1("bpp %d", Private->EPOC_BytesPerPixel); + SDL_TRACE1("bpsl %d", Private->EPOC_BytesPerScanLine); + SDL_TRACE1("bps %d", Private->EPOC_BytesPerScreen); + + + /* It seems that in SA1100 machines for 8bpp displays there is a 512 palette table at the + * beginning of the frame buffer. E.g. Series 7 and Netbook. + * In 12 bpp machines the table has 16 entries. + */ + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 8) + { + Private->EPOC_FrameBuffer += 512; + } + else + { + Private->EPOC_FrameBuffer += 32; + } + /*if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 12) + Private->EPOC_FrameBuffer += 16 * 2; + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 16) + Private->EPOC_FrameBuffer += 16 * 2; + */ +#else /* defined __WINS__ */ + + /* Create bitmap, device and context for screen drawing */ + Private->EPOC_ScreenSize = Private->EPOC_WsScreen->SizeInPixels(); + + Private->EPOC_Bitmap = new (ELeave) CWsBitmap(Private->EPOC_WsSession); + Private->EPOC_Bitmap->Create(Private->EPOC_ScreenSize, displayMode); + + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = ETrue; + Private->EPOC_FrameBuffer = NULL; /* Private->EPOC_Bitmap->DataAddress() can change any time */ + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + Private->EPOC_BytesPerScanLine = Private->EPOC_WsScreen->SizeInPixels().iWidth * Private->EPOC_BytesPerPixel; + +#endif /* __WINS__ */ + +#ifndef SYMBIAN_CRYSTAL + // Get draw device for updating the screen + TScreenInfoV01 screenInfo2; + + Epoc_Runtime::GetScreenInfo(screenInfo2); + + TRAPD(status, Private->EPOC_DrawDevice = CFbsDrawDevice::NewScreenDeviceL(screenInfo2, displayMode)); + User::LeaveIfError(status); +#endif + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = /*!!GetBpp(displayMode) */ 8; + vformat->BytesPerPixel = /*!!Private->EPOC_BytesPerPixel*/ 1; + + /* Activate events for me */ + + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + + SDL_TRACE("SDL:WsEventStatus"); + User::WaitForRequest(Private->EPOC_WsEventStatus); //Markus: I added this and ... + + Private->EPOC_RedrawEventStatus = KRequestPending; + Private->EPOC_WsSession.RedrawReady(&Private->EPOC_RedrawEventStatus); + + SDL_TRACE("SDL:RedrawEventStatus"); + User::WaitForRequest(Private->EPOC_RedrawEventStatus); //...this, if not catches a stray event is risen + //if there are active objects used, or confucing + //actions with User::WaitForAnyRequest + Private->EPOC_WsWindow.PointerFilter(EPointerFilterDrag, 0); + + Private->EPOC_ScreenOffset = TPoint(0, 0); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap +#endif + + SDL_TRACE("SDL:DrawBackground"); + DrawBackground(_this); // Clear screen + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + UnlockHeap(Private->EPOC_Bitmap); // Unlock bitmap heap +#endif + //!! TODO: error handling + //if (ret != KErrNone) + // return(-1); + //else + return(0); +} + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 /*flags*/) +{ + if (format->BitsPerPixel == 12 || format->BitsPerPixel == 8) + return Private->SDL_modelist; + return NULL; +} + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + if ((firstcolor+ncolors) > 256) + return -1; +// SDL_TRACE1("colors %d", (TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode))); + if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + EPOC_HWPalette_256_to_Screen[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + EPOC_HWPalette_256_to_Screen[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + EPOC_HWPalette_256_to_Screen[i] = color16M; + } + } + else + { + return -2; + } + return(0); +} + + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 /*flags*/) +{ + SDL_TRACE("SDL:EPOC_SetVideoMode"); + /* Check parameters */ +#ifdef SYMBIAN_CRYSTAL + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 640 && height == 200) || + (width == 640 && height == 400) || + (width == 640 && height == 480) || + (width == 320 && height == 200) || + (width == 320 && height == 240) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#else // SYMBIAN_SERIES60 + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 320 && height == 200) || + (width == 320 && height == 240) || + (width == 256 && height == 192) || + (width == 176 && height == 208) || + (width == 208 && height == 176) || // Rotated + (width == 160 && height == 144) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#endif + + if (current && current->pixels) { + free(current->pixels); + current->pixels = NULL; + } + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + if (bpp == 8) + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC|SDL_HWPALETTE); + else // 12 bpp, 16 bpp + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC); + current->w = width; + current->h = height; + int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + current->pixels = malloc(width * height * numBytesPerPixel); + memset(current->pixels, 0, width * height * numBytesPerPixel); + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + int w = current->w; + int h = current->h; + + // Rotate, if the screen does not fit horizontally and it is landscape screen +/* + if ((width>Private->EPOC_ScreenSize.iWidth) && (width>height)) { + Private->EPOC_ScreenOrientation = CFbsBitGc::EGraphicsOrientationRotated270; + w = current->h; + h = current->w; + } +*/ + // Get nearest stepwise scale values for width and height. The smallest supported scaled screen is 1/2. + TInt scaleValue = 0; + Private->EPOC_ScreenXScaleValue = 1; + Private->EPOC_ScreenYScaleValue = 1; + if (w > Private->EPOC_ScreenSize.iWidth) { + // Find the biggest scale value that result the width that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledWidth = (w * (scaleValue-1))/scaleValue; + if (scaledWidth > Private->EPOC_ScreenSize.iWidth) + break; + } + Private->EPOC_ScreenXScaleValue = Max(2, scaleValue - 1); + w = (w * (Private->EPOC_ScreenXScaleValue-1))/Private->EPOC_ScreenXScaleValue; + } + if (h > Private->EPOC_ScreenSize.iHeight) { + // Find the biggest scale value that result the height that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledHeight = (h * (scaleValue-1))/scaleValue; + if (scaledHeight > Private->EPOC_ScreenSize.iHeight) + break; + } + Private->EPOC_ScreenYScaleValue = Max(2, scaleValue - 1); + h = (h * (Private->EPOC_ScreenYScaleValue-1))/Private->EPOC_ScreenYScaleValue; + } + + /* Centralize game window on device screen */ + Private->EPOC_ScreenOffset.iX = (Private->EPOC_ScreenSize.iWidth - w) / 2; + if (Private->EPOC_ScreenOffset.iX < 0) + Private->EPOC_ScreenOffset.iX = 0; + Private->EPOC_ScreenOffset.iY = (Private->EPOC_ScreenSize.iHeight - h) / 2; + if (Private->EPOC_ScreenOffset.iY < 0) + Private->EPOC_ScreenOffset.iY = 0; + + + SDL_TRACE1("View width %d", w); + SDL_TRACE1("View height %d", h); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View s %d", scaleValue); + SDL_TRACE1("View x %d", Private->EPOC_ScreenOffset.iX); + SDL_TRACE1("View y %d", Private->EPOC_ScreenOffset.iY); + + /* We're done */ + return(current); +} + + +void RedrawWindowL(_THIS) +{ + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); +#endif + + int w = _this->screen->w; + int h = _this->screen->h; + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + w = _this->screen->h; + h = _this->screen->w; + } + if ((w < Private->EPOC_ScreenSize.iWidth) + || (h < Private->EPOC_ScreenSize.iHeight)) { + DrawBackground(_this); + } + + /* Tell the system that something has been drawn */ + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + UnlockHeap(Private->EPOC_Bitmap);; // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#endif + + /* Draw current buffer */ + SDL_Rect fullScreen; + fullScreen.x = 0; + fullScreen.y = 0; + fullScreen.w = _this->screen->w; + fullScreen.h = _this->screen->h; + EPOC_DirectUpdate(_this, 1, &fullScreen); +} + + +void DrawBackground(_THIS) +{ + /* Draw background */ +#if defined(__WINS__) || defined(TEST_BM_DRAW) + //warning heap is not locked! - a function calling must ensure that it's ok + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + // Draw black background + Mem::FillZ(screenBuffer, Private->EPOC_BytesPerScreen); + +#if 0 + for (int y = 0; y < Private->EPOC_ScreenSize.iHeight; y++) { + for (int x = 0; x < Private->EPOC_ScreenSize.iWidth; x++) { +#ifdef SYMBIAN_CRYSTAL + const TUint16 color = 0; // ((x+y)>>1) & 0xf; /* Draw blue stripes pattern, because in e.g. 320x200 mode there is a big background area*/ +#else // SYMBIAN_SERIES60 + const TUint16 color = 0; /* Draw black background */ +#endif + *screenBuffer++ = color; + } + } +#endif +} + + +/* We don't actually allow hardware surfaces other than the main one */ +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(-1); +} +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + //TInt focusWindowGroupId = Private->EPOC_WsSession.GetFocusWindowGroup();//these are async services + // if (focusWindowGroupId != Private->EPOC_WsWindowGroupID) { //for that cannot be called from + //SDL threads ??? + if (!Private->EPOC_IsWindowFocused) + { + /* Force focus window to redraw again for cleaning away SDL screen graphics */ +/* + TInt pos = Private->EPOC_WsWindowGroup.OrdinalPosition(); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0, KMaxTInt); + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(pos, ECoeWinPriorityNormal); + */ /* If this is not the topmost window, wait here! Sleep for 1 second to give cpu time to + multitasking and poll for being the topmost window. + */ + // if (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) { + + /* !!TODO: Could call GetRedraw() etc. for WsSession and redraw the screen if needed. That might be + needed if a small dialog comes in front of Game screen. + */ + // while (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) + + SDL_PauseAudio(1); + SDL_Delay(1000); + return; + // } + + // RedrawWindowL(_this); + } + + SDL_PauseAudio(0); + + // if we are not focused, do not draw +// if (!Private->EPOC_IsWindowFocused) +// return; +#if defined(__WINS__) || defined(TEST_BM_DRAW) + TBitmapUtil lock(Private->EPOC_Bitmap); + lock.Begin(TPoint(0,0)); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) + DirectDrawRotated(_this, numrects, rects, screenBuffer); + else + DirectDraw(_this, numrects, rects, screenBuffer); + + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + lock.End(); // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#else +#ifndef SYMBIAN_CRYSTAL + // This is not needed in Crystal. What is the performance penalty in SERIES60? + TRect rect2 = TRect(Private->EPOC_WsWindow.Size()); + + Private->EPOC_DrawDevice->UpdateRegion(rect2); // Should we update rects parameter area only?? + Private->EPOC_DrawDevice->Update(); +#endif +#endif + + /* Update virtual cursor. !!Do not yet work properly + Private->EPOC_WsSession.SetPointerCursorPosition(Private->EPOC_WsSession.PointerCursorPosition()); + */ + + /*static int foo = 1; + + for ( int i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) + continue; + + + foo++; + if((foo % 200) == 0) + { + SDL_TRACE1("foo %d", foo); + CFbsBitmap* b = new (ELeave) CFbsBitmap; + SDL_TRACE1("bee %d", (int)b); + int e = b->Create(TSize(currentRect.w, currentRect.h), Private->EPOC_DisplayMode); + + SDL_TRACE1("err %d", e); + if(e != KErrNone) + User::Panic(_L("damn"), e); + + TBitmapUtil u(b); + u.Begin(TPoint(0, 0)); + TUint32* d = b->DataAddress(); + + SDL_TRACE1("addr %d", (int)d); + + for(TInt o = 0; o < currentRect.h; o++) + for(TInt p = 0; p < currentRect.w; p++) + { + u.SetPos(TPoint(p, o)); + u.SetPixel(0xFFFF); + } + + SDL_TRACE1("w %d", (int)currentRect.w); + SDL_TRACE1("h %d", (int)currentRect.h); + + SDL_TRACE1("addr %d", (int)Private->EPOC_DisplayMode); + + + const TUint f = (TUint)Private->EPOC_FrameBuffer; + const TUint y = (TUint)Private->EPOC_BytesPerScreen; + + + SDL_TRACE1("frame %u", f); + SDL_TRACE1("bytes %u", y); + + Mem::Copy(d, Private->EPOC_FrameBuffer, Private->EPOC_BytesPerScreen); + + SDL_TRACE("kopied"); + + u.End(); + TBuf<32> name; + name.Format(_L("C:\\nokia\\images\\doom%d.mbm"), (foo / 200)); + e= b->Save(name); + if(e != KErrNone) + User::Panic(_L("damned"), e); + delete b; + }}*/ +} + + +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + const TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = 1; // no skip + + TInt targetStartOffset = fixedOffset.iX + rect2.x + (fixedOffset.iY +rect2.y) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + if(Private->EPOC_BytesPerPixel <= 2) + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + else + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint32* screenMemory = reinterpret_cast(screenBuffer + targetStartOffset); + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint32* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (reinterpret_cast(screenBuffer) + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= reinterpret_cast(screenBuffer), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + } // switch + } // for +} + +/* +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + +/* for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ +/* continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ +/* TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ +/* continue; + /* Clip from bottom */ +/* maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + +/* TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = Private->EPOC_ScreenXScaleValue; //1; // no skip + + const TInt targetStartOffset = // = (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) ; + (skipValue > 1 ? + (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) : + (fixedOffset.iX + rect2.x + (fixedOffset.iY + rect2.y) * targetScanlineLength )); + + __ASSERT_DEBUG(skipValue >= 1, User::Panic(KLibName, KErrArgument)); + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ +/* for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue > 1) + sourceRectWidth /= skipValue; +#if defined __MARM_ARMI__ + __asm volatile(" + mov %4, %4, lsl #1 @ targetScanLineLength is in pixels, we need it in bytes + 1: + mov r6, %0 @ bitmapLine + mov r7, %2 @ screenMemory + mov r8, %6 @ sourceRectWidth + 2: + ldrb r4, [%0], %7 @ r4 = *bitmapPos; bitmapPos += skipValue + ldr r5, [%1, r4, lsl #2] @ only 16 lower bits actually used + subs r8, r8, #1 @ x-- + strh r5, [%2], #2 @ *screenMemoryLinePos++ = r4 + bne 2b + + add %0, r6, %3 @ bitmapLine += sourceScanlineLength + add %2, r7, %4 @ screenMemory += targetScanlineLength + subs %5, %5, #1 @ sourceRectHeight-- + bne 1b + " + : // no output + // %0 %1 %2 %3 %4 %5 %6 %7 + : "r" (bitmapLine), "r" (&EPOC_HWPalette_256_to_Screen[0]), "r" (screenMemory), "r" (sourceScanlineLength), "r" (targetScanlineLength), "r" (sourceRectHeight), "r" (sourceRectWidth), "r" (skipValue) + : "r4", "r5", "r6", "r7", "r8" + ); +#else + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ +/* for (TInt x = 0 ; x < sourceRectWidth ; x++) + { + //__ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos]; + bitmapPos += skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } +//#endif + } + } // switch + } // for +} +*/ + +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; +// TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + TPoint fixedScreenOffset = Private->EPOC_ScreenOffset; + TInt bufferW = _this->screen->w; + TInt bufferH = _this->screen->h; + TInt ScreenW = Private->EPOC_ScreenSize.iWidth; +// TInt ScreenH = Private->EPOC_ScreenSize.iWidth; + TInt sourceW = bufferW; + TInt sourceH = bufferH; + TInt targetW = ScreenW - fixedScreenOffset.iX * 2; +// TInt targetH = ScreenH - fixedScreenOffset.iY * 2; + TInt sourceScanlineLength = bufferW; + TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + SDL_Rect rect2; + const SDL_Rect& currentRect = rects[i]; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(sourceW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(sourceH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + //maxX = Min(maxX, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + TInt sourceRectWidth = maxX - rect2.x + 1; +// TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + TInt sourceRectHeight = maxY - rect2.y + 1; + TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + TInt targetStartOffset = fixedScreenOffset.iX + (targetW-1 - rect2.y) + (fixedScreenOffset.iY +rect2.x) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + if (_this->screen->format->BitsPerPixel == 12) { + + /* !!TODO: not yet implemented + + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + //TODO: optimize: separate loops for 1, 2 and n skip + //Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + TUint16* bitmapPos = bitmapLine; // 2 bytes per pixel + TUint16* screenMemoryLinePos = screenMemory; // 2 bytes per pixel + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = *bitmapPos; + bitmapPos++; + screenMemoryLinePos += targetScanlineLength; + } + bitmapLine += sourceScanlineLength; + screenMemory--; + } + + */ + } + // 256 color paletted mode: 8 bpp --> 12 bpp + else { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + TInt screenXScaleValue = Private->EPOC_ScreenXScaleValue; + TInt debug_ycount=0; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + if(--screenXScaleValue) { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + TInt screenYScaleValue = Private->EPOC_ScreenYScaleValue; + TInt debug_xcount=0; + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + if(--screenYScaleValue) { + + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = TUint16(EPOC_HWPalette_256_to_Screen[*bitmapPos]); + screenMemoryLinePos += targetScanlineLength; debug_xcount++; + } + else + screenYScaleValue = Private->EPOC_ScreenYScaleValue; + bitmapPos++; + } + screenMemory--; debug_ycount++; + } // endif + else + screenXScaleValue = Private->EPOC_ScreenXScaleValue; + bitmapLine += sourceScanlineLength; + } + } + } +} + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) +{ + int i; + + /* Free video mode lists */ + for ( i=0; iSDL_modelist[i] != NULL ) { + free(Private->SDL_modelist[i]); + Private->SDL_modelist[i] = NULL; + } + } + + if ( _this->screen && (_this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, no memory buffer */ + _this->screen->pixels = NULL; + } + + if (_this->screen && _this->screen->pixels) { + free(_this->screen->pixels); + _this->screen->pixels = NULL; + } + + /* Free Epoc resources */ + + /* Disable events for me */ + if (Private->EPOC_WsEventStatus != KRequestPending) + Private->EPOC_WsSession.EventReadyCancel(); + if (Private->EPOC_RedrawEventStatus != KRequestPending) + Private->EPOC_WsSession.RedrawReadyCancel(); + + #if defined(__WINS__) || defined(TEST_BM_DRAW) + delete Private->EPOC_Bitmap; + Private->EPOC_Bitmap = NULL; + #else + #endif + +#ifndef SYMBIAN_CRYSTAL + free(Private->EPOC_DrawDevice); +#endif + + if (Private->EPOC_WsWindow.WsHandle()) + Private->EPOC_WsWindow.Close(); + + if (Private->EPOC_WsWindowGroup.WsHandle()) + Private->EPOC_WsWindowGroup.Close(); + + delete Private->EPOC_WindowGc; + Private->EPOC_WindowGc = NULL; + + delete Private->EPOC_WsScreen; + Private->EPOC_WsScreen = NULL; + + if (Private->EPOC_WsSession.WsHandle()) + Private->EPOC_WsSession.Close(); +} + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) +{ + return (WMcursor *) 9210; // it's ok to return something unuseful but true +} + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) +{ + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); +} + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) +{ + + if (cursor == (WMcursor *)9210) { + /* Enable virtual cursor */ + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNormal); + if (isCursorVisible) + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + else + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + + return(1); +} + +}; // extern "C" diff --git a/src/video/symbian/EKA1/SDL_epocvideo.h b/src/video/symbian/EKA1/SDL_epocvideo.h new file mode 100644 index 000000000..a83a1e7f0 --- /dev/null +++ b/src/video/symbian/EKA1/SDL_epocvideo.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef _SDL_epocvideo_h +#define _SDL_epocvideo_h + +#ifndef EKA2 +#include"SDL_epocvideo_org.h" +#else +#include"SDL_epocvideo2.h" +#endif + + +#endif + diff --git a/src/video/symbian/EKA2/SDL_epocevents.cpp b/src/video/symbian/EKA2/SDL_epocevents.cpp new file mode 100644 index 000000000..2452daed6 --- /dev/null +++ b/src/video/symbian/EKA2/SDL_epocevents.cpp @@ -0,0 +1,521 @@ +#include "epoc_sdl.h" + +#include +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +} /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdlepocapi.h" + +#include + +#include + + +extern "C" + { + static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); + } + +//extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +//} /* extern "C" */ + +SDLKey* KeyMap() + { + return keymap; + } + +TBool isCursorVisible = EFalse; + +void ResetKeyMap() + { + int i; + + /* Initialize the key translation table */ + for ( i=0; i array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close();*/ + /////////////////////////////////////////////////////////// + + + keymap[EStdKeyNumLock] = SDLK_NUMLOCK; + keymap[EStdKeyScrollLock] = SDLK_SCROLLOCK; + + keymap[EStdKeyNkpForwardSlash] = SDLK_KP_DIVIDE; + keymap[EStdKeyNkpAsterisk] = SDLK_KP_MULTIPLY; + keymap[EStdKeyNkpMinus] = SDLK_KP_MINUS; + keymap[EStdKeyNkpPlus] = SDLK_KP_PLUS; + keymap[EStdKeyNkpEnter] = SDLK_KP_ENTER; + keymap[EStdKeyNkp1] = SDLK_KP1; + keymap[EStdKeyNkp2] = SDLK_KP2; + keymap[EStdKeyNkp3] = SDLK_KP3; + keymap[EStdKeyNkp4] = SDLK_KP4; + keymap[EStdKeyNkp5] = SDLK_KP5; + keymap[EStdKeyNkp6] = SDLK_KP6; + keymap[EStdKeyNkp7] = SDLK_KP7; + keymap[EStdKeyNkp8] = SDLK_KP8; + keymap[EStdKeyNkp9] = SDLK_KP9; + keymap[EStdKeyNkp0] = SDLK_KP0; + keymap[EStdKeyNkpFullStop] = SDLK_KP_PERIOD; + /* + keymap[EStdKeyMenu] = SDLK_MENU; should be, but not yet + keymap[EStdKeyBacklightOn] = + keymap[EStdKeyBacklightOff] = + keymap[EStdKeyBacklightToggle] = + keymap[EStdKeyIncContrast] = + keymap[EStdKeyDecContrast] = + keymap[EStdKeySliderDown] = + keymap[EStdKeySliderUp] = + keymap[EStdKeyDictaphonePlay] = + keymap[EStdKeyDictaphoneStop] = + keymap[EStdKeyDictaphoneRecord] = + keymap[EStdKeyHelp] = + keymap[EStdKeyOff] = + keymap[EStdKeyDial] = + keymap[EStdKeyIncVolume] = + keymap[EStdKeyDecVolume] = + keymap[EStdKeyDevice0] = + keymap[EStdKeyDevice1] = + keymap[EStdKeyDevice2] = + keymap[EStdKeyDevice3] = + keymap[EStdKeyDevice4] = + keymap[EStdKeyDevice5] = + keymap[EStdKeyDevice6] = + keymap[EStdKeyDevice7] = + keymap[EStdKeyDevice8] = + keymap[EStdKeyDevice9] = + keymap[EStdKeyDeviceA] = + keymap[EStdKeyDeviceB] = + keymap[EStdKeyDeviceC] = + keymap[EStdKeyDeviceD] = + keymap[EStdKeyDeviceE] = + keymap[EStdKeyDeviceF] = + keymap[EStdKeyApplication0] = + keymap[EStdKeyApplication1] = + keymap[EStdKeyApplication2] = + keymap[EStdKeyApplication3] = + keymap[EStdKeyApplication4] = + keymap[EStdKeyApplication5] = + keymap[EStdKeyApplication6] = + keymap[EStdKeyApplication7] = + keymap[EStdKeyApplication8] = + keymap[EStdKeyApplication9] = + keymap[EStdKeyApplicationA] = + keymap[EStdKeyApplicationB] = + keymap[EStdKeyApplicationC] = + keymap[EStdKeyApplicationD] = + keymap[EStdKeyApplicationE] = + keymap[EStdKeyApplicationF] = + keymap[EStdKeyYes] = + keymap[EStdKeyNo] = + keymap[EStdKeyIncBrightness] = + keymap[EStdKeyDecBrightness] = + keymap[EStdKeyCaseOpen] = + keymap[EStdKeyCaseClose] = */ + + + +} + + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { +/* const TPointerCursorMode mode = EpocSdlEnv::PointerMode(); + + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } +*/ + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + const TPoint mousePos = EpocSdlEnv::WindowCoordinates(pointerEvent->iPosition); + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->iIsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + //RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { + + Private->iIsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + case EEventScreenDeviceChanged: + { + EpocSdlEnv::WaitDeviceChange(); + } + break; + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) + { + MEventQueue& events = EpocSdlEnv::EventQueue(); + while(events.HasData()) + { + events.Lock(); + + //there have to be a copy, so we can release + //lock immediately. HandleWsEvent may cause + //deadlock otherwise. + + const TWsEvent event = events.Shift(); + events.Unlock(); +// const TWsEvent& event = events.Top(); + EPOC_HandleWsEvent(_this, event); +// events.Shift(); + } + } + + + +void EPOC_InitOSKeymap(_THIS) + { + ResetKeyMap(); + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventKeyMapInit ,0); + } + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ +/* + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } +*/ + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +} /* extern "C" */ + + diff --git a/src/video/symbian/EKA2/SDL_epocvideo.cpp b/src/video/symbian/EKA2/SDL_epocvideo.cpp new file mode 100644 index 000000000..fc201bd2f --- /dev/null +++ b/src/video/symbian/EKA2/SDL_epocvideo.cpp @@ -0,0 +1,594 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Markus Mertama +*/ + + + +#include "epoc_sdl.h" + +#include +#include +#include + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +#include "SDL_mouse.h" +} + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + + + +#include +#include + +#include +#include +#include +#include "sdlepocapi.h" + + +//////////////////////////////////////////////////////////////// + + + + +_LIT(KLibName, "SDL"); + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + +/* +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + +*/ + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); +} + + +extern "C" + { + struct WMcursor + { + }; + } + +/* Epoc video driver bootstrap functions */ + + +static int EPOC_Available(void) + { + return 1; /* Always available */ + } + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) + { + User::Free(device->hidden); + User::Free(device); + } + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) + { + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = static_cast(User::Alloc(sizeof(SDL_VideoDevice))); + if ( device ) + { + Mem::FillZ(device, (sizeof *device)); + device->hidden = static_cast + (User::Alloc((sizeof *device->hidden))); + } + if ( (device == NULL) || (device->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( device ) { + User::Free(device); + } + return(0); + } + Mem::FillZ(device->hidden, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +VideoBootStrap EPOC_bootstrap = { + "epoc\0\0\0", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + + + +void DisableKeyBlocking(_THIS) + { + EpocSdlEnv::Request(EpocSdlEnv::EDisableKeyBlocking); + } + +void ConstructWindowL(_THIS) + { + SDL_TRACE("SDL:ConstructWindowL"); + DisableKeyBlocking(_this); //disable key blocking + } + + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) + { + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode); + vformat->BytesPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) / 8; + + + //?? Private->iWindow->PointerFilter(EPointerFilterDrag, 0); + + Private->iScreenPos = TPoint(0, 0); + + Private->iRect.x = Private->iScreenPos.iX; + Private->iRect.y = Private->iScreenPos.iY; + + const TSize sz = EpocSdlEnv::WindowSize(); + + Private->iRect.w = sz.iWidth; + Private->iRect.h = sz.iHeight; + Private->iRectPtr = &Private->iRect; + + return(0); + } + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) + { + if(flags & SDL_HWSURFACE) + { + if(format->BytesPerPixel != 4) //in HW only full color is supported + return NULL; + } + if(flags & SDL_FULLSCREEN) + { + return &Private->iRectPtr; + } + return (SDL_Rect **)(-1); //everythingisok, unless too small shoes + } + + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) + { + if ((firstcolor+ncolors) > 256) + return -1; + TUint32 palette[256]; + const TDisplayMode mode = EpocSdlEnv::DisplayMode(); + if(TDisplayModeUtils::NumDisplayModeColors(mode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + palette[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + palette[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + palette[i] = color16M; + } + } + else + { + return -2; + } + if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone) + return 0; + return -1; + } + + +/* +void AllocHWSurfaceL(CFbsBitmap*& aBitmap, const TDisplayMode& aMode, const TSize& aSize) + { + aBitmap = new (ELeave) CFbsBitmap(); + if(KErrNone != aBitmap->CreateHardwareBitmap(aSize, aMode, + EpocSdlEnv::EikonEnv().EikAppUi()->Application()->AppDllUid())) + //...if it fails - should we use wsbitmaps??? + {//the good reason to use hw bitmaps is that they wont need lock heap + PANIC_IF_ERROR(aBitmap->Create(aSize, aMode)); + } + } + +int CreateSurfaceL(_THIS, SDL_Surface* surface) + { + __ASSERT_ALWAYS(Private->iFrame == NULL, PANIC(KErrAlreadyExists)); +; + TInt dmode = EColorLast; + + TDisplayMode displayMode; + EpocSdlEnv::GetDiplayMode(displayMode); + + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == surface->format->BitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + surface->format->BitsPerPixel) + --dmode; + } + + __ASSERT_ALWAYS(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)), PANIC(KErrNotSupported)); + TRAPD(err, AllocHWSurfaceL(Private->iFrame, TDisplayMode(dmode), TSize(surface->w, surface->h))); + return err == KErrNone ? 0 : -1; + } +*/ + +TDisplayMode GetDisplayMode(TInt aBitsPerPixel) + { + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + TInt dmode = EColorLast; + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == aBitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + aBitsPerPixel) + --dmode; + } + return TDisplayMode(dmode); + } + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) + { + const TSize screenSize = EpocSdlEnv::WindowSize(TSize(width, height)); + if(width > screenSize.iWidth || height > screenSize.iHeight) + { + if(flags & SDL_FULLSCREEN) + { + width = screenSize.iWidth; + height = screenSize.iHeight; + } + else + return NULL; + } + + if(current && current->pixels) + { + // free(current->pixels); + current->pixels = NULL; + } + + if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0)) + { + return(NULL); + } + + current->flags = 0; + if(width == screenSize.iWidth && height == screenSize.iHeight) + current->flags |= SDL_FULLSCREEN; + + const int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + + /* Set up the new mode framebuffer */ + current->flags |= SDL_PREALLOC; + + if(bpp <= 8) + current->flags |= SDL_HWPALETTE; + + User::Free(Private->iSwSurface); + current->pixels = NULL; + Private->iSwSurface = NULL; + + if(flags & SDL_HWSURFACE) + { + current->flags |= SDL_HWSURFACE; + // current->pixels = NULL; + // Private->iSwSurface = NULL; + } + else + { + current->flags |= SDL_SWSURFACE; + const TInt surfacesize = width * height * numBytesPerPixel; + Private->iSwSurfaceSize = TSize(width, height); + delete Private->iSwSurface; + Private->iSwSurface = NULL; + current->pixels = (TUint8*) User::AllocL(surfacesize); + Private->iSwSurface = (TUint8*) current->pixels; + const TInt err = EpocSdlEnv::AllocSwSurface + (TSize(width, height), GetDisplayMode(current->format->BitsPerPixel)); + if(err != KErrNone) + return NULL; + } + + current->w = width; + current->h = height; + + + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + + /* Centralize game window on device screen */ + + + Private->iScreenPos.iX = Max(0, (screenSize.iWidth - width) / 2); + Private->iScreenPos.iY = Max(0, (screenSize.iHeight - height) / 2); + + // delete (Private->iFrame); +// Private->iFrame = NULL; + + // TRAPD(err, CreateSurfaceL(_this, current)); + // PANIC_IF_ERROR(err); + + SDL_TRACE1("View width %d", width); + SDL_TRACE1("View height %d", height); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View x %d", Private->iScreenPos.iX); + SDL_TRACE1("View y %d", Private->iScreenPos.iY); + + EpocSdlEnv::LockPalette(EFalse); + /* We're done */ + return(current); +} + + + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* surface) + { + return KErrNone == EpocSdlEnv::AllocHwSurface(TSize(surface->w, surface->h), GetDisplayMode(surface->format->BitsPerPixel)); + } + +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) + { + } + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* surface) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + TUint8* address = EpocSdlEnv::LockHwSurface(); + if(address != NULL) + { + surface->pixels = address; + return 1; + } + } + return 0; + } +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) + { + EpocSdlEnv::UnlockHwSurface(); + } + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) + { + return(0); + } + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + if(Private->iSwSurface) + { + const TRect target(Private->iScreenPos, Private->iSwSurfaceSize); + for(TInt i = 0; i < numrects ;i++) + { + const TRect rect(TPoint(rects[i].x, rects[i].y), + TSize(rects[i].w, rects[i].h)); + if(!EpocSdlEnv::AddUpdateRect(Private->iSwSurface, rect, target)) + return; //not succesful + } + EpocSdlEnv::UpdateSwSurface(); + } + SDL_PauseAudio(0); + } + else + { + SDL_PauseAudio(1); + EpocSdlEnv::WaitDsaAvailable(); + } + } + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) + { +// delete Private->iFrame; +// Private->iFrame = NULL; + User::Free(Private->iSwSurface); + Private->iSwSurface = NULL; + EpocSdlEnv::FreeSurface(); + } + + + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) + { + return (WMcursor*) 1; //hii! prevents SDL to view a std cursor + } + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) + { + } + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) + { + return true; + } + diff --git a/src/video/symbian/EKA2/SDL_epocvideo.h b/src/video/symbian/EKA2/SDL_epocvideo.h new file mode 100644 index 000000000..d823413f7 --- /dev/null +++ b/src/video/symbian/EKA2/SDL_epocvideo.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef EPOCVIDEO_H +#define EPOCVIDEO_H + +#include + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +class CFbsBitmap; + +struct SDL_VideoDevice; +void DisableKeyBlocking(SDL_VideoDevice*); + +struct SDL_PrivateVideoData + { + TPoint iScreenPos; + TBool iIsWindowFocused; + TSize iSwSurfaceSize; + TUint8* iSwSurface; + SDL_Rect iRect; //same info in SDL format + SDL_Rect* iRectPtr; + }; + +#endif + + + + \ No newline at end of file diff --git a/src/video/symbian/EKA2/dsa.cpp b/src/video/symbian/EKA2/dsa.cpp new file mode 100644 index 000000000..6702075b4 --- /dev/null +++ b/src/video/symbian/EKA2/dsa.cpp @@ -0,0 +1,1504 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + + + +template +class CBitmapSurface : public T + { +public: + CBitmapSurface(RWsSession& aSession); +private: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + ~CBitmapSurface(); + TUint8* LockSurface(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + TInt ExternalUpdate(); +private: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +template +void CBitmapSurface::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + delete iCopyBmp; + iCopyBmp = NULL; + iCopyBmp = new (ELeave) CFbsBitmap(); + T::ConstructL(aWindow, aDevice); + } + +template +CBitmapSurface::CBitmapSurface(RWsSession& aSession) : T(aSession) + { + } + +template +void CBitmapSurface::Free() + { + delete iBmp; + iBmp = NULL; + T::Free(); + } + +template +CBitmapSurface::~CBitmapSurface() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +template +TUint8* CBitmapSurface::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast(iBmp->DataAddress()); + } + + +template +void CBitmapSurface::UnlockHwSurface() + { + iBmp->UnlockHeap(); + T::SetUpdating(EFalse); + Update(*iBmp); + } + + +template +void CBitmapSurface::Update(CFbsBitmap& aBmp) + { + if(!T::Blitter(aBmp)) + { + if(T::SwSize() == T::HwRect().Size()) + T::Gc().BitBlt(T::HwRect().iTl, &aBmp); + else + T::Gc().DrawBitmap(T::HwRect(), &aBmp); + } + T::DrawOverlays(); + T::CompleteUpdate(); + } + +template +void CBitmapSurface::CreateSurfaceL() + { + Free(); + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(T::SwSize(), T::DisplayMode())); + T::CreateSurfaceL(*iBmp); + } + +template +void CBitmapSurface::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +template +TInt CBitmapSurface::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + + +////////////////////////////////////////////////////////////////////// + + + +NONSHARABLE_CLASS(CDsaBitgdi) : public CDsa + { +public: + CDsaBitgdi(RWsSession& aSession); +protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CBitmapContext& Gc(); + void CompleteUpdate(); + ~CDsaBitgdi(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); +private: + void Resume(); + + CFbsBitGc* iGc; + CFbsDevice* iDevice; + CFbsBitmap* iBitGdiBmp; + CWindowGc* iWinGc; + RWindow* iWindow; + TInt iHandle; + }; + + +CDsaBitgdi::CDsaBitgdi(RWsSession& aSession) : CDsa(aSession) + { + } + +CDsaBitgdi::~CDsaBitgdi() + { + delete iWinGc; + delete iBitGdiBmp; + } + +void CDsaBitgdi::CompleteUpdate() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + + +void CDsaBitgdi::UnlockHWSurfaceRequestComplete() + { + if(iHandle == 0) + return; + + if(iBitGdiBmp == NULL) + { + iBitGdiBmp = new CFbsBitmap(); + if(iBitGdiBmp == NULL) + return; + iBitGdiBmp->Duplicate(iHandle); + } + + iWindow->Invalidate(); + + iWindow->BeginRedraw(); + iWinGc->Activate(*iWindow); + iWinGc->BitBlt(TPoint(0, 0), iBitGdiBmp); + iWinGc->Deactivate(); + iWindow->EndRedraw(); + } + +void CDsaBitgdi::Resume() + { + Start(); + } + +CBitmapContext& CDsaBitgdi::Gc() + { + return *iGc; + } + + void CDsaBitgdi::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + + delete iBitGdiBmp; + iBitGdiBmp = NULL; + delete iWinGc; + iWinGc = NULL; + iHandle = 0; + + iWindow = &aWindow; + User::LeaveIfError(aDevice.CreateContext(iWinGc)); + CDsa::ConstructL(aWindow, aDevice); + Start(); + } + +void CDsaBitgdi::CreateSurfaceL(CFbsBitmap& aBmp) + { + iDevice = CFbsBitmapDevice::NewL(&aBmp); + User::LeaveIfError(iDevice->CreateContext(iGc)); + iHandle = aBmp.Handle(); + } + +void CDsaBitgdi::Free() + { + delete iGc; + iGc = NULL; + delete iDevice; + iDevice = NULL; + } + +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaBase) : public CDsa, public MDirectScreenAccess + { +protected: + inline CDirectScreenAccess& Dsa() const; + CDsaBase(RWsSession& aSession); + ~CDsaBase(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Stop(); + void Resume(); + CBitmapContext& Gc(); +protected: + CDirectScreenAccess* iDsa; +private: + void AbortNow(RDirectScreenAccess::TTerminationReasons aReason); + void Restart(RDirectScreenAccess::TTerminationReasons aReason); +private: + void RestartL(); + }; + + +inline CDirectScreenAccess& CDsaBase::Dsa() const + { + return *iDsa; + } + + +CDsaBase::CDsaBase(RWsSession& aSession) : CDsa(aSession) + { + } + +CBitmapContext& CDsaBase::Gc() + { + return *Dsa().Gc(); + } + +void CDsaBase::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsa::ConstructL(aWindow, aDevice); + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + Session(), + aDevice, + aWindow, + *this); + RestartL(); + } + +void CDsaBase::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +CDsaBase::~CDsaBase() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + } + + +void CDsaBase::RestartL() + { + + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != ScreenRect()) + { + return ; + } + + + SetTargetRect(); + RecreateL(); + + Start(); + + + } + +void CDsaBase::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { + Stop(); + } + +void CDsaBase::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + + +void CDsaBase::Stop() + { + CDsa::Stop(); + iDsa->Cancel(); + } + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast(targetPtr), reinterpret_cast(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast(targetPtr), reinterpret_cast(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsaBase + { + public: + CDsaA(RWsSession& aSession); + protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void CompleteUpdate(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsaBase(aSession) + { + } + + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsaBase::ConstructL(aWindow, aDevice); + } + +void CDsaA::CompleteUpdate() + { + iDsa->ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL(CFbsBitmap& /*aBmp*/) + { + } + +void CDsaA::Free() + { + + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsaBase, + public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsaBase(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsaBase::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrementalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else if(EpocSdlEnv::Flags(CSDL::EDrawModeGdi)) + { + return new (ELeave) CBitmapSurface(aSession); + } + else + { + return new (ELeave) CBitmapSurface(aSession); + } + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + + +void CDsa::SetUpdating(TBool aUpdate) + { + if(aUpdate) + iStateFlags |= EUpdating; + else + iStateFlags &= ~EUpdating; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + iOverlays.Close(); + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& /*aDevice*/) + { + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +*/ + + +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + + + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; + } + +void CDsa::Start() + { + iStateFlags |= ERunning; + + iStateFlags &= ~ESdlThreadExplicitStop; + + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + + +TBool CDsa::Blitter(CFbsBitmap& aBmp) + { + return iBlitter && iBlitter->BitBlt(Gc(), aBmp, HwRect(), SwSize()); + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); + + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template +void* TRgbCopy::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template +TRgbCopy::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template +void TRgbCopy::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template +void TRgbCopy::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template TUint32 TRgbCopy::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template TUint32 TRgbCopy::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template TUint32 TRgbCopy::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template TUint32 TRgbCopy::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/src/video/symbian/EKA2/dsa_new.cpp b/src/video/symbian/EKA2/dsa_new.cpp new file mode 100644 index 000000000..638fbe8c9 --- /dev/null +++ b/src/video/symbian/EKA2/dsa_new.cpp @@ -0,0 +1,1443 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast(targetPtr), reinterpret_cast(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast(targetPtr), reinterpret_cast(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + TInt ExternalUpdate(); + // void ExternalUpdate(); + protected: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Update(*iBmp); + } + +void CDsaA::Update(CFbsBitmap& aBmp) + { + if(!Blitter(aBmp)) + { + if(SwSize() == HwRect().Size()) + Dsa().Gc()->BitBlt(HwRect().iTl, &aBmp); + else + Dsa().Gc()->DrawBitmap(HwRect(), &aBmp); + } + DrawOverlays(); + Dsa().ScreenDevice()->Update(); + } +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(SwSize(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + + + +TInt CDsaA::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + iCopyBmp = new (ELeave) CFbsBitmap(); + CDsa::ConstructL(aWindow, aDevice); + } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsa(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else + return new (ELeave) CDsaA(aSession); + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + iOverlays.Close(); + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + RestartL(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != iScreenRect) + { + // iDsa->Cancel(); + return ; + } + + + + //iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + //targetrect shall no change + SetTargetRect(); + RecreateL(); + + iStateFlags |= ERunning; + + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +void ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) + { + const TInt iSourceBpp = 1; + const TInt iTargetBpp = 4; + const TInt iScanLineWidth = 800; + + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + const TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + } +*/ +/* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + //TUint8* target = aTarget; + const TUint32* source = (const TUint32*) aSource; + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + TUint32* targetPtr = reinterpret_cast(aTarget); + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * SwSize().iWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + +// TUint32* targetPtr = reinterpret_cast(target); + + const TInt targetWidth32 = SwSize().iWidth; + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth32 * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr -= targetWidth32; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr += targetWidth32; // >> 2; + } + } + + } + +*/ + +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + /* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +*/ + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +/* +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + */ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = Rect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect.iTl); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template +void* TRgbCopy::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template +TRgbCopy::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template +void TRgbCopy::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template +void TRgbCopy::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template TUint32 TRgbCopy::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template TUint32 TRgbCopy::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template TUint32 TRgbCopy::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template TUint32 TRgbCopy::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template TUint32 TRgbCopy::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/src/video/symbian/EKA2/dsa_old.cpp b/src/video/symbian/EKA2/dsa_old.cpp new file mode 100644 index 000000000..7e32de2cf --- /dev/null +++ b/src/video/symbian/EKA2/dsa_old.cpp @@ -0,0 +1,1075 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void Free(); + TInt ExternalUpdate() {return 0;} + private: + CFbsBitmap* iBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Dsa().Gc()->BitBlt(HwRect().iTl, iBmp); + Dsa().ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(HwRect().Size(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +void CDsaA::RecreateL() + { + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Free(); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate() {return 0;} + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + }; + +CDsaB::CDsaB(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaB::Free() + { + } + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + iSurface1 = new (ELeave) CDsbSurface(*this); + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::EDoubleBuffer); + } + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +TSize CDsa::WindowSize() const + { + TSize size = HwRect().Size(); + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iTargetRect = TRect(aWindow.Position(), aWindow.Size()); + RestartL(); + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + iDsa->StartL(); + + RRegion* r = iDsa->DrawingRegion(); + iDsa->Gc()->SetClippingRegion(r); + TRect rect = r->BoundingRect(); + + if(rect.IsEmpty()) + { + return; + } + + iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + + RecreateL(); + + iStateFlags |= ERunning; +// iScanLineWidth = iTargetBpp * HwRect().Width(); + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + + + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + + SetCopyFunction(); + + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + + return KErrNone; + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } +*/ +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TRect& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iTl.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iTl.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast(target); + const TInt targetWidth = HwRect().Size().iWidth; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * iScreenRect.Width() * iScreenRect.Height()); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = HwRect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession); + } + else + return new (ELeave) CDsaA(aSession); + } + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + Mem::Copy(aTarget, aSource, aBytes); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + + +typedef TRgb (*TRgbFunc) (TInt aValue); + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } + +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; +template +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + private: + TRgbFunc iFunc; + }; + +template +void* TRgbCopy::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template +TRgbCopy::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = TRgb::Gray256; break; + case EColor256 : iFunc = TRgb::Color256; break; + case EColor4K : iFunc = TRgb::Color4K; break; + case EColor64K : iFunc = TRgb::Color64K; break; + case EColor16M : iFunc = TRgb::Color16M; break; + case EColor16MU : iFunc = TRgb::Color16MU; break; + case EColor16MA : iFunc = rgb16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template +void TRgbCopy::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + TUint32 value = *source++; + *(--endt) = iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + TUint32 value = *source++; + *target++ = iFunc(value).Value(); + } + } + } + +template +void TRgbCopy::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column).Value(); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column).Value(); + column += aLineLen; + } + } + } + + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } \ No newline at end of file diff --git a/src/video/symbian/SDL_epocevents_c.h b/src/video/symbian/SDL_epocevents_c.h new file mode 100644 index 000000000..8dd76f6c9 --- /dev/null +++ b/src/video/symbian/SDL_epocevents_c.h @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents_c.h + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) and Markus Mertama + +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_aaevents_c.h,v 1.1.2.2 2000/03/16 15:20:39 hercules Exp $"; +#endif + +extern "C" { +#include "SDL_sysvideo.h" +//#include "SDL_epocvideo.h" +} + + + +#define MAX_SCANCODE 255 + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +extern "C" { +extern void EPOC_InitOSKeymap(_THIS); +extern void EPOC_PumpEvents(_THIS); +} + +extern TBool isCursorVisible; +