Drop support for dirty rectangles.
[SDL.s60v3.git] / src / video / symbian / SDL_epocvideo.cpp
blobe445ba0b1fb4d51e6389b204a041d1a818c6834d
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
23 #include "epoc_sdl.h"
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
28 extern "C" {
29 #include "SDL_error.h"
30 #include "SDL_timer.h"
31 #include "SDL_video.h"
32 #undef NULL
33 #include "SDL_pixels_c.h"
34 #include "SDL.h"
35 #include "SDL_mouse.h"
38 #include "SDL_epocvideo.h"
39 #include "SDL_epocevents_c.h"
40 #include <coedef.h>
41 #include <flogger.h>
42 #include <eikenv.h>
43 #include <eikappui.h>
44 #include <eikapp.h>
45 #include "sdlepocapi.h"
46 #include <SDL_gliop.h>
47 #include <egl.h>
48 #include "gles_armv5_def.h"
50 extern "C"
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);
70 /* Mouse functions */
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);
75 /*GL Functions*/
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);
82 struct WMcursor
87 static TSize GetScreenSize()
89 CWsScreenDevice *sd = new CWsScreenDevice(CEikonEnv::Static()->WsSession());
90 sd->Construct();
91 const TSize sz(sd->SizeInPixels());
92 delete sd;
94 return sz;
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;
107 delete device;
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;
116 if (device)
118 Mem::FillZ(device, (sizeof *device));
119 device->hidden = new SDL_PrivateVideoData;
120 device->gl_data = new SDL_PrivateGLData;
122 else
124 SDL_OutOfMemory();
125 return 0;
127 if((device->hidden == NULL) || (device->gl_data == NULL))
129 SDL_OutOfMemory();
130 delete device->hidden;
131 delete device->gl_data;
132 delete device;
133 return 0;
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;
165 /*gles funtions*/
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);
174 return device;
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*[3];
192 Private->iRect[0] = new SDL_Rect;
193 Private->iRect[1] = new SDL_Rect;
194 Private->iRect[2] = NULL;
196 Private->iRect[0]->x = 0;
197 Private->iRect[0]->y = 0;
199 Private->iRect[1]->x = 0;
200 Private->iRect[1]->y = 0;
202 const TSize sz = GetScreenSize();
204 Private->iRect[0]->w = sz.iWidth;
205 Private->iRect[0]->h = sz.iHeight;
207 Private->iRect[1]->w = sz.iHeight;
208 Private->iRect[1]->h = sz.iWidth;
210 Private->iOrientation = new CAknAppUi::TAppUiOrientation[2];
212 if(sz.iWidth < sz.iHeight)
214 Private->iOrientation[0] = CAknAppUi::EAppUiOrientationPortrait;
215 Private->iOrientation[1] = CAknAppUi::EAppUiOrientationLandscape;
217 else
219 Private->iOrientation[0] = CAknAppUi::EAppUiOrientationLandscape;
220 Private->iOrientation[1] = CAknAppUi::EAppUiOrientationPortrait;
223 return(0);
226 SDL_Rect **S60_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
228 if(flags & SDL_HWSURFACE)
230 if(format->BytesPerPixel != 4) //in HW only full color is supported
231 return NULL;
233 if(flags & SDL_FULLSCREEN)
235 return Private->iRect;
238 return (SDL_Rect **)(-1); //everythingisok, but too small shoes
241 int S60_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
243 if ((firstcolor+ncolors) > 256)
244 return -1;
245 TUint32 palette[256];
246 int c = 0;
248 for(int i = firstcolor; i < firstcolor+ncolors; i++)
250 TUint32 color64K = (colors[c].r & 0x0000f8) << 8;
251 color64K |= (colors[c].g & 0x0000fc) << 3;
252 color64K |= (colors[c].b & 0x0000f8) >> 3;
253 palette[i] = color64K;
254 c++;
257 if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone)
259 return 0;
261 return -1;
264 int S60_GlesLoadLibrary(SDL_VideoDevice* _this, const char* path)
266 if(_this->gl_data->iLibrary.Handle() != 0)
267 return KErrAlreadyExists; //already loaded
268 const char* const gles_lib[] = {"libgles_cm.dll", "libSWGLES.dll"};
269 int err = KErrNotFound;
270 for(int i = 0; i < 2 && err != KErrNone; i++)
272 const char* name8 = path == NULL ? gles_lib[i] : path;
273 TFileName lib;
274 lib.Copy(TPtrC8((unsigned char*)name8));
275 err = _this->gl_data->iLibrary.Load(lib);
277 if(err == KErrNone)
278 _this->gl_config.driver_loaded = 1;
279 return err;
282 typedef int (*Ftp)(...);
283 #define DC(x) ((Ftp) S60_GlesGetProcAddress(_this, #x))
285 const char* const OpenGL[] = //these funtions are in gl, but not in gles, at least in all in all versions...
287 "glBegin",
288 "glEnd",
289 "glOrtho",
290 "glPopAttrib",
291 "glPopClientAttrib",
292 "glPushAttrib",
293 "glPushClientAttrib",
294 "glTexCoord2f",
295 "glVertex2i",
296 "glTexParameteri"
299 int NotSupported()
301 User::Panic(_L("SDL, Gles"), KErrNotSupported);
302 return 0;
305 void* S60_GlesGetProcAddress(_THIS, const char *proc)
307 if(_this->gl_data->iLibrary.Handle() == 0)
308 return NULL; //not loaded
309 TLibraryFunction f = NULL;
310 for(int i = 0; i < G_ordinals_count; i++)
312 if(strcmp(G_ordinals[i].name, proc) == 0)
314 f = _this->gl_data->iLibrary.Lookup(G_ordinals[i].ord);
315 break;
319 if(f != NULL) /*Lookup may fail*/
320 return (void*) f;
322 for(int i = 0; i < sizeof(OpenGL) / sizeof(char*); i++)
324 if(strcmp(OpenGL[i], proc) == 0)
325 return (void*) NotSupported;
328 return NULL;
331 int S60_GlesGetAttribute(_THIS, SDL_GLattr aAttrib, int* aValue)
333 EGLint attrib;
334 switch(aAttrib)
336 /*todo*/
337 case SDL_GL_RED_SIZE: attrib = EGL_RED_SIZE; break;
338 case SDL_GL_GREEN_SIZE: attrib = EGL_GREEN_SIZE; break;
339 case SDL_GL_BLUE_SIZE:attrib = EGL_BLUE_SIZE; break;
340 case SDL_GL_ALPHA_SIZE: attrib = EGL_ALPHA_SIZE; break;
341 case SDL_GL_BUFFER_SIZE: attrib = EGL_BUFFER_SIZE; break;
342 case SDL_GL_DOUBLEBUFFER: *aValue = 1; return 0; //always
343 case SDL_GL_DEPTH_SIZE: attrib = EGL_DEPTH_SIZE; break;
344 case SDL_GL_STENCIL_SIZE: attrib = EGL_STENCIL_SIZE; break;
345 case SDL_GL_ACCUM_RED_SIZE:
346 case SDL_GL_ACCUM_GREEN_SIZE:
347 case SDL_GL_ACCUM_BLUE_SIZE:
348 case SDL_GL_ACCUM_ALPHA_SIZE:
349 case SDL_GL_STEREO:
350 case SDL_GL_MULTISAMPLEBUFFERS:
351 case SDL_GL_MULTISAMPLESAMPLES:
352 case SDL_GL_ACCELERATED_VISUAL:
353 case SDL_GL_SWAP_CONTROL:
354 *aValue = 0;
355 return -1;
357 const int success = DC(eglGetConfigAttrib)
359 _this->gl_data->iDisplay,
360 _this->gl_data->iConfig,
361 attrib,
362 aValue);
363 return success == EGL_FALSE ? -1 : 0;
367 int S60_GlesMakeCurrent(_THIS)
369 DC(eglMakeCurrent)
370 (_this->gl_data->iDisplay,
371 _this->gl_data->iSurface,
372 _this->gl_data->iSurface,
373 _this->gl_data->iContext);
374 return DC(eglGetError)();
377 void S60_GlesSwapBuffers(_THIS)
379 DC(eglSwapBuffers)(
380 _this->gl_data->iDisplay,
381 _this->gl_data->iSurface);
384 static void glAssert(_THIS)
386 const EGLint err = DC(eglGetError)();
387 if(err != EGL_SUCCESS)
389 User::Leave(err);
393 static void CreateGles(_THIS, RWindow& aWindow, int bpp, SDL_PrivateGLData& aData)
395 SDL_GL_LoadLibrary(NULL); //just if its not already loaded
396 aData.iDisplay = DC(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
397 DC(eglInitialize)(aData.iDisplay, NULL, NULL);
399 glAssert(_this);
401 int configs = 0;
402 EGLConfig* configList = NULL;
403 int configSz = 0;
404 DC(eglGetConfigs)(aData.iDisplay, configList, configSz, &configs);
405 configSz = configs;
407 glAssert(_this);
409 configList = new EGLConfig[configSz];
411 int red, green, blue;
412 if(bpp == 16)
414 red = 5;
415 green = 6;
416 blue = 5;
418 else
420 red = 8;
421 green = 8;
422 blue = 8;
425 const EGLint attribList[] =
427 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
428 EGL_RED_SIZE, red,
429 EGL_GREEN_SIZE, green,
430 EGL_BLUE_SIZE, blue,
431 EGL_BUFFER_SIZE, EGL_DONT_CARE,
432 EGL_DEPTH_SIZE, 8,
433 EGL_NONE
436 DC(eglChooseConfig)(aData.iDisplay,
437 attribList,
438 configList,
439 configSz,
440 &configs);
443 glAssert(_this);
445 __ASSERT_ALWAYS(configs > 0, User::Invariant());
447 aData.iConfig = configList[0];
449 delete[] configList;
451 aData.iContext = DC(eglCreateContext)(aData.iDisplay,
452 aData.iConfig,
453 EGL_NO_CONTEXT,
454 NULL);
456 glAssert(_this);
458 aData.iSurface = DC(eglCreateWindowSurface)(aData.iDisplay,
459 aData.iConfig,
460 &aWindow,
461 NULL);
463 glAssert(_this);
467 static void DestroyGles(_THIS)
469 if( _this->gl_config.driver_loaded)
471 DC(eglMakeCurrent)(_this->gl_data->iDisplay,
472 EGL_NO_SURFACE,
473 EGL_NO_SURFACE,
474 EGL_NO_CONTEXT);
475 DC(eglDestroySurface)(_this->gl_data->iDisplay, _this->gl_data->iSurface);
476 DC(eglDestroyContext)(_this->gl_data->iDisplay, _this->gl_data->iContext);
477 DC(eglTerminate)(_this->gl_data->iDisplay);
478 _this->gl_data->iLibrary.Close();
479 _this->gl_config.driver_loaded = 0;
483 SDL_Surface *S60_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
485 if(flags & SDL_OPENGL)
487 current->flags |= SDL_OPENGL;
488 current->w = width;
489 current->h = height;
491 RWindow* win = EpocSdlEnv::Window();
492 EpocSdlEnv::ApplyGlesDsa();
494 CreateGles(_this, *win, bpp, *_this->gl_data);
496 return current;
499 if(flags & SDL_HWSURFACE)
500 return NULL;
502 // check orientation and resolution validity
503 bool resValid = false;
504 Orientation orientation = CAknAppUi::EAppUiOrientationUnspecified;
505 for(int i=0; i<2; i++)
507 if(width <= Private->iRect[i]->w && height <= Private->iRect[i]->h)
509 orientation = Private->iOrientation[i];
510 resValid = true;
511 break;
514 if(!resValid)
515 return NULL;
517 if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0))
518 return NULL;
520 const int numBytesPerPixel = ((bpp-1)>>3) + 1;
521 current->pitch = numBytesPerPixel * width;
523 // set proper surface flags
524 current->flags = SDL_SWSURFACE | SDL_PREALLOC;
525 if(flags & SDL_FULLSCREEN)
526 current->flags |= SDL_FULLSCREEN;
527 if(flags & SDL_RESIZABLE)
528 current->flags |= SDL_RESIZABLE;
529 if(bpp <= 8)
530 current->flags |= SDL_HWPALETTE;
532 current->w = width;
533 current->h = height;
535 // allocate surface
536 const int surfacesize = width * height * numBytesPerPixel;
537 Private->iSwSurfaceSize = TSize(width, height);
539 delete[] (TUint8*)current->pixels;
540 current->pixels = new TUint8[surfacesize];
541 Private->iSwSurface = (TUint8*) current->pixels;
543 if(current->pixels == NULL)
544 return NULL;
546 const TSize sz = GetScreenSize();
548 if(sz.iWidth < sz.iHeight && orientation != CAknAppUi::EAppUiOrientationPortrait ||
549 sz.iWidth > sz.iHeight && orientation != CAknAppUi::EAppUiOrientationLandscape)
551 g_SDL->SetOrientation(orientation, TSize(width, height), current->format->BitsPerPixel / 8);
553 else
555 if((flags & SDL_RESIZABLE) == 0)
557 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
559 else
561 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationUnspecified));
564 const int err = EpocSdlEnv::AllocSurface(TSize(width, height), current->format->BitsPerPixel / 8);
565 if(err != KErrNone)
566 return NULL;
569 // Set the blit function
570 _this->UpdateRects = S60_DirectUpdate;
572 return current;
575 static int S60_AllocHWSurface(_THIS, SDL_Surface* surface)
577 return KErrNone == EpocSdlEnv::AllocSurface(TSize(surface->w, surface->h), surface->format->BitsPerPixel / 8);
580 static void S60_FreeHWSurface(_THIS, SDL_Surface* /*surface*/)
584 static int S60_LockHWSurface(_THIS, SDL_Surface* surface)
586 if(EpocSdlEnv::IsDsaAvailable())
588 TUint8* address = EpocSdlEnv::LockHwSurface();
589 if(address != NULL)
591 surface->pixels = address;
592 return 1;
595 return 0;
597 static void S60_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/)
599 EpocSdlEnv::UnlockHwSurface();
602 static int S60_FlipHWSurface(_THIS, SDL_Surface* /*surface*/)
604 return(0);
607 static void S60_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
609 if(EpocSdlEnv::IsDsaAvailable())
611 if(Private->iSwSurface)
613 const TRect target(TPoint(0, 0), Private->iSwSurfaceSize);
615 EpocSdlEnv::AddUpdateRect(Private->iSwSurface, target, target);
616 EpocSdlEnv::UpdateSwSurface();
618 if(!Private->iIsWindowFocused)
620 User::After(100000);
625 /* Note: If we are terminated, this could be called in the middle of
626 another SDL video routine -- notably UpdateRects.
628 void S60_VideoQuit(_THIS)
630 delete[] Private->iOrientation;
632 delete Private->iRect[0];
633 delete Private->iRect[1];
634 delete[] Private->iRect;
636 if(_this->gl_data)
637 DestroyGles(_this);
639 delete[] Private->iSwSurface;
640 Private->iSwSurface = NULL;
641 EpocSdlEnv::FreeSurface();
645 WMcursor *S60_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/)
647 // prevents SDL from displaying standard cursor
648 return (WMcursor*) 1;
651 void S60_FreeWMCursor(_THIS, WMcursor* /*cursor*/)
655 int S60_ShowWMCursor(_THIS, WMcursor *cursor)
657 return true;
660 /*FOR GL comp*/
662 void glBegin(GLenum a) {}
663 void glEnd(void) {}
664 void glOrtho(GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f) {}
665 void glPopAttrib(void) {}
666 void glPopClientAttrib(void){}
667 void glPushAttrib(GLbitfield mask) {}
668 void glPushClientAttrib(GLbitfield mask) {}
669 void glTexCoord2f(GLfloat s, GLfloat t) {}
670 void glVertex2i(GLint x, GLint y) {}