1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
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.
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    Library General Public License for more details.
14
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
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/*
25     File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability
26	 23 March 2003
27
28     Implements RISC OS display device management.
29	 Routines for full screen and wimp modes are split
30	 into other source files.
31*/
32
33#include "SDL_video.h"
34#include "SDL_mouse.h"
35#include "SDL_syswm.h"
36#include "../SDL_sysvideo.h"
37#include "../SDL_pixels_c.h"
38#include "../../events/SDL_events_c.h"
39
40#include "SDL_riscostask.h"
41#include "SDL_riscosvideo.h"
42#include "SDL_riscosevents_c.h"
43#include "SDL_riscosmouse_c.h"
44
45#include "kernel.h"
46#include "swis.h"
47
48#define RISCOSVID_DRIVER_NAME "riscos"
49
50/* Initialization/Query functions */
51static int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat);
52static void RISCOS_VideoQuit(_THIS);
53
54static SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
55static SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
56
57int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info);
58
59int RISCOS_ToggleFullScreen(_THIS, int fullscreen);
60/* Mouse checking */
61void RISCOS_CheckMouseMode(_THIS);
62extern SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode);
63
64/* Fullscreen mode functions */
65extern SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
66extern void FULLSCREEN_BuildModeList(_THIS);
67extern void	FULLSCREEN_SetDeviceMode(_THIS);
68extern int FULLSCREEN_ToggleFromWimp(_THIS);
69
70/* Wimp mode functions */
71extern SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current,	int width, int height, int bpp, Uint32 flags);
72extern void WIMP_DeleteWindow(_THIS);
73extern int WIMP_ToggleFromFullScreen(_THIS);
74
75/* Hardware surface functions - common to WIMP and FULLSCREEN */
76static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface);
77static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface);
78static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface);
79static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface);
80
81/* RISC OS driver bootstrap functions */
82
83static int RISCOS_Available(void)
84{
85	return(1);
86}
87
88static void RISCOS_DeleteDevice(SDL_VideoDevice *device)
89{
90	SDL_free(device->hidden);
91	SDL_free(device);
92}
93
94static SDL_VideoDevice *RISCOS_CreateDevice(int devindex)
95{
96	SDL_VideoDevice *device;
97
98	/* Initialize all variables that we clean on shutdown */
99	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
100	if ( device ) {
101		SDL_memset(device, 0, (sizeof *device));
102		device->hidden = (struct SDL_PrivateVideoData *)
103				SDL_malloc((sizeof *device->hidden));
104	}
105	if ( (device == NULL) || (device->hidden == NULL) ) {
106		SDL_OutOfMemory();
107		if ( device ) {
108			SDL_free(device);
109		}
110		return(0);
111	}
112	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
113
114	/* Set the function pointers */
115	device->VideoInit = RISCOS_VideoInit;
116	device->VideoQuit = RISCOS_VideoQuit;
117
118	device->ListModes = RISCOS_ListModes;
119	device->SetVideoMode = RISCOS_SetVideoMode;
120	device->CreateYUVOverlay = NULL;
121	device->AllocHWSurface = RISCOS_AllocHWSurface;
122	device->CheckHWBlit = NULL;
123	device->FillHWRect = NULL;
124	device->SetHWColorKey = NULL;
125	device->SetHWAlpha = NULL;
126	device->LockHWSurface = RISCOS_LockHWSurface;
127	device->UnlockHWSurface = RISCOS_UnlockHWSurface;
128	device->FreeHWSurface = RISCOS_FreeHWSurface;
129
130	device->FreeWMCursor = RISCOS_FreeWMCursor;
131	device->CreateWMCursor = RISCOS_CreateWMCursor;
132	device->CheckMouseMode = RISCOS_CheckMouseMode;
133    device->GrabInput = RISCOS_GrabInput;
134
135	device->InitOSKeymap = RISCOS_InitOSKeymap;
136
137	device->GetWMInfo = RISCOS_GetWmInfo;
138
139	device->free = RISCOS_DeleteDevice;
140
141/* Can't get Toggle screen to work if program starts up in Full screen mode so
142   disable it here and re-enable it when a wimp screen is chosen */
143    device->ToggleFullScreen = NULL; /*RISCOS_ToggleFullScreen;*/
144
145	/* Set other entries for fullscreen mode */
146	FULLSCREEN_SetDeviceMode(device);
147
148	/* Mouse pointer needs to use the WIMP ShowCursor version so
149	   that it doesn't modify the pointer until the SDL Window is
150	   entered or the application goes full screen */
151	device->ShowWMCursor = WIMP_ShowWMCursor;
152
153	return device;
154}
155
156VideoBootStrap RISCOS_bootstrap = {
157	RISCOSVID_DRIVER_NAME, "RISC OS video driver",
158	RISCOS_Available, RISCOS_CreateDevice
159};
160
161
162int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat)
163{
164	_kernel_swi_regs regs;
165	int vars[4], vals[3];
166
167	if (RISCOS_InitTask() == 0)
168	{
169		SDL_SetError("Unable to start task");
170		return 0;
171	}
172
173	vars[0] = 9;  /* Log base 2 bpp */
174	vars[1] = 11; /* XWndLimit - num x pixels -1 */
175	vars[2] = 12; /* YWndLimit - num y pixels -1 */
176	vars[3] = -1; /* Terminate list */
177	regs.r[0] = (int)vars;
178	regs.r[1] = (int)vals;
179
180	_kernel_swi(OS_ReadVduVariables, &regs, &regs);
181	vformat->BitsPerPixel = (1 << vals[0]);
182
183	/* Determine the current screen size */
184	this->info.current_w = vals[1] + 1;
185	this->info.current_h = vals[2] + 1;
186
187	/* Minimum bpp for SDL is 8 */
188	if (vformat->BitsPerPixel < 8) vformat->BitsPerPixel = 8;
189
190
191	switch (vformat->BitsPerPixel)
192	{
193		case 15:
194		case 16:
195			vformat->Bmask = 0x00007c00;
196			vformat->Gmask = 0x000003e0;
197			vformat->Rmask = 0x0000001f;
198			vformat->BitsPerPixel = 16; /* SDL wants actual number of bits used */
199			vformat->BytesPerPixel = 2;
200			break;
201
202		case 24:
203		case 32:
204			vformat->Bmask = 0x00ff0000;
205			vformat->Gmask = 0x0000ff00;
206			vformat->Rmask = 0x000000ff;
207			vformat->BytesPerPixel = 4;
208			break;
209
210		default:
211			vformat->Bmask = 0;
212			vformat->Gmask = 0;
213			vformat->Rmask = 0;
214			vformat->BytesPerPixel = 1;
215			break;
216	}
217
218	/* Fill in some window manager capabilities */
219	this->info.wm_available = 1;
220
221	/* We're done! */
222	return(0);
223}
224
225/* Note:  If we are terminated, this could be called in the middle of
226   another SDL video routine -- notably UpdateRects.
227*/
228void RISCOS_VideoQuit(_THIS)
229{
230	RISCOS_ExitTask();
231
232	if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank);
233	this->hidden->alloc_bank = 0;
234}
235
236
237SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
238{
239	if (flags & SDL_FULLSCREEN)
240	{
241		/* Build mode list when first required. */
242		if (SDL_nummodes[0] == 0) FULLSCREEN_BuildModeList(this);
243
244		return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
245	} else
246		return (SDL_Rect **)-1;
247}
248
249
250/* Set up video mode */
251SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current,
252				int width, int height, int bpp, Uint32 flags)
253{
254	if (flags & SDL_FULLSCREEN)
255	{
256	    RISCOS_StoreWimpMode();
257		/* Dump wimp window on switch to full screen */
258  	    if (this->hidden->window_handle) WIMP_DeleteWindow(this);
259
260		return FULLSCREEN_SetVideoMode(this, current, width, height, bpp, flags);
261	} else
262	{
263	    RISCOS_RestoreWimpMode();
264		return WIMP_SetVideoMode(this, current, width, height, bpp, flags);
265	}
266}
267
268
269/* We don't actually allow hardware surfaces other than the main one */
270static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface)
271{
272	return(-1);
273}
274static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface)
275{
276	return;
277}
278
279/* We need to wait for vertical retrace on page flipped displays */
280static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface)
281{
282	return(0);
283}
284
285static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface)
286{
287	return;
288}
289
290
291int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info)
292{
293	SDL_VERSION(&(info->version));
294	info->wimpVersion = RISCOS_GetWimpVersion();
295	info->taskHandle = RISCOS_GetTaskHandle();
296	info->window = this->hidden->window_handle;
297
298	return 1;
299}
300/* Toggle full screen mode.
301   Returns 1 if successful otherwise 0
302*/
303
304int RISCOS_ToggleFullScreen(_THIS, int fullscreen)
305{
306    if (fullscreen)
307    {
308       return FULLSCREEN_ToggleFromWimp(this);
309    } else
310    {
311       return WIMP_ToggleFromFullScreen(this);
312    }
313
314   return 0;
315}
316
317