[libsdl] Initial Android port of famous libSDL
[0xdroid:external_libsdl-12.git] / src / video / android / SDL_androidvideo.cpp
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2006 Sam Lantinga
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 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     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22
23 extern "C" {
24
25 #include "SDL_config.h"
26
27 /* Dummy SDL video driver implementation; this is just enough to make an
28  *  SDL-based application THINK it's got a working video driver, for
29  *  applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it,
30  *  and also for use as a collection of stubs when porting SDL to a new
31  *  platform for which you haven't yet written a valid video driver.
32  *
33  * This is also a great way to determine bottlenecks: if you think that SDL
34  *  is a performance problem for a given platform, enable this driver, and
35  *  then see if your application runs faster without video overhead.
36  *
37  * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
38  *  of this was cut-and-pasted from Stephane Peter's work in the AAlib
39  *  SDL video driver.  Renamed to "DUMMY" by Sam Lantinga.
40  */
41
42 #include "SDL_video.h"
43 #include "SDL_mouse.h"
44 #include "../SDL_sysvideo.h"
45 #include "../SDL_pixels_c.h"
46 #include "../../events/SDL_events_c.h"
47
48 }
49
50 #include <limits.h>
51
52 #include "SDL_androidvideo.h"
53 #include "SDL_androidevents_c.h"
54 #include "SDL_androidmouse_c.h"
55
56 #include <ui/DisplayInfo.h>
57 #include <ui/Surface.h>
58 #include <ui/SurfaceComposerClient.h>
59
60 using namespace android;
61
62 extern "C" {
63
64 #define ANDROIDVID_DRIVER_NAME "android"
65
66 /* Initialization/Query functions */
67 static int ANDROID_VideoInit(_THIS, SDL_PixelFormat *vformat);
68 static SDL_Rect **ANDROID_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
69 static SDL_Surface *ANDROID_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
70 static int ANDROID_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
71 static void ANDROID_VideoQuit(_THIS);
72
73 /* Hardware surface functions */
74 static int ANDROID_AllocHWSurface(_THIS, SDL_Surface *surface);
75 static int ANDROID_LockHWSurface(_THIS, SDL_Surface *surface);
76 static void ANDROID_UnlockHWSurface(_THIS, SDL_Surface *surface);
77 static void ANDROID_FreeHWSurface(_THIS, SDL_Surface *surface);
78
79 /* etc. */
80 static void ANDROID_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
81
82 /* ANDROID driver bootstrap functions */
83
84 static int ANDROID_Available(void)
85 {
86     return 1;
87 }
88
89 static void ANDROID_DeleteDevice(SDL_VideoDevice *device)
90 {
91     delete device->hidden->scc;
92     delete device->hidden;
93     SDL_free(device);
94 }
95
96 static SDL_VideoDevice *ANDROID_CreateDevice(int devindex)
97 {
98     SDL_VideoDevice *device;
99
100     /* Initialize all variables that we clean on shutdown */
101     device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
102     if ( device ) {
103         SDL_memset(device, 0, (sizeof *device));
104         device->hidden = new SDL_PrivateVideoData;
105     }
106     if ( (device == NULL) || (device->hidden == NULL) ) {
107         SDL_OutOfMemory();
108         if ( device ) {
109             SDL_free(device);
110         }
111         return(0);
112     }
113
114     device->hidden->scc = new SurfaceComposerClient;
115
116     /* Set the function pointers */
117     device->VideoInit = ANDROID_VideoInit;
118     device->ListModes = ANDROID_ListModes;
119     device->SetVideoMode = ANDROID_SetVideoMode;
120     device->CreateYUVOverlay = NULL;
121     device->SetColors = ANDROID_SetColors;
122     device->UpdateRects = ANDROID_UpdateRects;
123     device->VideoQuit = ANDROID_VideoQuit;
124     device->AllocHWSurface = ANDROID_AllocHWSurface;
125     device->CheckHWBlit = NULL;
126     device->FillHWRect = NULL;
127     device->SetHWColorKey = NULL;
128     device->SetHWAlpha = NULL;
129     device->LockHWSurface = ANDROID_LockHWSurface;
130     device->UnlockHWSurface = ANDROID_UnlockHWSurface;
131     device->FlipHWSurface = NULL;
132     device->FreeHWSurface = ANDROID_FreeHWSurface;
133     device->SetCaption = NULL;
134     device->SetIcon = NULL;
135     device->IconifyWindow = NULL;
136     device->GrabInput = NULL;
137     device->GetWMInfo = NULL;
138     device->InitOSKeymap = ANDROID_InitOSKeymap;
139     device->PumpEvents = ANDROID_PumpEvents;
140
141     device->free = ANDROID_DeleteDevice;
142
143     return device;
144 }
145
146 VideoBootStrap ANDROID_bootstrap = {
147     ANDROIDVID_DRIVER_NAME, "SDL android video driver",
148     ANDROID_Available, ANDROID_CreateDevice
149 };
150
151
152 int ANDROID_VideoInit(_THIS, SDL_PixelFormat *vformat)
153 {
154     /* TODO: we only support RGB565 for now */
155     vformat->BitsPerPixel = 16;
156     vformat->BytesPerPixel = 2;
157
158     /* We're done! */
159     return(0);
160 }
161
162 SDL_Rect **ANDROID_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
163 {
164      return (SDL_Rect **) -1;
165 }
166
167 SDL_Surface *ANDROID_SetVideoMode(_THIS, SDL_Surface *current,
168                 int width, int height, int bpp, Uint32 flags)
169 {
170     status_t st;
171     DisplayID dpy_id = 0;
172
173     DisplayInfo dpy_info;
174     st = SurfaceComposerClient::getDisplayInfo(dpy_id, &dpy_info);
175     if (st != 0) {
176         SDL_SetError("Couldn't get display info");
177         return NULL;
178     }
179
180     self->hidden->scc->openTransaction();
181
182     self->hidden->surface = self->hidden->scc->createSurface(
183         getpid(), dpy_id, width, height, dpy_info.pixelFormatInfo.format);
184     if (!self->hidden->surface.get()) {
185         SDL_SetError("Couldn't create display surface");
186         return NULL;
187     }
188
189     self->hidden->surface->setLayer(INT_MAX);
190
191     Surface::SurfaceInfo surf_info;
192     st = self->hidden->surface->lock(&surf_info, true);
193     if (st != 0) {
194         self->hidden->surface.clear();
195         SDL_SetError("Failed to lock surface");
196         return NULL;
197     }
198     self->hidden->buffer = surf_info.bits;
199
200     st = self->hidden->surface->show();
201     if (st != 0) {
202         self->hidden->surface.clear();
203         SDL_SetError("Coundn't show display surface");
204         return NULL;
205     }
206
207     self->hidden->scc->closeTransaction();
208
209 /*  printf("Setting mode %dx%d\n", width, height); */
210
211     /* Allocate the new pixel format for the screen */
212     if (!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0)) {
213         self->hidden->surface.clear();
214         SDL_SetError("Couldn't allocate new pixel format for requested mode");
215         return NULL;
216     }
217
218     /* Set up the new mode framebuffer */
219     current->flags = flags;
220     self->hidden->w = current->w = width;
221     self->hidden->h = current->h = height;
222     current->pitch = current->w * (bpp / 8);
223     current->pixels = self->hidden->buffer;
224
225     /* We're done */
226     return current;
227 }
228
229 /* We don't actually allow hardware surfaces other than the main one */
230 static int ANDROID_AllocHWSurface(_THIS, SDL_Surface *surface)
231 {
232     return(-1);
233 }
234 static void ANDROID_FreeHWSurface(_THIS, SDL_Surface *surface)
235 {
236     return;
237 }
238
239 /* We need to wait for vertical retrace on page flipped displays */
240 static int ANDROID_LockHWSurface(_THIS, SDL_Surface *surface)
241 {
242     return(0);
243 }
244
245 static void ANDROID_UnlockHWSurface(_THIS, SDL_Surface *surface)
246 {
247     return;
248 }
249
250 static void ANDROID_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
251 {
252     if (!self->hidden->surface.get()) {
253         /* why? */
254         return;
255     }
256
257     status_t st;
258     st = self->hidden->surface->unlockAndPost();
259     if (st != 0) {
260         SDL_SetError("Failed to unlock surface");
261         return;
262     }
263
264     Surface::SurfaceInfo surf_info;
265     st = self->hidden->surface->lock(&surf_info, true);
266     if (st != 0) {
267         self->hidden->surface.clear();
268         SDL_SetError("Failed to lock surface");
269         return;
270     }
271     self->screen->pixels = self->hidden->buffer = surf_info.bits;
272 }
273
274 int ANDROID_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
275 {
276     /* do nothing of note. */
277     return(1);
278 }
279
280 /* Note:  If we are terminated, this could be called in the middle of
281    another SDL video routine -- notably UpdateRects.
282 */
283 void ANDROID_VideoQuit(_THIS)
284 {
285 #if 0
286     if (self->screen->pixels != NULL)
287     {
288         SDL_free(self->screen->pixels);
289         self->screen->pixels = NULL;
290     }
291 #endif
292 }
293
294 }