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