Mercurial > sdl-ios-xcode
comparison src/video/riscos/SDL_wimpvideo.c @ 630:550bccdf04bd
Added initial support for RISC OS (thanks Peter Naulls!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 29 May 2003 04:44:13 +0000 |
parents | |
children | 44d574ed4780 |
comparison
equal
deleted
inserted
replaced
629:3fa401bb4bb5 | 630:550bccdf04bd |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com | |
21 */ | |
22 | |
23 /* | |
24 File added by Alan Buckley (alan_baa@hotmail.com) for RISCOS compatability | |
25 27 March 2003 | |
26 | |
27 Implements RISCOS wimp display. | |
28 */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 | |
34 #include "SDL.h" | |
35 #include "SDL_error.h" | |
36 #include "SDL_video.h" | |
37 #include "SDL_mouse.h" | |
38 #include "SDL_sysvideo.h" | |
39 #include "SDL_pixels_c.h" | |
40 #include "SDL_events_c.h" | |
41 | |
42 #include "SDL_riscostask.h" | |
43 #include "SDL_riscosvideo.h" | |
44 #include "SDL_riscosevents_c.h" | |
45 #include "SDL_riscosmouse_c.h" | |
46 | |
47 #include "kernel.h" | |
48 #include "swis.h" | |
49 | |
50 /* Initialization/Query functions */ | |
51 SDL_Rect **WIMP_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
52 SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
53 int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
54 void WIMP_SetWMCaption(_THIS, const char *title, const char *icon); | |
55 | |
56 | |
57 extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); | |
58 extern void WIMP_PumpEvents(_THIS); | |
59 extern void WIMP_PlotSprite(_THIS, int x, int y); | |
60 extern void WIMP_SetupPlotInfo(_THIS); | |
61 extern void WIMP_SetFocus(int win); | |
62 | |
63 /* etc. */ | |
64 static void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | |
65 | |
66 /* RISC OS Wimp handling helpers */ | |
67 void WIMP_ReadModeInfo(_THIS); | |
68 unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface); | |
69 void WIMP_SetDeviceMode(_THIS); | |
70 void WIMP_DeleteWindow(_THIS); | |
71 | |
72 /* FULLSCREEN function required for wimp/fullscreen toggling */ | |
73 extern int FULLSCREEN_SetMode(int width, int height, int bpp); | |
74 | |
75 /* Currently need to set this up here as it only works if you | |
76 start up in a Wimp mode */ | |
77 extern int RISCOS_ToggleFullScreen(_THIS, int fullscreen); | |
78 | |
79 extern int riscos_backbuffer; | |
80 extern int mouseInWindow; | |
81 extern int riscos_closeaction; | |
82 | |
83 | |
84 SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, | |
85 int width, int height, int bpp, Uint32 flags) | |
86 { | |
87 Uint32 Rmask = 0; | |
88 Uint32 Gmask = 0; | |
89 Uint32 Bmask = 0; | |
90 char *buffer = NULL; | |
91 int bytesPerPixel = 1; | |
92 | |
93 /* Don't support double buffering in Wimp mode */ | |
94 flags &= ~SDL_DOUBLEBUF; | |
95 flags &= ~SDL_HWSURFACE; | |
96 | |
97 switch(bpp) | |
98 { | |
99 case 8: | |
100 /* Emulated palette using ColourTrans */ | |
101 flags |= SDL_HWPALETTE; | |
102 break; | |
103 | |
104 case 15: | |
105 case 16: | |
106 Bmask = 0x00007c00; | |
107 Gmask = 0x000003e0; | |
108 Rmask = 0x0000001f; | |
109 bytesPerPixel = 2; | |
110 break; | |
111 | |
112 case 32: | |
113 Bmask = 0x00ff0000; | |
114 Gmask = 0x0000ff00; | |
115 Rmask = 0x000000ff; | |
116 bytesPerPixel = 4; | |
117 break; | |
118 | |
119 default: | |
120 SDL_SetError("Pixel depth not supported"); | |
121 return NULL; | |
122 break; | |
123 } | |
124 | |
125 /* printf("Setting mode %dx%d\n", width, height);*/ | |
126 | |
127 /* Allocate the new pixel format for the screen */ | |
128 if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { | |
129 SDL_SetError("Couldn't allocate new pixel format for requested mode"); | |
130 return(NULL); | |
131 } | |
132 | |
133 /* Set up the new mode framebuffer */ | |
134 current->w = width; | |
135 this->hidden->height = current->h = height; | |
136 | |
137 if (bpp == 15) bpp = 16; | |
138 buffer = WIMP_CreateBuffer(width, height, bpp); | |
139 if (buffer == NULL) | |
140 { | |
141 SDL_SetError("Couldn't create sprite for video memory"); | |
142 return (NULL); | |
143 } | |
144 | |
145 this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ | |
146 if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ | |
147 | |
148 this->hidden->bank[1] = buffer; /* Start of buffer */ | |
149 | |
150 /* Remember sprite buffer so it can be freed later */ | |
151 if (this->hidden->alloc_bank) free(this->hidden->alloc_bank); | |
152 this->hidden->alloc_bank = buffer; | |
153 | |
154 current->pitch = width * bytesPerPixel; | |
155 if ((current->pitch & 3)) | |
156 { | |
157 /* Sprites are 32bit word aligned */ | |
158 current->pitch += (4 - (current->pitch & 3)); | |
159 } | |
160 | |
161 current->flags = flags | SDL_PREALLOC; | |
162 | |
163 WIMP_ReadModeInfo(this); | |
164 | |
165 memset(this->hidden->bank[0], 0, height * current->pitch); | |
166 | |
167 this->hidden->current_bank = 0; | |
168 current->pixels = this->hidden->bank[0]; | |
169 | |
170 | |
171 if (WIMP_SetupWindow(this, current) == 0) | |
172 { | |
173 SDL_SetError("Unable to create window to display surface"); | |
174 return NULL; | |
175 } | |
176 | |
177 /* Reset device functions for the wimp */ | |
178 WIMP_SetDeviceMode(this); | |
179 | |
180 /* Needs to set up plot info after window has been created */ | |
181 /* Not sure why, but plots don't work if I do it earlier */ | |
182 WIMP_SetupPlotInfo(this); | |
183 | |
184 /* We're done */ | |
185 return(current); | |
186 } | |
187 | |
188 | |
189 void WIMP_ReadModeInfo(_THIS) | |
190 { | |
191 _kernel_swi_regs regs; | |
192 int vars[6]; | |
193 int vals[5]; | |
194 | |
195 vars[0] = 4; /* XEig */ | |
196 vars[1] = 5; /* YEig */ | |
197 vars[2] = 9; /* Log base 2 bpp */ | |
198 vars[3] = 11; /* Screen Width - 1 */ | |
199 vars[4] = 12; /* Screen Depth - 1 */ | |
200 vars[5] = -1; /* Terminate list */ | |
201 | |
202 regs.r[0] = (int)vars; | |
203 regs.r[1] = (int)vals; | |
204 _kernel_swi(OS_ReadVduVariables, ®s, ®s); | |
205 this->hidden->xeig = vals[0]; | |
206 this->hidden->yeig = vals[1]; | |
207 this->hidden->screen_bpp = 1 << vals[2]; | |
208 this->hidden->screen_width = vals[3] + 1; | |
209 this->hidden->screen_height = vals[4] + 1; | |
210 } | |
211 | |
212 /* Set device function to call the correct versions for running | |
213 in a wimp window */ | |
214 | |
215 void WIMP_SetDeviceMode(_THIS) | |
216 { | |
217 if (this->UpdateRects == WIMP_UpdateRects) return; /* Already set up */ | |
218 | |
219 this->SetColors = WIMP_SetColors; | |
220 this->UpdateRects = WIMP_UpdateRects; | |
221 | |
222 this->FlipHWSurface = NULL; | |
223 | |
224 this->SetCaption = WIMP_SetWMCaption; | |
225 this->SetIcon = NULL; | |
226 this->IconifyWindow = NULL; | |
227 | |
228 this->ShowWMCursor = WIMP_ShowWMCursor; | |
229 this->WarpWMCursor = WIMP_WarpWMCursor; | |
230 | |
231 this->ToggleFullScreen = RISCOS_ToggleFullScreen; | |
232 | |
233 this->PumpEvents = WIMP_PumpEvents; | |
234 } | |
235 | |
236 /* Setup the Window to display the surface */ | |
237 unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface) | |
238 { | |
239 _kernel_swi_regs regs; | |
240 int window_data[23]; | |
241 int *window_block = window_data+1; | |
242 int x = (this->hidden->screen_width - surface->w) / 2; | |
243 int y = (this->hidden->screen_height - surface->h) / 2; | |
244 int xeig = this->hidden->xeig; | |
245 int yeig = this->hidden->yeig; | |
246 | |
247 mouseInWindow = 0; | |
248 | |
249 /* Always delete the window and recreate on a change */ | |
250 if (this->hidden->window_handle) WIMP_DeleteWindow(this); | |
251 | |
252 /* Setup window co-ordinates */ | |
253 window_block[0] = x << xeig; | |
254 window_block[1] = y << yeig; | |
255 window_block[2] = window_block[0] + (surface->w << xeig); | |
256 window_block[3] = window_block[1] + (surface->h << yeig); | |
257 | |
258 | |
259 window_block[4] = 0; /* Scroll offsets */ | |
260 window_block[5] = 0; | |
261 window_block[6] = -1; /* Open on top of window stack */ | |
262 | |
263 window_block[7] = 0x85040042; /* Window flags */ | |
264 if (riscos_closeaction != 0) window_block[7] |= 0x2000000; | |
265 | |
266 /* TODO: Take into account surface->flags */ | |
267 | |
268 window_block[8] = 0xff070207; /* Window colours */ | |
269 window_block[9] = 0x000c0103; | |
270 window_block[10] = 0; /* Work area minimum */ | |
271 window_block[11] = -surface->h << yeig; | |
272 window_block[12] = surface->w << xeig; /* Work area maximum */ | |
273 window_block[13] = 0; | |
274 window_block[14] = 0x2700013d; /* Title icon flags */ | |
275 window_block[15] = 0x00003000; /* Work area flags - Mouse click down reported */ | |
276 window_block[16] = 1; /* Sprite area control block pointer */ | |
277 window_block[17] = 0x00100010; /* Minimum window size (width & height) (16x16)*/ | |
278 window_block[18] = (int)this->hidden->title; /* Title data */ | |
279 window_block[19] = -1; | |
280 window_block[20] = 256; | |
281 window_block[21] = 0; /* Number of icons */ | |
282 | |
283 regs.r[1] = (unsigned int)(window_block); | |
284 | |
285 /* Create the window */ | |
286 if (_kernel_swi(Wimp_CreateWindow, ®s, ®s) == NULL) | |
287 { | |
288 this->hidden->window_handle = window_data[0] = regs.r[0]; | |
289 | |
290 /* Show the window on the screen */ | |
291 regs.r[1] = (unsigned int)window_data; | |
292 if (_kernel_swi(Wimp_OpenWindow, ®s, ®s) == NULL) | |
293 { | |
294 WIMP_SetFocus(this->hidden->window_handle); | |
295 } else | |
296 { | |
297 WIMP_DeleteWindow(this); | |
298 } | |
299 } | |
300 | |
301 return this->hidden->window_handle; | |
302 } | |
303 | |
304 /* Destroy the Window */ | |
305 | |
306 void WIMP_DeleteWindow(_THIS) | |
307 { | |
308 _kernel_swi_regs regs; | |
309 regs.r[1] = (unsigned int)&(this->hidden->window_handle); | |
310 _kernel_swi(Wimp_DeleteWindow, ®s, ®s); | |
311 this->hidden->window_handle = 0; | |
312 } | |
313 | |
314 | |
315 void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | |
316 { | |
317 _kernel_swi_regs regs; | |
318 int update_block[12]; | |
319 int xeig = this->hidden->xeig; | |
320 int yeig = this->hidden->yeig; | |
321 int j; | |
322 update_block[0] = this->hidden->window_handle; | |
323 | |
324 for (j = 0; j < numrects; j++) | |
325 { | |
326 update_block[1] = rects[j].x << xeig; /* Min X */ | |
327 update_block[4] = -(rects[j].y << yeig); | |
328 update_block[3] = update_block[1] + (rects[j].w << xeig); | |
329 update_block[2] = update_block[4] - (rects[j].h << yeig); | |
330 | |
331 regs.r[1] = (int)update_block; | |
332 /* Update window can fail if called before first poll */ | |
333 if (_kernel_swi(Wimp_UpdateWindow, ®s, ®s) == 0) | |
334 { | |
335 while (regs.r[0]) | |
336 { | |
337 WIMP_PlotSprite(this, update_block[1], update_block[2]); | |
338 _kernel_swi(Wimp_GetRectangle, ®s, ®s); | |
339 } | |
340 } | |
341 } | |
342 } | |
343 | |
344 | |
345 int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
346 { | |
347 unsigned int *pal = (unsigned int *)(this->hidden->bank[1]+60); | |
348 int j; | |
349 SDL_Rect update; | |
350 | |
351 pal += firstcolor*2; | |
352 for (j = 0; j < ncolors; j++) | |
353 { | |
354 *pal = (((unsigned int)colors->r) << 8) | |
355 + (((unsigned int)colors->g) << 16) | |
356 + (((unsigned int)colors->b) << 24); | |
357 pal[1] = *pal; | |
358 pal += 2; | |
359 colors++; | |
360 } | |
361 | |
362 WIMP_SetupPlotInfo(this); | |
363 | |
364 /* Need to refresh the window */ | |
365 update.x = 0; | |
366 update.y = 0; | |
367 update.w = SDL_VideoSurface->w; | |
368 update.h = SDL_VideoSurface->h; | |
369 WIMP_UpdateRects(this, 1, &update); | |
370 | |
371 return 1; | |
372 } | |
373 | |
374 void WIMP_SetWMCaption(_THIS, const char *title, const char *icon) | |
375 { | |
376 _kernel_swi_regs regs; | |
377 | |
378 strncpy(this->hidden->title, title, 255); | |
379 this->hidden->title[255] = 0; | |
380 | |
381 if (RISCOS_GetWimpVersion() < 380) | |
382 { | |
383 int block[6]; | |
384 | |
385 regs.r[1] = (int)block; | |
386 _kernel_swi(Wimp_GetCaretPosition, ®s, ®s); | |
387 if (block[0] == (int)this->hidden->window_handle) | |
388 { | |
389 regs.r[0] = -1; | |
390 _kernel_swi(Wimp_SetCaretPosition, ®s,®s); | |
391 } else | |
392 { | |
393 regs.r[0] = this->hidden->window_handle; | |
394 regs.r[1] = -1; | |
395 regs.r[2] = -1; | |
396 regs.r[3] = -1; | |
397 _kernel_swi(Wimp_SetCaretPosition, ®s,®s); | |
398 } | |
399 regs.r[0] = block[0]; | |
400 regs.r[1] = block[1]; | |
401 regs.r[2] = block[2]; | |
402 regs.r[3] = block[3]; | |
403 regs.r[4] = block[4]; | |
404 regs.r[5] = block[5]; | |
405 _kernel_swi(Wimp_SetCaretPosition, ®s,®s); | |
406 } else | |
407 { | |
408 regs.r[0] = this->hidden->window_handle; | |
409 regs.r[1] = 0x4b534154; /* "TASK" */ | |
410 regs.r[2] = 3; /* Redraw title */ | |
411 _kernel_swi(Wimp_ForceRedraw, ®s, ®s); | |
412 } | |
413 } | |
414 | |
415 void WIMP_RefreshDesktop(_THIS) | |
416 { | |
417 int width = this->hidden->screen_width << this->hidden->xeig; | |
418 int height = this->hidden->screen_height << this->hidden->yeig; | |
419 _kernel_swi_regs regs; | |
420 regs.r[0] = -1; /* Whole screen */ | |
421 regs.r[1] = 0; | |
422 regs.r[2] = 0; | |
423 regs.r[3] = width; | |
424 regs.r[4] = height; | |
425 _kernel_swi(Wimp_ForceRedraw, ®s, ®s); | |
426 } | |
427 | |
428 /* Toggle to window from full screen */ | |
429 int WIMP_ToggleFromFullScreen(_THIS) | |
430 { | |
431 int width = this->screen->w; | |
432 int height = this->screen->h; | |
433 int bpp = this->screen->format->BitsPerPixel; | |
434 char *buffer = NULL; | |
435 char *old_bank[2]; | |
436 char *old_alloc_bank; | |
437 | |
438 /* Ensure flags are OK */ | |
439 this->screen->flags &= ~(SDL_DOUBLEBUF|SDL_HWSURFACE); | |
440 | |
441 if (this->hidden->bank[0] == this->hidden->alloc_bank || riscos_backbuffer == 0) | |
442 { | |
443 /* Need to create a sprite for the screen and copy the data to it */ | |
444 char *data; | |
445 buffer = WIMP_CreateBuffer(width, height, bpp); | |
446 data = buffer + 60; /* Start of sprite data */ | |
447 if (bpp == 8) data += 2048; /* 8bpp sprite have palette first */ | |
448 | |
449 if (buffer == NULL) return 0; | |
450 memcpy(data, this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel); | |
451 } | |
452 /* else We've switch to full screen before so we already have a sprite */ | |
453 | |
454 old_bank[0] = this->hidden->bank[0]; | |
455 old_bank[1] = this->hidden->bank[1]; | |
456 old_alloc_bank = this->hidden->alloc_bank; | |
457 | |
458 if (buffer != NULL) this->hidden->alloc_bank = buffer; | |
459 | |
460 this->hidden->bank[1] = this->hidden->alloc_bank; | |
461 this->hidden->bank[0] = this->hidden->bank[1] + 60; /* Start of sprite data */ | |
462 if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ | |
463 | |
464 this->hidden->current_bank = 0; | |
465 this->screen->pixels = this->hidden->bank[0]; | |
466 | |
467 RISCOS_RestoreWimpMode(); | |
468 WIMP_ReadModeInfo(this); | |
469 if (WIMP_SetupWindow(this, this->screen)) | |
470 { | |
471 WIMP_SetDeviceMode(this); | |
472 WIMP_SetupPlotInfo(this); | |
473 | |
474 riscos_backbuffer = 1; | |
475 | |
476 if (buffer && old_alloc_bank) free(old_alloc_bank); | |
477 | |
478 return 1; | |
479 } else | |
480 { | |
481 /* Drop back to full screen mode on failure */ | |
482 this->hidden->bank[0] = old_bank[0]; | |
483 this->hidden->bank[1] = old_bank[1]; | |
484 this->hidden->alloc_bank = old_alloc_bank; | |
485 if (buffer) free(buffer); | |
486 | |
487 RISCOS_StoreWimpMode(); | |
488 FULLSCREEN_SetMode(width, height, bpp); | |
489 } | |
490 | |
491 return 0; | |
492 } |