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
25 Epoc based SDL video driver implementation
37 #include "SDL_error.h"
38 #include "SDL_timer.h"
39 #include "SDL_video.h"
41 #include "SDL_pixels_c.h"
43 #include "SDL_mouse.h"
46 #include "SDL_epocvideo.h"
47 #include "SDL_epocevents_c.h"
54 #include "sdlepocapi.h"
55 #include <SDL_gliop.h>
58 #include "gles_armv5_def.h"
60 _LIT(KLibName
, "SDL");
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
,
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
);
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
);
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
);
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
);
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
)));
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
))));
145 if((device
->hidden
== NULL
) || (device
->gl_data
== NULL
))
148 User::Free(device
->hidden
);
149 User::Free(device
->gl_data
);
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
;
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);
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
;
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
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)
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
++)
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
;
300 if(EpocSdlEnv::SetPalette(firstcolor
, ncolors
, palette
) == KErrNone
)
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
;
315 lib
.Copy(TPtrC8((unsigned char*)name8
));
316 err
= _this
->gl_data
->iLibrary
.Load(lib
);
319 _this
->gl_config
.driver_loaded
= 1;
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...
334 "glPushClientAttrib",
342 User::Panic(_L("SDL, Gles"), KErrNotSupported
);
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
);
360 if(f
!= NULL
) /*Lookup may fail*/
363 for(TInt i
= 0; i
< sizeof(OpenGL
) / sizeof(char*); i
++)
365 if(strcmp(OpenGL
[i
], proc
) == 0)
366 return (void*) NotSupported
;
374 int S60_GlesGetAttribute(_THIS
, SDL_GLattr aAttrib
, int* aValue
)
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
:
393 case SDL_GL_MULTISAMPLEBUFFERS
:
394 case SDL_GL_MULTISAMPLESAMPLES
:
395 case SDL_GL_ACCELERATED_VISUAL
:
396 case SDL_GL_SWAP_CONTROL
:
400 const int success
= DC(eglGetConfigAttrib
)
402 _this
->gl_data
->iDisplay
,
403 _this
->gl_data
->iConfig
,
406 return success
== EGL_FALSE
? -1 : 0;
410 int S60_GlesMakeCurrent(_THIS
)
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
)
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
)
440 while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode
)) &&
441 TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode
)) !=
445 return TDisplayMode(dmode
);
449 LOCAL_C
void glAssert(_THIS
)
451 const EGLint err
= DC(eglGetError
)();
452 if(err
!= EGL_SUCCESS
)
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
);
467 EGLConfig
* configList
= NULL
;
469 DC(eglGetConfigs
)(aData
.iDisplay
, configList
, configSz
, &configs
);
474 configList
= (EGLConfig
*) User::Alloc(sizeof(EGLConfig
) * configSz
);
476 TInt red
, green
, blue
;
490 const EGLint attribList
[] =
492 EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
,
494 EGL_GREEN_SIZE
, green
,
496 EGL_BUFFER_SIZE
, EGL_DONT_CARE
,
501 DC(eglChooseConfig
)(aData
.iDisplay
,
510 __ASSERT_ALWAYS(configs
> 0, User::Invariant());
512 aData
.iConfig
= configList
[0];
514 User::Free(configList
);
516 aData
.iContext
= DC(eglCreateContext
)(aData
.iDisplay
,
523 aData
.iSurface
= DC(eglCreateWindowSurface
)(aData
.iDisplay
,
533 LOCAL_C
void DestroyGles(_THIS
)
535 if( _this
->gl_config
.driver_loaded
)
537 DC(eglMakeCurrent
)(_this
->gl_data
->iDisplay
,
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
;
558 RWindow
* win
= EpocSdlEnv::Window();
559 EpocSdlEnv::ApplyGlesDsa();
561 CreateGles(_this
, *win
, bpp
, *_this
->gl_data
);
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
;
577 if(current
&& current
->pixels
)
579 current
->pixels
= NULL
;
582 if(!SDL_ReallocFormat(current
, bpp
, 0, 0, 0, 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
;
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
;
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
)
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
);
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();
661 surface
->pixels
= address
;
667 static void S60_UnlockHWSurface(_THIS
, SDL_Surface
* /*surface*/)
669 EpocSdlEnv::UnlockHwSurface();
672 static int S60_FlipHWSurface(_THIS
, SDL_Surface
* /*surface*/)
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();
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
)
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
)
732 void glBegin(GLenum a
) {}
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
) {}