add some NEON 32bpp blitters
[sdl_omap.git] / src / video / symbian / EKA2 / SDL_epocvideo.cpp
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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@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