Big cleanup part 1.
[SDL.s60v3.git] / src / video / symbian / SDL_epocvideo.cpp
blob1b108f8ba381c6881a5bd8c8a3cde98caa62e247
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
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.
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.
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
19 Sam Lantinga
20 slouken@devolution.com
24 SDL_epocvideo.cpp
25 Epoc based SDL video driver implementation
27 Markus Mertama
30 #include "epoc_sdl.h"
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
36 extern "C" {
37 #include "SDL_error.h"
38 #include "SDL_timer.h"
39 #include "SDL_video.h"
40 #undef NULL
41 #include "SDL_pixels_c.h"
42 #include "SDL.h"
43 #include "SDL_mouse.h"
46 #include "SDL_epocvideo.h"
47 #include "SDL_epocevents_c.h"
49 #include <coedef.h>
50 #include <flogger.h>
51 #include <eikenv.h>
52 #include <eikappui.h>
53 #include <eikapp.h>
54 #include "sdlepocapi.h"
55 #include <SDL_gliop.h>
56 #include <egl.h>
58 #include "gles_armv5_def.h"
60 _LIT(KLibName, "SDL");
62 extern "C" {
64 /* Initialization/Query functions */
66 static int S60_VideoInit(_THIS, SDL_PixelFormat *vformat);
67 static SDL_Rect **S60_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
68 static SDL_Surface *S60_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
69 static int S60_SetColors(_THIS, int firstcolor, int ncolors,
70 SDL_Color *colors);
71 static void S60_VideoQuit(_THIS);
73 /* Hardware surface functions */
75 static int S60_AllocHWSurface(_THIS, SDL_Surface *surface);
76 static int S60_LockHWSurface(_THIS, SDL_Surface *surface);
77 static int S60_FlipHWSurface(_THIS, SDL_Surface *surface);
78 static void S60_UnlockHWSurface(_THIS, SDL_Surface *surface);
79 static void S60_FreeHWSurface(_THIS, SDL_Surface *surface);
80 static void S60_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
82 static int S60_Available(void);
83 static SDL_VideoDevice *S60_CreateDevice(int devindex);
85 void DrawBackground(_THIS);
86 void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer);
87 void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer);
89 /* Mouse functions */
91 static WMcursor *S60_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);
92 static void S60_FreeWMCursor(_THIS, WMcursor *cursor);
93 static int S60_ShowWMCursor(_THIS, WMcursor *cursor);
95 /*GL Functions*/
96 static int S60_GlesLoadLibrary(_THIS, const char* path);
97 static void* S60_GlesGetProcAddress(_THIS, const char *proc);
98 static int S60_GlesGetAttribute(_THIS, SDL_GLattr attrib, int* value);
99 static int S60_GlesMakeCurrent(_THIS);
100 static void S60_GlesSwapBuffers(_THIS);
105 extern "C"
107 struct WMcursor
112 /* Epoc video driver bootstrap functions */
114 static int S60_Available(void)
116 return 1; /* Always available */
119 static void S60_DeleteDevice(SDL_VideoDevice *device)
121 User::Free(device->gl_data);
122 User::Free(device->hidden);
123 User::Free(device);
126 static SDL_VideoDevice *S60_CreateDevice(int /*devindex*/)
128 SDL_VideoDevice *device;
130 /* Allocate all variables that we free on delete */
131 device = static_cast<SDL_VideoDevice*>(User::Alloc(sizeof(SDL_VideoDevice)));
132 if (device)
134 Mem::FillZ(device, (sizeof *device));
135 device->hidden = static_cast<struct SDL_PrivateVideoData*>
136 (User::Alloc((sizeof *device->hidden)));
137 device->gl_data = static_cast<struct SDL_PrivateGLData*>
138 (User::Alloc((sizeof (SDL_PrivateGLData))));
140 else
142 SDL_OutOfMemory();
143 return 0;
145 if((device->hidden == NULL) || (device->gl_data == NULL))
147 SDL_OutOfMemory();
148 User::Free(device->hidden);
149 User::Free(device->gl_data);
150 User::Free(device);
151 return(0);
154 Mem::FillZ(device->hidden, (sizeof *device->hidden));
156 /* Set the function pointers */
157 device->VideoInit = S60_VideoInit;
158 device->ListModes = S60_ListModes;
159 device->SetVideoMode = S60_SetVideoMode;
160 device->SetColors = S60_SetColors;
161 device->UpdateRects = NULL;
162 device->VideoQuit = S60_VideoQuit;
163 device->AllocHWSurface = S60_AllocHWSurface;
164 device->CheckHWBlit = NULL;
165 device->FillHWRect = NULL;
166 device->SetHWColorKey = NULL;
167 device->SetHWAlpha = NULL;
168 device->LockHWSurface = S60_LockHWSurface;
169 device->UnlockHWSurface = S60_UnlockHWSurface;
170 device->FlipHWSurface = S60_FlipHWSurface;
171 device->FreeHWSurface = S60_FreeHWSurface;
172 device->SetIcon = NULL;
173 device->SetCaption = NULL;
174 device->GetWMInfo = NULL;
175 device->FreeWMCursor = S60_FreeWMCursor;
176 device->CreateWMCursor = S60_CreateWMCursor;
177 device->ShowWMCursor = S60_ShowWMCursor;
178 device->WarpWMCursor = NULL;
179 device->InitOSKeymap = EPOC_InitOSKeymap;
180 device->PumpEvents = EPOC_PumpEvents;
181 device->free = S60_DeleteDevice;
183 /*gles funtions*/
185 device->GL_LoadLibrary = S60_GlesLoadLibrary;
186 device->GL_GetProcAddress = S60_GlesGetProcAddress;
187 device->GL_GetAttribute = S60_GlesGetAttribute;
188 device->GL_MakeCurrent = S60_GlesMakeCurrent;
189 device->GL_SwapBuffers = S60_GlesSwapBuffers;
191 device->gl_data->iLibrary.SetHandle(0);
193 return device;
197 VideoBootStrap EPOC_bootstrap = {
198 "epoc\0\0\0", "EPOC system",
199 S60_Available, S60_CreateDevice
204 void DisableKeyBlocking(_THIS)
206 EpocSdlEnv::Request(EpocSdlEnv::EDisableKeyBlocking);
209 int S60_VideoInit(_THIS, SDL_PixelFormat *vformat)
211 /* Initialise Epoc frame buffer */
213 DisableKeyBlocking(_this); //disable key blocking
215 const TDisplayMode displayMode = EpocSdlEnv::DisplayMode();
217 /* The "best" video format should be returned to caller. */
219 vformat->BitsPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode);
220 vformat->BytesPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) / 8;
222 Private->iScreenPos = TPoint(0, 0);
224 Private->iRect.x = Private->iScreenPos.iX;
225 Private->iRect.y = Private->iScreenPos.iY;
227 const TSize sz = EpocSdlEnv::WindowSize();
229 Private->iRect.w = sz.iWidth;
230 Private->iRect.h = sz.iHeight;
231 Private->iRectPtr = &Private->iRect;
233 return(0);
237 SDL_Rect **S60_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
239 if(flags & SDL_HWSURFACE)
241 if(format->BytesPerPixel != 4) //in HW only full color is supported
242 return NULL;
244 if(flags & SDL_FULLSCREEN)
246 return &Private->iRectPtr;
249 return (SDL_Rect **)(-1); //everythingisok, but too small shoes
253 int S60_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
255 if ((firstcolor+ncolors) > 256)
256 return -1;
257 TUint32 palette[256];
258 const TDisplayMode mode = EpocSdlEnv::DisplayMode();
259 if(TDisplayModeUtils::NumDisplayModeColors(mode) == 4096)
261 // Set 12 bit palette
262 for(int i = firstcolor; i < ncolors; i++)
264 // 4k value: 0000 rrrr gggg bbbb
265 TUint32 color4K = (colors[i].r & 0x0000f0) << 4;
266 color4K |= (colors[i].g & 0x0000f0);
267 color4K |= (colors[i].b & 0x0000f0) >> 4;
268 palette[i] = color4K;
271 else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 65536)
273 for(int i = firstcolor; i < ncolors; i++)
275 // 64k-colour displays effectively support RGB values
276 // with 5 bits allocated to red, 6 to green and 5 to blue
277 // 64k value: rrrr rggg gggb bbbb
278 TUint32 color64K = (colors[i].r & 0x0000f8) << 8;
279 color64K |= (colors[i].g & 0x0000fc) << 3;
280 color64K |= (colors[i].b & 0x0000f8) >> 3;
281 palette[i] = color64K;
284 else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 16777216)
286 for(int i = firstcolor; i < ncolors; i++)
288 // 16M-colour
289 //0000 0000 rrrr rrrr gggg gggg bbbb bbbb
290 TUint32 color16M = colors[i].r << 16;
291 color16M |= colors[i].g << 8;
292 color16M |= colors[i].b;
293 palette[i] = color16M;
296 else
298 return -2;
300 if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone)
301 return 0;
302 return -1;
305 int S60_GlesLoadLibrary(SDL_VideoDevice* _this, const char* path)
307 if(_this->gl_data->iLibrary.Handle() != 0)
308 return KErrAlreadyExists; //already loaded
309 const char* const gles_lib[] = {"libgles_cm.dll", "libSWGLES.dll"};
310 TInt err = KErrNotFound;
311 for(TInt i = 0; i < 2 && err != KErrNone; i++)
313 const char* name8 = path == NULL ? gles_lib[i] : path;
314 TFileName lib;
315 lib.Copy(TPtrC8((unsigned char*)name8));
316 err = _this->gl_data->iLibrary.Load(lib);
318 if(err == KErrNone)
319 _this->gl_config.driver_loaded = 1;
320 return err;
323 typedef TInt (*Ftp)(...);
324 #define DC(x) ((Ftp) S60_GlesGetProcAddress(_this, #x))
326 const char* const OpenGL[] = //these funtions are in gl, but not in gles, at least in all in all versions...
328 "glBegin",
329 "glEnd",
330 "glOrtho",
331 "glPopAttrib",
332 "glPopClientAttrib",
333 "glPushAttrib",
334 "glPushClientAttrib",
335 "glTexCoord2f",
336 "glVertex2i",
337 "glTexParameteri"
340 TInt NotSupported()
342 User::Panic(_L("SDL, Gles"), KErrNotSupported);
343 return 0;
346 void* S60_GlesGetProcAddress(_THIS, const char *proc)
348 if(_this->gl_data->iLibrary.Handle() == 0)
349 return NULL; //not loaded
350 TLibraryFunction f = NULL;
351 for(TInt i = 0; i < G_ordinals_count; i++)
353 if(strcmp(G_ordinals[i].name, proc) == 0)
355 f = _this->gl_data->iLibrary.Lookup(G_ordinals[i].ord);
356 break;
360 if(f != NULL) /*Lookup may fail*/
361 return (void*) f;
363 for(TInt i = 0; i < sizeof(OpenGL) / sizeof(char*); i++)
365 if(strcmp(OpenGL[i], proc) == 0)
366 return (void*) NotSupported;
369 return NULL;
374 int S60_GlesGetAttribute(_THIS, SDL_GLattr aAttrib, int* aValue)
376 EGLint attrib;
377 switch(aAttrib)
379 /*todo*/
380 case SDL_GL_RED_SIZE: attrib = EGL_RED_SIZE; break;
381 case SDL_GL_GREEN_SIZE: attrib = EGL_GREEN_SIZE; break;
382 case SDL_GL_BLUE_SIZE:attrib = EGL_BLUE_SIZE; break;
383 case SDL_GL_ALPHA_SIZE: attrib = EGL_ALPHA_SIZE; break;
384 case SDL_GL_BUFFER_SIZE: attrib = EGL_BUFFER_SIZE; break;
385 case SDL_GL_DOUBLEBUFFER: *aValue = 1; return 0; //always
386 case SDL_GL_DEPTH_SIZE: attrib = EGL_DEPTH_SIZE; break;
387 case SDL_GL_STENCIL_SIZE: attrib = EGL_STENCIL_SIZE; break;
388 case SDL_GL_ACCUM_RED_SIZE:
389 case SDL_GL_ACCUM_GREEN_SIZE:
390 case SDL_GL_ACCUM_BLUE_SIZE:
391 case SDL_GL_ACCUM_ALPHA_SIZE:
392 case SDL_GL_STEREO:
393 case SDL_GL_MULTISAMPLEBUFFERS:
394 case SDL_GL_MULTISAMPLESAMPLES:
395 case SDL_GL_ACCELERATED_VISUAL:
396 case SDL_GL_SWAP_CONTROL:
397 *aValue = 0;
398 return -1;
400 const int success = DC(eglGetConfigAttrib)
402 _this->gl_data->iDisplay,
403 _this->gl_data->iConfig,
404 attrib,
405 aValue);
406 return success == EGL_FALSE ? -1 : 0;
410 int S60_GlesMakeCurrent(_THIS)
412 DC(eglMakeCurrent)
413 (_this->gl_data->iDisplay,
414 _this->gl_data->iSurface,
415 _this->gl_data->iSurface,
416 _this->gl_data->iContext);
417 return DC(eglGetError)();
420 void S60_GlesSwapBuffers(_THIS)
422 DC(eglSwapBuffers)(
423 _this->gl_data->iDisplay,
424 _this->gl_data->iSurface);
427 TDisplayMode GetDisplayMode(TInt aBitsPerPixel)
429 const TDisplayMode displayMode = EpocSdlEnv::DisplayMode();
430 TInt dmode = EColorLast;
432 TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)
433 == aBitsPerPixel)
435 dmode = displayMode;
437 else
439 --dmode;
440 while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) &&
441 TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) !=
442 aBitsPerPixel)
443 --dmode;
445 return TDisplayMode(dmode);
449 LOCAL_C void glAssert(_THIS)
451 const EGLint err = DC(eglGetError)();
452 if(err != EGL_SUCCESS)
454 User::Leave(err);
458 LOCAL_C void CreateGles(_THIS, RWindow& aWindow, int bpp, SDL_PrivateGLData& aData)
460 SDL_GL_LoadLibrary(NULL); //just if its not already loaded
461 aData.iDisplay = DC(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
462 DC(eglInitialize)(aData.iDisplay, NULL, NULL);
464 glAssert(_this);
466 int configs = 0;
467 EGLConfig* configList = NULL;
468 int configSz = 0;
469 DC(eglGetConfigs)(aData.iDisplay, configList, configSz, &configs);
470 configSz = configs;
472 glAssert(_this);
474 configList = (EGLConfig*) User::Alloc(sizeof(EGLConfig) * configSz);
476 TInt red, green, blue;
477 if(bpp == 16)
479 red = 5;
480 green = 6;
481 blue = 5;
483 else
485 red = 8;
486 green = 8;
487 blue = 8;
490 const EGLint attribList[] =
492 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
493 EGL_RED_SIZE, red,
494 EGL_GREEN_SIZE, green,
495 EGL_BLUE_SIZE, blue,
496 EGL_BUFFER_SIZE, EGL_DONT_CARE,
497 EGL_DEPTH_SIZE, 8,
498 EGL_NONE
501 DC(eglChooseConfig)(aData.iDisplay,
502 attribList,
503 configList,
504 configSz,
505 &configs);
508 glAssert(_this);
510 __ASSERT_ALWAYS(configs > 0, User::Invariant());
512 aData.iConfig = configList[0];
514 User::Free(configList);
516 aData.iContext = DC(eglCreateContext)(aData.iDisplay,
517 aData.iConfig,
518 EGL_NO_CONTEXT,
519 NULL);
521 glAssert(_this);
523 aData.iSurface = DC(eglCreateWindowSurface)(aData.iDisplay,
524 aData.iConfig,
525 &aWindow,
526 NULL);
528 glAssert(_this);
533 LOCAL_C void DestroyGles(_THIS)
535 if( _this->gl_config.driver_loaded)
537 DC(eglMakeCurrent)(_this->gl_data->iDisplay,
538 EGL_NO_SURFACE,
539 EGL_NO_SURFACE,
540 EGL_NO_CONTEXT);
541 DC(eglDestroySurface)(_this->gl_data->iDisplay, _this->gl_data->iSurface);
542 DC(eglDestroyContext)(_this->gl_data->iDisplay, _this->gl_data->iContext);
543 DC(eglTerminate)(_this->gl_data->iDisplay);
544 _this->gl_data->iLibrary.Close();
545 _this->gl_config.driver_loaded = 0;
549 SDL_Surface *S60_SetVideoMode(_THIS, SDL_Surface *current,
550 int width, int height, int bpp, Uint32 flags)
552 if(flags & SDL_OPENGL)
554 current->flags |= SDL_OPENGL;
555 current->w = width;
556 current->h = height;
558 RWindow* win = EpocSdlEnv::Window();
559 EpocSdlEnv::ApplyGlesDsa();
561 CreateGles(_this, *win, bpp, *_this->gl_data);
563 return current;
565 const TSize screenSize = EpocSdlEnv::WindowSize(TSize(width, height));
566 if(width > screenSize.iWidth || height > screenSize.iHeight)
568 if(flags & SDL_FULLSCREEN)
570 width = screenSize.iWidth;
571 height = screenSize.iHeight;
573 else
574 return NULL;
577 if(current && current->pixels)
579 current->pixels = NULL;
582 if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0))
584 return(NULL);
587 current->flags = 0;
588 if(width == screenSize.iWidth && height == screenSize.iHeight)
589 current->flags |= SDL_FULLSCREEN;
591 const int numBytesPerPixel = ((bpp-1)>>3) + 1;
592 current->pitch = numBytesPerPixel * width; // Number of bytes in scanline
594 /* Set up the new mode framebuffer */
595 current->flags |= SDL_PREALLOC;
597 if(bpp <= 8)
598 current->flags |= SDL_HWPALETTE;
600 User::Free(Private->iSwSurface);
601 current->pixels = NULL;
602 Private->iSwSurface = NULL;
604 if(flags & SDL_HWSURFACE)
606 current->flags |= SDL_HWSURFACE;
608 else
610 current->flags |= SDL_SWSURFACE;
611 const TInt surfacesize = width * height * numBytesPerPixel;
612 Private->iSwSurfaceSize = TSize(width, height);
613 delete Private->iSwSurface;
614 Private->iSwSurface = NULL;
615 current->pixels = (TUint8*) User::Alloc(surfacesize);
616 Private->iSwSurface = (TUint8*) current->pixels;
617 const TInt err = EpocSdlEnv::AllocSwSurface
618 (TSize(width, height), GetDisplayMode(current->format->BitsPerPixel));
619 if(err != KErrNone || current->pixels == NULL)
620 return NULL;
623 current->w = width;
624 current->h = height;
626 /* Set the blit function */
627 _this->UpdateRects = S60_DirectUpdate;
630 * Logic for getting suitable screen dimensions, offset, scaling and orientation
634 /* Centralize game window on device screen */
637 Private->iScreenPos.iX = Max(0, (screenSize.iWidth - width) / 2);
638 Private->iScreenPos.iY = Max(0, (screenSize.iHeight - height) / 2);
640 EpocSdlEnv::LockPalette(EFalse);
641 /* We're done */
642 return(current);
645 static int S60_AllocHWSurface(_THIS, SDL_Surface* surface)
647 return KErrNone == EpocSdlEnv::AllocHwSurface(TSize(surface->w, surface->h), GetDisplayMode(surface->format->BitsPerPixel));
650 static void S60_FreeHWSurface(_THIS, SDL_Surface* /*surface*/)
654 static int S60_LockHWSurface(_THIS, SDL_Surface* surface)
656 if(EpocSdlEnv::IsDsaAvailable())
658 TUint8* address = EpocSdlEnv::LockHwSurface();
659 if(address != NULL)
661 surface->pixels = address;
662 return 1;
665 return 0;
667 static void S60_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/)
669 EpocSdlEnv::UnlockHwSurface();
672 static int S60_FlipHWSurface(_THIS, SDL_Surface* /*surface*/)
674 return(0);
677 static void S60_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
679 if(EpocSdlEnv::IsDsaAvailable())
681 if(Private->iSwSurface)
683 const TRect target(Private->iScreenPos, Private->iSwSurfaceSize);
684 for(TInt i = 0; i < numrects ;i++)
686 const TRect rect(TPoint(rects[i].x, rects[i].y),
687 TSize(rects[i].w, rects[i].h));
688 if(!EpocSdlEnv::AddUpdateRect(Private->iSwSurface, rect, target))
689 return; //not succesful
691 EpocSdlEnv::UpdateSwSurface();
693 SDL_PauseAudio(0);
695 else
697 SDL_PauseAudio(1);
698 EpocSdlEnv::WaitDsaAvailable();
702 /* Note: If we are terminated, this could be called in the middle of
703 another SDL video routine -- notably UpdateRects.
705 void S60_VideoQuit(_THIS)
707 if(_this->gl_data)
708 DestroyGles(_this);
710 User::Free(Private->iSwSurface);
711 Private->iSwSurface = NULL;
712 EpocSdlEnv::FreeSurface();
716 WMcursor *S60_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/)
718 return (WMcursor*) 1; //hii! prevents SDL to view a std cursor
721 void S60_FreeWMCursor(_THIS, WMcursor* /*cursor*/)
725 int S60_ShowWMCursor(_THIS, WMcursor *cursor)
727 return true;
730 /*FOR GL comp*/
732 void glBegin(GLenum a) {}
733 void glEnd(void) {}
734 void glOrtho(GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f) {}
735 void glPopAttrib(void) {}
736 void glPopClientAttrib(void){}
737 void glPushAttrib(GLbitfield mask) {}
738 void glPushClientAttrib(GLbitfield mask) {}
739 void glTexCoord2f(GLfloat s, GLfloat t) {}
740 void glVertex2i(GLint x, GLint y) {}