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
20 slouken@devolution.com
29 #include "SDL_error.h"
30 #include "SDL_timer.h"
31 #include "SDL_video.h"
33 #include "SDL_pixels_c.h"
35 #include "SDL_mouse.h"
38 #include "SDL_epocvideo.h"
39 #include "SDL_epocevents_c.h"
45 #include "sdlepocapi.h"
46 #include <SDL_gliop.h>
48 #include "gles_armv5_def.h"
52 /* Initialization/Query functions */
53 static int S60_VideoInit(_THIS
, SDL_PixelFormat
*vformat
);
54 static SDL_Rect
**S60_ListModes(_THIS
, SDL_PixelFormat
*format
, Uint32 flags
);
55 static SDL_Surface
*S60_SetVideoMode(_THIS
, SDL_Surface
*current
, int width
, int height
, int bpp
, Uint32 flags
);
56 static int S60_SetColors(_THIS
, int firstcolor
, int ncolors
, SDL_Color
*colors
);
57 static void S60_VideoQuit(_THIS
);
59 /* Hardware surface functions */
60 static int S60_AllocHWSurface(_THIS
, SDL_Surface
*surface
);
61 static int S60_LockHWSurface(_THIS
, SDL_Surface
*surface
);
62 static int S60_FlipHWSurface(_THIS
, SDL_Surface
*surface
);
63 static void S60_UnlockHWSurface(_THIS
, SDL_Surface
*surface
);
64 static void S60_FreeHWSurface(_THIS
, SDL_Surface
*surface
);
65 static void S60_DirectUpdate(_THIS
, int numrects
, SDL_Rect
*rects
);
67 static int S60_Available(void);
68 static SDL_VideoDevice
*S60_CreateDevice(int devindex
);
71 static WMcursor
*S60_CreateWMCursor(_THIS
, Uint8
*data
, Uint8
*mask
, int w
, int h
, int hot_x
, int hot_y
);
72 static void S60_FreeWMCursor(_THIS
, WMcursor
*cursor
);
73 static int S60_ShowWMCursor(_THIS
, WMcursor
*cursor
);
76 static int S60_GlesLoadLibrary(_THIS
, const char* path
);
77 static void* S60_GlesGetProcAddress(_THIS
, const char *proc
);
78 static int S60_GlesGetAttribute(_THIS
, SDL_GLattr attrib
, int* value
);
79 static int S60_GlesMakeCurrent(_THIS
);
80 static void S60_GlesSwapBuffers(_THIS
);
87 static TSize
GetScreenSize()
89 CWsScreenDevice
*sd
= new CWsScreenDevice(CEikonEnv::Static()->WsSession());
91 const TSize
sz(sd
->SizeInPixels());
97 /* Epoc video driver bootstrap functions */
98 static int S60_Available(void)
100 return 1; /* Always available */
103 static void S60_DeleteDevice(SDL_VideoDevice
*device
)
105 delete device
->gl_data
;
106 delete device
->hidden
;
110 static SDL_VideoDevice
*S60_CreateDevice(int /*devindex*/)
112 SDL_VideoDevice
*device
;
114 /* Allocate all variables that we free on delete */
115 device
= new SDL_VideoDevice
;
118 Mem::FillZ(device
, (sizeof *device
));
119 device
->hidden
= new SDL_PrivateVideoData
;
120 device
->gl_data
= new SDL_PrivateGLData
;
127 if((device
->hidden
== NULL
) || (device
->gl_data
== NULL
))
130 delete device
->hidden
;
131 delete device
->gl_data
;
136 Mem::FillZ(device
->hidden
, (sizeof *device
->hidden
));
138 /* Set the function pointers */
139 device
->VideoInit
= S60_VideoInit
;
140 device
->ListModes
= S60_ListModes
;
141 device
->SetVideoMode
= S60_SetVideoMode
;
142 device
->SetColors
= S60_SetColors
;
143 device
->UpdateRects
= NULL
;
144 device
->VideoQuit
= S60_VideoQuit
;
145 device
->AllocHWSurface
= S60_AllocHWSurface
;
146 device
->CheckHWBlit
= NULL
;
147 device
->FillHWRect
= NULL
;
148 device
->SetHWColorKey
= NULL
;
149 device
->SetHWAlpha
= NULL
;
150 device
->LockHWSurface
= S60_LockHWSurface
;
151 device
->UnlockHWSurface
= S60_UnlockHWSurface
;
152 device
->FlipHWSurface
= S60_FlipHWSurface
;
153 device
->FreeHWSurface
= S60_FreeHWSurface
;
154 device
->SetIcon
= NULL
;
155 device
->SetCaption
= NULL
;
156 device
->GetWMInfo
= NULL
;
157 device
->FreeWMCursor
= S60_FreeWMCursor
;
158 device
->CreateWMCursor
= S60_CreateWMCursor
;
159 device
->ShowWMCursor
= S60_ShowWMCursor
;
160 device
->WarpWMCursor
= NULL
;
161 device
->InitOSKeymap
= EPOC_InitOSKeymap
;
162 device
->PumpEvents
= EPOC_PumpEvents
;
163 device
->free
= S60_DeleteDevice
;
166 device
->GL_LoadLibrary
= S60_GlesLoadLibrary
;
167 device
->GL_GetProcAddress
= S60_GlesGetProcAddress
;
168 device
->GL_GetAttribute
= S60_GlesGetAttribute
;
169 device
->GL_MakeCurrent
= S60_GlesMakeCurrent
;
170 device
->GL_SwapBuffers
= S60_GlesSwapBuffers
;
172 device
->gl_data
->iLibrary
.SetHandle(0);
177 VideoBootStrap EPOC_bootstrap
= {
178 "epoc\0\0\0", "EPOC system",
179 S60_Available
, S60_CreateDevice
182 int S60_VideoInit(_THIS
, SDL_PixelFormat
*vformat
)
184 /* Initialise Epoc frame buffer */
186 /* The "best" video format should be returned to caller. */
188 vformat
->BitsPerPixel
= 16;
189 vformat
->BytesPerPixel
= 2;
191 Private
->iRect
= new SDL_Rect
*[5];
192 Private
->iRect
[0] = new SDL_Rect
;
193 Private
->iRect
[1] = new SDL_Rect
;
194 Private
->iRect
[2] = new SDL_Rect
;
195 Private
->iRect
[3] = new SDL_Rect
;
196 Private
->iRect
[4] = NULL
;
198 for( int i
=0; i
<4; i
++ )
200 Private
->iRect
[i
]->x
= 0;
201 Private
->iRect
[i
]->y
= 0;
204 const TSize sz
= GetScreenSize();
206 Private
->iRect
[0]->w
= sz
.iWidth
;
207 Private
->iRect
[0]->h
= sz
.iHeight
;
209 Private
->iRect
[1]->w
= sz
.iHeight
;
210 Private
->iRect
[1]->h
= sz
.iWidth
;
212 Private
->iRect
[2]->w
= sz
.iWidth
* 2;
213 Private
->iRect
[2]->h
= sz
.iHeight
* 2;
215 Private
->iRect
[3]->w
= sz
.iHeight
* 2;
216 Private
->iRect
[3]->h
= sz
.iWidth
* 2;
218 Private
->iOrientation
= new CAknAppUi::TAppUiOrientation
[4];
220 if(sz
.iWidth
< sz
.iHeight
)
222 Private
->iOrientation
[0] = CAknAppUi::EAppUiOrientationPortrait
;
223 Private
->iOrientation
[1] = CAknAppUi::EAppUiOrientationLandscape
;
224 Private
->iOrientation
[2] = CAknAppUi::EAppUiOrientationPortrait
;
225 Private
->iOrientation
[3] = CAknAppUi::EAppUiOrientationLandscape
;
229 Private
->iOrientation
[0] = CAknAppUi::EAppUiOrientationLandscape
;
230 Private
->iOrientation
[1] = CAknAppUi::EAppUiOrientationPortrait
;
231 Private
->iOrientation
[2] = CAknAppUi::EAppUiOrientationLandscape
;
232 Private
->iOrientation
[3] = CAknAppUi::EAppUiOrientationPortrait
;
238 SDL_Rect
**S60_ListModes(_THIS
, SDL_PixelFormat
*format
, Uint32 flags
)
240 if(flags
& SDL_HWSURFACE
)
242 if(format
->BytesPerPixel
!= 4) //in HW only full color is supported
245 if(flags
& SDL_FULLSCREEN
)
247 return Private
->iRect
;
250 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)
257 TUint32 palette
[256];
260 for(int i
= firstcolor
; i
< firstcolor
+ncolors
; i
++)
262 TUint32 color64K
= (colors
[c
].r
& 0x0000f8) << 8;
263 color64K
|= (colors
[c
].g
& 0x0000fc) << 3;
264 color64K
|= (colors
[c
].b
& 0x0000f8) >> 3;
265 palette
[i
] = color64K
;
269 if(EpocSdlEnv::SetPalette(firstcolor
, ncolors
, palette
) == KErrNone
)
276 int S60_GlesLoadLibrary(SDL_VideoDevice
* _this
, const char* path
)
278 if(_this
->gl_data
->iLibrary
.Handle() != 0)
279 return KErrAlreadyExists
; //already loaded
280 const char* const gles_lib
[] = {"libgles_cm.dll", "libSWGLES.dll"};
281 int err
= KErrNotFound
;
282 for(int i
= 0; i
< 2 && err
!= KErrNone
; i
++)
284 const char* name8
= path
== NULL
? gles_lib
[i
] : path
;
286 lib
.Copy(TPtrC8((unsigned char*)name8
));
287 err
= _this
->gl_data
->iLibrary
.Load(lib
);
290 _this
->gl_config
.driver_loaded
= 1;
294 typedef int (*Ftp
)(...);
295 #define DC(x) ((Ftp) S60_GlesGetProcAddress(_this, #x))
297 const char* const OpenGL
[] = //these funtions are in gl, but not in gles, at least in all in all versions...
305 "glPushClientAttrib",
313 User::Panic(_L("SDL, Gles"), KErrNotSupported
);
317 void* S60_GlesGetProcAddress(_THIS
, const char *proc
)
319 if(_this
->gl_data
->iLibrary
.Handle() == 0)
320 return NULL
; //not loaded
321 TLibraryFunction f
= NULL
;
322 for(int i
= 0; i
< G_ordinals_count
; i
++)
324 if(strcmp(G_ordinals
[i
].name
, proc
) == 0)
326 f
= _this
->gl_data
->iLibrary
.Lookup(G_ordinals
[i
].ord
);
331 if(f
!= NULL
) /*Lookup may fail*/
334 for(int i
= 0; i
< sizeof(OpenGL
) / sizeof(char*); i
++)
336 if(strcmp(OpenGL
[i
], proc
) == 0)
337 return (void*) NotSupported
;
343 int S60_GlesGetAttribute(_THIS
, SDL_GLattr aAttrib
, int* aValue
)
349 case SDL_GL_RED_SIZE
: attrib
= EGL_RED_SIZE
; break;
350 case SDL_GL_GREEN_SIZE
: attrib
= EGL_GREEN_SIZE
; break;
351 case SDL_GL_BLUE_SIZE
:attrib
= EGL_BLUE_SIZE
; break;
352 case SDL_GL_ALPHA_SIZE
: attrib
= EGL_ALPHA_SIZE
; break;
353 case SDL_GL_BUFFER_SIZE
: attrib
= EGL_BUFFER_SIZE
; break;
354 case SDL_GL_DOUBLEBUFFER
: *aValue
= 1; return 0; //always
355 case SDL_GL_DEPTH_SIZE
: attrib
= EGL_DEPTH_SIZE
; break;
356 case SDL_GL_STENCIL_SIZE
: attrib
= EGL_STENCIL_SIZE
; break;
357 case SDL_GL_ACCUM_RED_SIZE
:
358 case SDL_GL_ACCUM_GREEN_SIZE
:
359 case SDL_GL_ACCUM_BLUE_SIZE
:
360 case SDL_GL_ACCUM_ALPHA_SIZE
:
362 case SDL_GL_MULTISAMPLEBUFFERS
:
363 case SDL_GL_MULTISAMPLESAMPLES
:
364 case SDL_GL_ACCELERATED_VISUAL
:
365 case SDL_GL_SWAP_CONTROL
:
369 const int success
= DC(eglGetConfigAttrib
)
371 _this
->gl_data
->iDisplay
,
372 _this
->gl_data
->iConfig
,
375 return success
== EGL_FALSE
? -1 : 0;
379 int S60_GlesMakeCurrent(_THIS
)
382 (_this
->gl_data
->iDisplay
,
383 _this
->gl_data
->iSurface
,
384 _this
->gl_data
->iSurface
,
385 _this
->gl_data
->iContext
);
386 return DC(eglGetError
)();
389 void S60_GlesSwapBuffers(_THIS
)
392 _this
->gl_data
->iDisplay
,
393 _this
->gl_data
->iSurface
);
396 static void glAssert(_THIS
)
398 const EGLint err
= DC(eglGetError
)();
399 if(err
!= EGL_SUCCESS
)
405 static void CreateGles(_THIS
, RWindow
& aWindow
, int bpp
, SDL_PrivateGLData
& aData
)
407 SDL_GL_LoadLibrary(NULL
); //just if its not already loaded
408 aData
.iDisplay
= DC(eglGetDisplay
)(EGL_DEFAULT_DISPLAY
);
409 DC(eglInitialize
)(aData
.iDisplay
, NULL
, NULL
);
414 EGLConfig
* configList
= NULL
;
416 DC(eglGetConfigs
)(aData
.iDisplay
, configList
, configSz
, &configs
);
421 configList
= new EGLConfig
[configSz
];
423 int red
, green
, blue
;
437 const EGLint attribList
[] =
439 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
,
441 EGL_GREEN_SIZE
, green
,
443 EGL_BUFFER_SIZE
, EGL_DONT_CARE
,
448 DC(eglChooseConfig
)(aData
.iDisplay
,
457 __ASSERT_ALWAYS(configs
> 0, User::Invariant());
459 aData
.iConfig
= configList
[0];
463 aData
.iContext
= DC(eglCreateContext
)(aData
.iDisplay
,
470 aData
.iSurface
= DC(eglCreateWindowSurface
)(aData
.iDisplay
,
479 static void DestroyGles(_THIS
)
481 if( _this
->gl_config
.driver_loaded
)
483 DC(eglMakeCurrent
)(_this
->gl_data
->iDisplay
,
487 DC(eglDestroySurface
)(_this
->gl_data
->iDisplay
, _this
->gl_data
->iSurface
);
488 DC(eglDestroyContext
)(_this
->gl_data
->iDisplay
, _this
->gl_data
->iContext
);
489 DC(eglTerminate
)(_this
->gl_data
->iDisplay
);
490 _this
->gl_data
->iLibrary
.Close();
491 _this
->gl_config
.driver_loaded
= 0;
495 SDL_Surface
*S60_SetVideoMode(_THIS
, SDL_Surface
*current
, int width
, int height
, int bpp
, Uint32 flags
)
497 if(flags
& SDL_OPENGL
)
499 current
->flags
|= SDL_OPENGL
;
503 RWindow
* win
= EpocSdlEnv::Window();
504 EpocSdlEnv::ApplyGlesDsa();
506 CreateGles(_this
, *win
, bpp
, *_this
->gl_data
);
511 if(flags
& SDL_HWSURFACE
)
514 // check orientation and resolution validity
515 bool resValid
= false;
516 Orientation orientation
= CAknAppUi::EAppUiOrientationUnspecified
;
517 for(int i
=0; i
<4; i
++)
519 if(width
<= Private
->iRect
[i
]->w
&& height
<= Private
->iRect
[i
]->h
)
521 orientation
= Private
->iOrientation
[i
];
529 if(!SDL_ReallocFormat(current
, bpp
, 0, 0, 0, 0))
532 const int numBytesPerPixel
= ((bpp
-1)>>3) + 1;
533 current
->pitch
= numBytesPerPixel
* width
;
535 // set proper surface flags
536 current
->flags
= SDL_SWSURFACE
| SDL_PREALLOC
;
537 if(flags
& SDL_FULLSCREEN
)
538 current
->flags
|= SDL_FULLSCREEN
;
539 if(flags
& SDL_RESIZABLE
)
540 current
->flags
|= SDL_RESIZABLE
;
542 current
->flags
|= SDL_HWPALETTE
;
548 const int surfacesize
= width
* height
* numBytesPerPixel
;
549 Private
->iSwSurfaceSize
= TSize(width
, height
);
551 delete[] (TUint8
*)current
->pixels
;
552 current
->pixels
= new TUint8
[surfacesize
];
553 Private
->iSwSurface
= (TUint8
*) current
->pixels
;
555 if(current
->pixels
== NULL
)
558 const TSize sz
= GetScreenSize();
560 if(sz
.iWidth
< sz
.iHeight
&& orientation
!= CAknAppUi::EAppUiOrientationPortrait
||
561 sz
.iWidth
> sz
.iHeight
&& orientation
!= CAknAppUi::EAppUiOrientationLandscape
)
563 g_SDL
->SetOrientation(orientation
, current
->format
->BitsPerPixel
/ 8);
567 if((flags
& SDL_RESIZABLE
) == 0)
569 TRAPD(err
, static_cast<CAknAppUi
*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation
));
573 TRAPD(err
, static_cast<CAknAppUi
*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationUnspecified
));
576 const int err
= EpocSdlEnv::AllocSurface(current
->format
->BitsPerPixel
/ 8);
581 // Set the blit function
582 _this
->UpdateRects
= S60_DirectUpdate
;
587 static int S60_AllocHWSurface(_THIS
, SDL_Surface
* surface
)
589 return KErrNone
== EpocSdlEnv::AllocSurface(surface
->format
->BitsPerPixel
/ 8);
592 static void S60_FreeHWSurface(_THIS
, SDL_Surface
* /*surface*/)
596 static int S60_LockHWSurface(_THIS
, SDL_Surface
* surface
)
598 if(EpocSdlEnv::IsDsaAvailable())
600 TUint8
* address
= EpocSdlEnv::LockHwSurface();
603 surface
->pixels
= address
;
609 static void S60_UnlockHWSurface(_THIS
, SDL_Surface
* /*surface*/)
611 EpocSdlEnv::UnlockHwSurface();
614 static int S60_FlipHWSurface(_THIS
, SDL_Surface
* /*surface*/)
619 static void S60_DirectUpdate(_THIS
, int numrects
, SDL_Rect
*rects
)
621 if(EpocSdlEnv::IsDsaAvailable())
623 if(Private
->iSwSurface
)
625 EpocSdlEnv::Blit(Private
->iSwSurface
, Private
->iSwSurfaceSize
);
627 if(!Private
->iIsWindowFocused
)
634 /* Note: If we are terminated, this could be called in the middle of
635 another SDL video routine -- notably UpdateRects.
637 void S60_VideoQuit(_THIS
)
639 delete[] Private
->iOrientation
;
641 delete Private
->iRect
[0];
642 delete Private
->iRect
[1];
643 delete[] Private
->iRect
;
648 delete[] Private
->iSwSurface
;
649 Private
->iSwSurface
= NULL
;
650 EpocSdlEnv::FreeSurface();
654 WMcursor
*S60_CreateWMCursor(_THIS
, Uint8
* /*data*/, Uint8
* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/)
656 // prevents SDL from displaying standard cursor
657 return (WMcursor
*) 1;
660 void S60_FreeWMCursor(_THIS
, WMcursor
* /*cursor*/)
664 int S60_ShowWMCursor(_THIS
, WMcursor
*cursor
)
671 void glBegin(GLenum a
) {}
673 void glOrtho(GLdouble l
, GLdouble r
, GLdouble b
, GLdouble t
, GLdouble n
, GLdouble f
) {}
674 void glPopAttrib(void) {}
675 void glPopClientAttrib(void){}
676 void glPushAttrib(GLbitfield mask
) {}
677 void glPushClientAttrib(GLbitfield mask
) {}
678 void glTexCoord2f(GLfloat s
, GLfloat t
) {}
679 void glVertex2i(GLint x
, GLint y
) {}