Home | History | Annotate | Download | only in EKA2
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public
     16     License along with this library; if not, write to the Free
     17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     18 
     19     Sam Lantinga
     20     slouken (at) devolution.com
     21 */
     22 
     23 /*
     24     SDL_epocvideo.cpp
     25     Epoc based SDL video driver implementation
     26 
     27     Markus Mertama
     28 */
     29 
     30 
     31 
     32 #include "epoc_sdl.h"
     33 
     34 #include <stdlib.h>
     35 #include <stdio.h>
     36 #include <string.h>
     37 
     38 extern "C" {
     39 #include "SDL_error.h"
     40 #include "SDL_timer.h"
     41 #include "SDL_video.h"
     42 #undef NULL
     43 #include "SDL_pixels_c.h"
     44 #include "SDL.h"
     45 #include "SDL_mouse.h"
     46 }
     47 
     48 #include "SDL_epocvideo.h"
     49 #include "SDL_epocevents_c.h"
     50 
     51 
     52 
     53 #include <coedef.h>
     54 #include <flogger.h>
     55 
     56 #include <eikenv.h>
     57 #include <eikappui.h>
     58 #include <eikapp.h>
     59 #include "sdlepocapi.h"
     60 
     61 
     62 ////////////////////////////////////////////////////////////////
     63 
     64 
     65 
     66 
     67 _LIT(KLibName, "SDL");
     68 
     69 void RDebug_Print_b(char* error_str, void* param)
     70     {
     71     TBuf8<128> error8((TUint8*)error_str);
     72     TBuf<128> error;
     73     error.Copy(error8);
     74 
     75 #ifndef TRACE_TO_FILE
     76     if (param) //!! Do not work if the parameter is really 0!!
     77         RDebug::Print(error, param);
     78     else
     79         RDebug::Print(error);
     80 #else
     81     if (param) //!! Do not work if the parameter is really 0!!
     82         RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param);
     83     else
     84         RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error);
     85 #endif
     86 
     87     }
     88 
     89 extern "C" void RDebug_Print(char* error_str, void* param)
     90     {
     91     RDebug_Print_b(error_str, param);
     92     }
     93 
     94 /*
     95 int Debug_AvailMem2()
     96     {
     97     //User::CompressAllHeaps();
     98     TMemoryInfoV1Buf membuf;
     99     User::LeaveIfError(UserHal::MemoryInfo(membuf));
    100     TMemoryInfoV1 minfo = membuf();
    101 	return(minfo.iFreeRamInBytes);
    102     }
    103 
    104 extern "C" int Debug_AvailMem()
    105     {
    106     return(Debug_AvailMem2());
    107     }
    108 
    109 */
    110 
    111 extern "C" {
    112 
    113 /* Initialization/Query functions */
    114 
    115 static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat);
    116 static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
    117 static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    118 static int EPOC_SetColors(_THIS, int firstcolor, int ncolors,
    119 			  SDL_Color *colors);
    120 static void EPOC_VideoQuit(_THIS);
    121 
    122 /* Hardware surface functions */
    123 
    124 static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface);
    125 static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface);
    126 static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface);
    127 static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface);
    128 static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface);
    129 static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
    130 
    131 static int EPOC_Available(void);
    132 static SDL_VideoDevice *EPOC_CreateDevice(int devindex);
    133 
    134 void DrawBackground(_THIS);
    135 void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer);
    136 void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer);
    137 
    138 /* Mouse functions */
    139 
    140 static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
    141 static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor);
    142 static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor);
    143 }
    144 
    145 
    146 extern "C"
    147 	{
    148 	struct WMcursor
    149 		{
    150 		};
    151 	}
    152 
    153 /* Epoc video driver bootstrap functions */
    154 
    155 
    156 static int EPOC_Available(void)
    157     {
    158     return 1; /* Always available */
    159     }
    160 
    161 static void EPOC_DeleteDevice(SDL_VideoDevice *device)
    162     {
    163 	User::Free(device->hidden);
    164 	User::Free(device);
    165     }
    166 
    167 static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/)
    168     {
    169 	SDL_VideoDevice *device;
    170 
    171 	SDL_TRACE("SDL:EPOC_CreateDevice");
    172 
    173 	/* Allocate all variables that we free on delete */
    174 	device = static_cast<SDL_VideoDevice*>(User::Alloc(sizeof(SDL_VideoDevice)));
    175 	if ( device )
    176 	    {
    177 		Mem::FillZ(device, (sizeof *device));
    178 		device->hidden = static_cast<struct SDL_PrivateVideoData*>
    179 				(User::Alloc((sizeof *device->hidden)));
    180 	    }
    181 	if ( (device == NULL) || (device->hidden == NULL) )
    182 	    {
    183 		SDL_OutOfMemory();
    184 		if ( device ) {
    185 		User::Free(device);
    186 		}
    187 		return(0);
    188 	}
    189 	Mem::FillZ(device->hidden, (sizeof *device->hidden));
    190 
    191 	/* Set the function pointers */
    192 	device->VideoInit = EPOC_VideoInit;
    193 	device->ListModes = EPOC_ListModes;
    194 	device->SetVideoMode = EPOC_SetVideoMode;
    195 	device->SetColors = EPOC_SetColors;
    196 	device->UpdateRects = NULL;
    197 	device->VideoQuit = EPOC_VideoQuit;
    198 	device->AllocHWSurface = EPOC_AllocHWSurface;
    199 	device->CheckHWBlit = NULL;
    200 	device->FillHWRect = NULL;
    201 	device->SetHWColorKey = NULL;
    202 	device->SetHWAlpha = NULL;
    203 	device->LockHWSurface = EPOC_LockHWSurface;
    204 	device->UnlockHWSurface = EPOC_UnlockHWSurface;
    205 	device->FlipHWSurface = EPOC_FlipHWSurface;
    206 	device->FreeHWSurface = EPOC_FreeHWSurface;
    207 	device->SetIcon = NULL;
    208 	device->SetCaption = NULL;
    209 	device->GetWMInfo = NULL;
    210 	device->FreeWMCursor = EPOC_FreeWMCursor;
    211 	device->CreateWMCursor = EPOC_CreateWMCursor;
    212 	device->ShowWMCursor = EPOC_ShowWMCursor;
    213 	device->WarpWMCursor = NULL;
    214 	device->InitOSKeymap = EPOC_InitOSKeymap;
    215 	device->PumpEvents = EPOC_PumpEvents;
    216 	device->free = EPOC_DeleteDevice;
    217 
    218 	return device;
    219 }
    220 
    221 
    222 VideoBootStrap EPOC_bootstrap = {
    223 	"epoc\0\0\0", "EPOC system",
    224     EPOC_Available, EPOC_CreateDevice
    225 };
    226 
    227 
    228 
    229 void DisableKeyBlocking(_THIS)
    230     {
    231     EpocSdlEnv::Request(EpocSdlEnv::EDisableKeyBlocking);
    232     }
    233 
    234 void ConstructWindowL(_THIS)
    235 	{
    236 	SDL_TRACE("SDL:ConstructWindowL");
    237 	DisableKeyBlocking(_this); //disable key blocking
    238 	}
    239 
    240 
    241 int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat)
    242 	{
    243     /* Construct Epoc window */
    244 
    245     ConstructWindowL(_this);
    246 
    247     /* Initialise Epoc frame buffer */
    248 
    249 
    250     const TDisplayMode displayMode = EpocSdlEnv::DisplayMode();
    251 
    252     /* The "best" video format should be returned to caller. */
    253 
    254     vformat->BitsPerPixel 	= TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode);
    255     vformat->BytesPerPixel  = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) / 8;
    256 
    257 
    258  //??   Private->iWindow->PointerFilter(EPointerFilterDrag, 0);
    259 
    260     Private->iScreenPos = TPoint(0, 0);
    261 
    262     Private->iRect.x = Private->iScreenPos.iX;
    263     Private->iRect.y = Private->iScreenPos.iY;
    264 
    265     const TSize sz = EpocSdlEnv::WindowSize();
    266 
    267     Private->iRect.w = sz.iWidth;
    268     Private->iRect.h = sz.iHeight;
    269 	Private->iRectPtr = &Private->iRect;
    270 
    271 	return(0);
    272 	}
    273 
    274 
    275 SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    276 	{
    277 	if(flags & SDL_HWSURFACE)
    278 		{
    279 		if(format->BytesPerPixel != 4) //in HW only full color is supported
    280 			return NULL;
    281 		}
    282 	if(flags & SDL_FULLSCREEN)
    283 		{
    284 		return &Private->iRectPtr;
    285 		}
    286     return (SDL_Rect **)(-1); //everythingisok, unless too small shoes
    287 	}
    288 
    289 
    290 int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
    291 	{
    292 	if ((firstcolor+ncolors) > 256)
    293 		return -1;
    294 	TUint32 palette[256];
    295 	const TDisplayMode mode = EpocSdlEnv::DisplayMode();
    296     if(TDisplayModeUtils::NumDisplayModeColors(mode) == 4096)
    297         {
    298 	// Set 12 bit palette
    299         for(int i = firstcolor; i < ncolors; i++)
    300             {
    301 	        // 4k value: 0000 rrrr gggg bbbb
    302 	        TUint32 color4K	 = (colors[i].r & 0x0000f0) << 4;
    303 	        color4K			|= (colors[i].g & 0x0000f0);
    304 	        color4K			|= (colors[i].b & 0x0000f0) >> 4;
    305             palette[i] = color4K;
    306             }
    307         }
    308     else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 65536)
    309         {
    310         for(int i = firstcolor; i < ncolors; i++)
    311             {
    312 			// 64k-colour displays effectively support RGB values
    313 			// with 5 bits allocated to red, 6 to green and 5 to blue
    314 			// 64k value: rrrr rggg gggb bbbb
    315 	        TUint32 color64K = (colors[i].r & 0x0000f8) << 8;
    316 	        color64K		|= (colors[i].g & 0x0000fc) << 3;
    317 	        color64K		|= (colors[i].b & 0x0000f8) >> 3;
    318             palette[i] = color64K;
    319             }
    320         }
    321     else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 16777216)
    322         {
    323         for(int i = firstcolor; i < ncolors; i++)
    324             {
    325 			// 16M-colour
    326             //0000 0000 rrrr rrrr gggg gggg bbbb bbbb
    327 	        TUint32 color16M = colors[i].r << 16;
    328 	        color16M		|= colors[i].g << 8;
    329 	        color16M		|= colors[i].b;
    330             palette[i] = color16M;
    331             }
    332         }
    333     else
    334         {
    335         return -2;
    336         }
    337     if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone)
    338     	return 0;
    339 	return -1;
    340 	}
    341 
    342 
    343 /*
    344 void AllocHWSurfaceL(CFbsBitmap*& aBitmap, const TDisplayMode& aMode, const TSize& aSize)
    345 	{
    346 	aBitmap = new (ELeave) CFbsBitmap();
    347 	if(KErrNone != aBitmap->CreateHardwareBitmap(aSize, aMode,
    348 		EpocSdlEnv::EikonEnv().EikAppUi()->Application()->AppDllUid()))
    349 	//...if it fails - should we use wsbitmaps???
    350 		{//the good reason to use hw bitmaps is that they wont need lock heap
    351 		PANIC_IF_ERROR(aBitmap->Create(aSize, aMode));
    352 		}
    353 	}
    354 
    355 int CreateSurfaceL(_THIS, SDL_Surface* surface)
    356     {
    357     __ASSERT_ALWAYS(Private->iFrame == NULL, PANIC(KErrAlreadyExists));
    358 ;
    359 	TInt dmode = EColorLast;
    360 
    361 	TDisplayMode displayMode;
    362 	EpocSdlEnv::GetDiplayMode(displayMode);
    363 
    364 	if(
    365 	TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)
    366 	== surface->format->BitsPerPixel)
    367 		{
    368 		dmode = displayMode;
    369 		}
    370 	else
    371 		{
    372 		--dmode;
    373 		while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) &&
    374 			TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) !=
    375 			surface->format->BitsPerPixel)
    376 			--dmode;
    377 		}
    378 
    379 	__ASSERT_ALWAYS(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)), PANIC(KErrNotSupported));
    380 	TRAPD(err, AllocHWSurfaceL(Private->iFrame, TDisplayMode(dmode), TSize(surface->w, surface->h)));
    381 	return err == KErrNone ? 0 : -1;
    382     }
    383 */
    384 
    385 TDisplayMode GetDisplayMode(TInt aBitsPerPixel)
    386 	{
    387 	const TDisplayMode displayMode = EpocSdlEnv::DisplayMode();
    388 	TInt dmode = EColorLast;
    389 	if(
    390 	TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)
    391 	== aBitsPerPixel)
    392 		{
    393 		dmode = displayMode;
    394 		}
    395 	else
    396 		{
    397 		--dmode;
    398 		while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) &&
    399 			TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) !=
    400 			aBitsPerPixel)
    401 			--dmode;
    402 		}
    403 	return TDisplayMode(dmode);
    404 	}
    405 
    406 SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current,
    407 				int width, int height, int bpp, Uint32 flags)
    408 	{
    409 	const TSize screenSize = EpocSdlEnv::WindowSize(TSize(width, height));
    410 	if(width > screenSize.iWidth || height > screenSize.iHeight)
    411 	    {
    412 	    if(flags & SDL_FULLSCREEN)
    413 	        {
    414 	        width = screenSize.iWidth;
    415 	        height = screenSize.iHeight;
    416 	        }
    417 	    else
    418 		    return NULL;
    419 	    }
    420 
    421     if(current && current->pixels)
    422     	{
    423       //  free(current->pixels);
    424         current->pixels = NULL;
    425     	}
    426 
    427 	if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0))
    428 	 	{
    429 		return(NULL);
    430 	 	}
    431 
    432 	current->flags = 0;
    433 	if(width == screenSize.iWidth && height == screenSize.iHeight)
    434 		current->flags |= SDL_FULLSCREEN;
    435 
    436 	const int numBytesPerPixel = ((bpp-1)>>3) + 1;
    437 	current->pitch = numBytesPerPixel * width; // Number of bytes in scanline
    438 
    439     /* Set up the new mode framebuffer */
    440    	current->flags |= SDL_PREALLOC;
    441 
    442    	if(bpp <= 8)
    443    		current->flags |= SDL_HWPALETTE;
    444 
    445    	User::Free(Private->iSwSurface);
    446    	current->pixels = NULL;
    447    	Private->iSwSurface = NULL;
    448 
    449    	if(flags & SDL_HWSURFACE)
    450    	    {
    451    	    current->flags |= SDL_HWSURFACE;
    452    	   //	current->pixels = NULL;
    453    	   // 	Private->iSwSurface = NULL;
    454    	    }
    455    	else
    456    	    {
    457    	    current->flags |= SDL_SWSURFACE;
    458    	    const TInt surfacesize = width * height * numBytesPerPixel;
    459    	   	Private->iSwSurfaceSize = TSize(width, height);
    460    	   	delete Private->iSwSurface;
    461    	   	Private->iSwSurface = NULL;
    462    	  	current->pixels = (TUint8*) User::AllocL(surfacesize);
    463    	  	Private->iSwSurface = (TUint8*) current->pixels;
    464    	  	const TInt err = EpocSdlEnv::AllocSwSurface
    465    	  		(TSize(width, height), GetDisplayMode(current->format->BitsPerPixel));
    466 	    if(err != KErrNone)
    467 	    	return NULL;
    468 	    }
    469 
    470 	current->w = width;
    471 	current->h = height;
    472 
    473 
    474 
    475 	/* Set the blit function */
    476 	_this->UpdateRects = EPOC_DirectUpdate;
    477 
    478     /*
    479      *  Logic for getting suitable screen dimensions, offset, scaling and orientation
    480      */
    481 
    482 
    483     /* Centralize game window on device screen  */
    484 
    485 
    486     Private->iScreenPos.iX = Max(0, (screenSize.iWidth  - width)  / 2);
    487     Private->iScreenPos.iY = Max(0, (screenSize.iHeight - height) / 2);
    488 
    489  //   delete (Private->iFrame);
    490 //	Private->iFrame = NULL;
    491 
    492   //  TRAPD(err, CreateSurfaceL(_this, current));
    493   //  PANIC_IF_ERROR(err);
    494 
    495     SDL_TRACE1("View width %d", width);
    496     SDL_TRACE1("View height %d", height);
    497     SDL_TRACE1("View bmode %d", bpp);
    498     SDL_TRACE1("View x %d", Private->iScreenPos.iX);
    499     SDL_TRACE1("View y %d", Private->iScreenPos.iY);
    500 
    501 	EpocSdlEnv::LockPalette(EFalse);
    502 	/* We're done */
    503 	return(current);
    504 }
    505 
    506 
    507 
    508 static int EPOC_AllocHWSurface(_THIS, SDL_Surface* surface)
    509 	{
    510 	return KErrNone == EpocSdlEnv::AllocHwSurface(TSize(surface->w, surface->h), GetDisplayMode(surface->format->BitsPerPixel));
    511 	}
    512 
    513 static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/)
    514 	{
    515 	}
    516 
    517 static int EPOC_LockHWSurface(_THIS, SDL_Surface* surface)
    518 	{
    519 	if(EpocSdlEnv::IsDsaAvailable())
    520 		{
    521 		TUint8* address = EpocSdlEnv::LockHwSurface();
    522 		if(address != NULL)
    523 			{
    524 			surface->pixels = address;
    525 			return 1;
    526 			}
    527 		}
    528 	return 0;
    529 	}
    530 static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/)
    531 	{
    532 	EpocSdlEnv::UnlockHwSurface();
    533 	}
    534 
    535 static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/)
    536 	{
    537 	return(0);
    538 	}
    539 
    540 static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
    541 	{
    542 	if(EpocSdlEnv::IsDsaAvailable())
    543 		{
    544 		if(Private->iSwSurface)
    545 		    {
    546 		    const TRect target(Private->iScreenPos, Private->iSwSurfaceSize);
    547 		    for(TInt i = 0; i < numrects ;i++)
    548 		    	{
    549 		    	const TRect rect(TPoint(rects[i].x, rects[i].y),
    550 		    		TSize(rects[i].w, rects[i].h));
    551 		    	if(!EpocSdlEnv::AddUpdateRect(Private->iSwSurface, rect, target))
    552 		    		return; //not succesful
    553 		    	}
    554 		    EpocSdlEnv::UpdateSwSurface();
    555 		    }
    556 		SDL_PauseAudio(0);
    557 		}
    558     else
    559     	{
    560      	SDL_PauseAudio(1);
    561     	EpocSdlEnv::WaitDsaAvailable();
    562 		}
    563 	}
    564 
    565 
    566 /* Note:  If we are terminated, this could be called in the middle of
    567    another SDL video routine -- notably UpdateRects.
    568 */
    569 void EPOC_VideoQuit(_THIS)
    570 	{
    571 //	delete Private->iFrame;
    572 //	Private->iFrame = NULL;
    573 	User::Free(Private->iSwSurface);
    574 	Private->iSwSurface = NULL;
    575 	EpocSdlEnv::FreeSurface();
    576 	}
    577 
    578 
    579 
    580 
    581 WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/)
    582     {
    583     return (WMcursor*) 1; //hii! prevents SDL to view a std cursor
    584     }
    585 
    586 void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/)
    587     {
    588     }
    589 
    590 int EPOC_ShowWMCursor(_THIS, WMcursor *cursor)
    591     {
    592     return true;
    593     }
    594 
    595