e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 | #include "SDL_config.h" |
23 | |
24 | /* BWindow based framebuffer implementation */ |
25 | |
26 | #include <unistd.h> |
27 | |
28 | #include "SDL_BWin.h" |
29 | #include "SDL_timer.h" |
30 | |
31 | extern "C" { |
32 | |
33 | #include "../SDL_sysvideo.h" |
34 | #include "../../events/SDL_events_c.h" |
35 | #include "SDL_sysevents_c.h" |
36 | #include "SDL_sysmouse_c.h" |
37 | #include "SDL_syswm_c.h" |
38 | #include "SDL_lowvideo.h" |
39 | #include "../SDL_yuvfuncs.h" |
40 | #include "SDL_sysyuv.h" |
41 | #include "../blank_cursor.h" |
42 | |
43 | #define BEOS_HIDDEN_SIZE 32 /* starting hidden window size */ |
44 | |
45 | /* Initialization/Query functions */ |
46 | static int BE_VideoInit(_THIS, SDL_PixelFormat *vformat); |
47 | static SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); |
48 | static SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
49 | static void BE_UpdateMouse(_THIS); |
50 | static int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); |
51 | static void BE_VideoQuit(_THIS); |
52 | |
53 | /* Hardware surface functions */ |
54 | static int BE_AllocHWSurface(_THIS, SDL_Surface *surface); |
55 | static int BE_LockHWSurface(_THIS, SDL_Surface *surface); |
56 | static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface); |
57 | static void BE_FreeHWSurface(_THIS, SDL_Surface *surface); |
58 | |
59 | static int BE_ToggleFullScreen(_THIS, int fullscreen); |
60 | static SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); |
61 | |
62 | /* OpenGL functions */ |
63 | #if SDL_VIDEO_OPENGL |
64 | static int BE_GL_LoadLibrary(_THIS, const char *path); |
65 | static void* BE_GL_GetProcAddress(_THIS, const char *proc); |
66 | static int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); |
67 | static int BE_GL_MakeCurrent(_THIS); |
68 | static void BE_GL_SwapBuffers(_THIS); |
69 | #endif |
70 | |
71 | /* FB driver bootstrap functions */ |
72 | |
73 | static int BE_Available(void) |
74 | { |
75 | return(1); |
76 | } |
77 | |
78 | static void BE_DeleteDevice(SDL_VideoDevice *device) |
79 | { |
80 | SDL_free(device->hidden); |
81 | SDL_free(device); |
82 | } |
83 | |
84 | static SDL_VideoDevice *BE_CreateDevice(int devindex) |
85 | { |
86 | SDL_VideoDevice *device; |
87 | |
88 | /* Initialize all variables that we clean on shutdown */ |
89 | device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); |
90 | if ( device ) { |
91 | SDL_memset(device, 0, (sizeof *device)); |
92 | device->hidden = (struct SDL_PrivateVideoData *) |
93 | SDL_malloc((sizeof *device->hidden)); |
94 | } |
95 | if ( (device == NULL) || (device->hidden == NULL) ) { |
96 | SDL_OutOfMemory(); |
97 | if ( device ) { |
98 | SDL_free(device); |
99 | } |
100 | return(0); |
101 | } |
102 | SDL_memset(device->hidden, 0, (sizeof *device->hidden)); |
103 | |
104 | /* Set the function pointers */ |
105 | /* Initialization/Query functions */ |
106 | device->VideoInit = BE_VideoInit; |
107 | device->ListModes = BE_ListModes; |
108 | device->SetVideoMode = BE_SetVideoMode; |
109 | device->ToggleFullScreen = BE_ToggleFullScreen; |
110 | device->UpdateMouse = BE_UpdateMouse; |
111 | device->CreateYUVOverlay = BE_CreateYUVOverlay; |
112 | device->SetColors = BE_SetColors; |
113 | device->UpdateRects = NULL; |
114 | device->VideoQuit = BE_VideoQuit; |
115 | /* Hardware acceleration functions */ |
116 | device->AllocHWSurface = BE_AllocHWSurface; |
117 | device->CheckHWBlit = NULL; |
118 | device->FillHWRect = NULL; |
119 | device->SetHWColorKey = NULL; |
120 | device->SetHWAlpha = NULL; |
121 | device->LockHWSurface = BE_LockHWSurface; |
122 | device->UnlockHWSurface = BE_UnlockHWSurface; |
123 | device->FlipHWSurface = NULL; |
124 | device->FreeHWSurface = BE_FreeHWSurface; |
125 | /* Gamma support */ |
126 | #if SDL_VIDEO_OPENGL |
127 | /* OpenGL support */ |
128 | device->GL_LoadLibrary = BE_GL_LoadLibrary; |
129 | device->GL_GetProcAddress = BE_GL_GetProcAddress; |
130 | device->GL_GetAttribute = BE_GL_GetAttribute; |
131 | device->GL_MakeCurrent = BE_GL_MakeCurrent; |
132 | device->GL_SwapBuffers = BE_GL_SwapBuffers; |
133 | #endif |
134 | /* Window manager functions */ |
135 | device->SetCaption = BE_SetWMCaption; |
136 | device->SetIcon = NULL; |
137 | device->IconifyWindow = BE_IconifyWindow; |
138 | device->GrabInput = BE_GrabInput; |
139 | device->GetWMInfo = BE_GetWMInfo; |
140 | /* Cursor manager functions */ |
141 | device->FreeWMCursor = BE_FreeWMCursor; |
142 | device->CreateWMCursor = BE_CreateWMCursor; |
143 | device->ShowWMCursor = BE_ShowWMCursor; |
144 | device->WarpWMCursor = BE_WarpWMCursor; |
145 | device->MoveWMCursor = NULL; |
146 | device->CheckMouseMode = BE_CheckMouseMode; |
147 | /* Event manager functions */ |
148 | device->InitOSKeymap = BE_InitOSKeymap; |
149 | device->PumpEvents = BE_PumpEvents; |
150 | |
151 | device->free = BE_DeleteDevice; |
152 | |
153 | /* Set the driver flags */ |
154 | device->handles_any_size = 1; |
155 | |
156 | return device; |
157 | } |
158 | |
159 | VideoBootStrap BWINDOW_bootstrap = { |
160 | "bwindow", "BDirectWindow graphics", |
161 | BE_Available, BE_CreateDevice |
162 | }; |
163 | |
164 | static inline int ColorSpaceToBitsPerPixel(uint32 colorspace) |
165 | { |
166 | int bitsperpixel; |
167 | |
168 | bitsperpixel = 0; |
169 | switch (colorspace) { |
170 | case B_CMAP8: |
171 | bitsperpixel = 8; |
172 | break; |
173 | case B_RGB15: |
174 | case B_RGBA15: |
175 | case B_RGB15_BIG: |
176 | case B_RGBA15_BIG: |
177 | bitsperpixel = 15; |
178 | break; |
179 | case B_RGB16: |
180 | case B_RGB16_BIG: |
181 | bitsperpixel = 16; |
182 | break; |
183 | case B_RGB32: |
184 | case B_RGBA32: |
185 | case B_RGB32_BIG: |
186 | case B_RGBA32_BIG: |
187 | bitsperpixel = 32; |
188 | break; |
189 | default: |
190 | break; |
191 | } |
192 | return(bitsperpixel); |
193 | } |
194 | |
195 | /* Function to sort the display_list in bscreen */ |
196 | static int CompareModes(const void *A, const void *B) |
197 | { |
198 | const display_mode *a = (display_mode *)A; |
199 | const display_mode *b = (display_mode *)B; |
200 | |
201 | if ( a->space == b->space ) { |
202 | return((b->virtual_width*b->virtual_height)- |
203 | (a->virtual_width*a->virtual_height)); |
204 | } else { |
205 | return(ColorSpaceToBitsPerPixel(b->space)- |
206 | ColorSpaceToBitsPerPixel(a->space)); |
207 | } |
208 | } |
209 | |
210 | /* Yes, this isn't the fastest it could be, but it works nicely */ |
211 | static int BE_AddMode(_THIS, int index, unsigned int w, unsigned int h) |
212 | { |
213 | SDL_Rect *mode; |
214 | int i; |
215 | int next_mode; |
216 | |
217 | /* Check to see if we already have this mode */ |
218 | if ( SDL_nummodes[index] > 0 ) { |
219 | for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { |
220 | mode = SDL_modelist[index][i]; |
221 | if ( (mode->w == w) && (mode->h == h) ) { |
222 | #ifdef BWINDOW_DEBUG |
223 | fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); |
224 | #endif |
225 | return(0); |
226 | } |
227 | } |
228 | } |
229 | |
230 | /* Set up the new video mode rectangle */ |
231 | mode = (SDL_Rect *)SDL_malloc(sizeof *mode); |
232 | if ( mode == NULL ) { |
233 | SDL_OutOfMemory(); |
234 | return(-1); |
235 | } |
236 | mode->x = 0; |
237 | mode->y = 0; |
238 | mode->w = w; |
239 | mode->h = h; |
240 | #ifdef BWINDOW_DEBUG |
241 | fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); |
242 | #endif |
243 | |
244 | /* Allocate the new list of modes, and fill in the new mode */ |
245 | next_mode = SDL_nummodes[index]; |
246 | SDL_modelist[index] = (SDL_Rect **) |
247 | SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); |
248 | if ( SDL_modelist[index] == NULL ) { |
249 | SDL_OutOfMemory(); |
250 | SDL_nummodes[index] = 0; |
251 | SDL_free(mode); |
252 | return(-1); |
253 | } |
254 | SDL_modelist[index][next_mode] = mode; |
255 | SDL_modelist[index][next_mode+1] = NULL; |
256 | SDL_nummodes[index]++; |
257 | |
258 | return(0); |
259 | } |
260 | |
261 | int BE_VideoInit(_THIS, SDL_PixelFormat *vformat) |
262 | { |
263 | display_mode *modes; |
264 | uint32 i, nmodes; |
265 | int bpp; |
266 | BRect bounds; |
267 | |
268 | /* Initialize the Be Application for appserver interaction */ |
269 | if ( SDL_InitBeApp() < 0 ) { |
270 | return(-1); |
271 | } |
272 | |
273 | /* It is important that this be created after SDL_InitBeApp() */ |
274 | BScreen bscreen; |
275 | |
276 | /* Save the current display mode */ |
277 | bscreen.GetMode(&saved_mode); |
278 | _this->info.current_w = saved_mode.virtual_width; |
279 | _this->info.current_h = saved_mode.virtual_height; |
280 | |
281 | /* Determine the screen depth */ |
282 | vformat->BitsPerPixel = ColorSpaceToBitsPerPixel(bscreen.ColorSpace()); |
283 | if ( vformat->BitsPerPixel == 0 ) { |
284 | SDL_SetError("Unknown BScreen colorspace: 0x%x", |
285 | bscreen.ColorSpace()); |
286 | return(-1); |
287 | } |
288 | |
289 | /* Get the video modes we can switch to in fullscreen mode */ |
290 | bscreen.GetModeList(&modes, &nmodes); |
291 | SDL_qsort(modes, nmodes, sizeof *modes, CompareModes); |
292 | for ( i=0; i<nmodes; ++i ) { |
293 | bpp = ColorSpaceToBitsPerPixel(modes[i].space); |
294 | //if ( bpp != 0 ) { // There are bugs in changing colorspace |
295 | if ( modes[i].space == saved_mode.space ) { |
296 | BE_AddMode(_this, ((bpp+7)/8)-1, |
297 | modes[i].virtual_width, |
298 | modes[i].virtual_height); |
299 | } |
300 | } |
301 | |
302 | /* Create the window and view */ |
303 | bounds.top = 0; bounds.left = 0; |
304 | bounds.right = BEOS_HIDDEN_SIZE; |
305 | bounds.bottom = BEOS_HIDDEN_SIZE; |
306 | SDL_Win = new SDL_BWin(bounds); |
307 | |
308 | #if SDL_VIDEO_OPENGL |
309 | /* testgl application doesn't load library, just tries to load symbols */ |
310 | /* is it correct? if so we have to load library here */ |
311 | BE_GL_LoadLibrary(_this, NULL); |
312 | #endif |
313 | |
314 | /* Create the clear cursor */ |
315 | SDL_BlankCursor = BE_CreateWMCursor(_this, blank_cdata, blank_cmask, |
316 | BLANK_CWIDTH, BLANK_CHEIGHT, BLANK_CHOTX, BLANK_CHOTY); |
317 | |
318 | /* Fill in some window manager capabilities */ |
319 | _this->info.wm_available = 1; |
320 | |
321 | /* We're done! */ |
322 | return(0); |
323 | } |
324 | |
325 | /* We support any dimension at our bit-depth */ |
326 | SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
327 | { |
328 | SDL_Rect **modes; |
329 | |
330 | modes = ((SDL_Rect **)0); |
331 | if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { |
332 | modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; |
333 | } else { |
334 | if ( format->BitsPerPixel == |
335 | _this->screen->format->BitsPerPixel ) { |
336 | modes = ((SDL_Rect **)-1); |
337 | } |
338 | } |
339 | return(modes); |
340 | } |
341 | |
342 | /* Various screen update functions available */ |
343 | static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); |
344 | |
345 | |
346 | /* Find the closest display mode for fullscreen */ |
347 | static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp, |
348 | display_mode *mode) |
349 | { |
350 | BScreen bscreen; |
351 | uint32 i, nmodes; |
352 | SDL_Rect **modes; |
353 | display_mode *dmodes; |
354 | display_mode current; |
355 | float current_refresh; |
356 | bscreen.GetMode(¤t); |
357 | current_refresh = (1000 * current.timing.pixel_clock) / |
358 | (current.timing.h_total * current.timing.v_total); |
359 | |
360 | modes = SDL_modelist[((bpp+7)/8)-1]; |
361 | |
362 | // find end of list (lowest-resolution mode; modes are ordered |
363 | // highest-to-lowest). |
364 | i = 0; while(modes[i]) i++; |
365 | if (!i) return false; // what? no modes at all? |
366 | |
367 | // find first mode with resolution >= requested in both dimensions |
368 | for (--i; i >= 0; --i) |
369 | { |
370 | if (modes[i]->w >= width && modes[i]->h >= height) |
371 | break; |
372 | } |
373 | |
374 | // unable to find any mode with that high a resolution! |
375 | if (i < 0) |
376 | return false; |
377 | |
378 | width = modes[i]->w; |
379 | height = modes[i]->h; |
380 | |
381 | bscreen.GetModeList(&dmodes, &nmodes); |
382 | for ( i = 0; i < nmodes; ++i ) { |
383 | if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) && |
384 | (width == dmodes[i].virtual_width) && |
385 | (height == dmodes[i].virtual_height) ) { |
386 | break; |
387 | } |
388 | } |
389 | if ( i != nmodes ) { |
390 | *mode = dmodes[i]; |
391 | if ((mode->virtual_width <= current.virtual_width) && |
392 | (mode->virtual_height <= current.virtual_height)) { |
393 | float new_refresh = (1000 * mode->timing.pixel_clock) / |
394 | (mode->timing.h_total * mode->timing.v_total); |
395 | if (new_refresh < current_refresh) { |
396 | mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total) |
397 | * current_refresh / 1000); |
398 | } |
399 | } |
400 | return true; |
401 | } else { |
402 | return false; |
403 | } |
404 | } |
405 | |
406 | static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) |
407 | { |
408 | // printf("SetFullScreen(%d)\n", fullscreen); |
409 | BScreen bscreen; |
410 | |
411 | // SetFullSscreen() does not work as expected if called in a window |
412 | // that was never shown. This is probably a bug in the Haiku Game Kit that needs |
413 | // to be investigated. |
414 | if (SDL_Win->Lock()) { |
415 | // Show our window. |
416 | SDL_Win->Show(); |
417 | } |
418 | |
419 | if (SDL_Win->IsLocked()) { |
420 | // Unlock the window if it was locked. This is needed as only the |
421 | // first call to Show() unlocks the looper. All other calls to it |
422 | // will not. |
423 | SDL_Win->Unlock(); |
424 | } |
425 | |
426 | int width = screen->w; |
427 | int height = screen->h; |
428 | |
429 | if (fullscreen) { |
430 | // Set resolution to the closest available one that matches the |
431 | // current SDL resolution. |
432 | display_mode mode; |
433 | bscreen.GetMode(&mode); |
434 | |
435 | int bpp = screen->format->BitsPerPixel; |
436 | if (bpp != ColorSpaceToBitsPerPixel(mode.space) || |
437 | width != mode.virtual_width || height != mode.virtual_height) { |
438 | if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { |
439 | bscreen.SetMode(&mode); |
440 | } else { |
441 | // printf("Could not set new mode.\n"); |
442 | return(0); |
443 | } |
444 | } |
445 | } else { |
446 | // Reset to the previous known resolution as we are now in window |
447 | // mode. |
448 | bscreen.SetMode(&saved_mode); |
449 | } |
450 | |
451 | // Effectivelly set/reset full screen mode. If we are already in |
452 | // full screen mode, we reset back to windowed mode first so the |
453 | // window can resize when going fullscreen. |
454 | // if (fullscreen) |
455 | // printf("Going fullscreen\n"); |
456 | // else |
457 | // printf("Going windowed\n"); |
458 | SDL_Win->SetFullScreen(fullscreen); |
459 | |
460 | // Calculate offsets for centering the window (in window mode) and for |
461 | // dentering the bitmap (in full screen mode). |
462 | BRect bounds = bscreen.Frame(); |
463 | bounds.PrintToStream(); |
464 | int32 cx = (bounds.IntegerWidth() - width)/2; |
465 | int32 cy = (bounds.IntegerHeight() - height)/2; |
466 | |
467 | // printf ("cx = %d, cy = %d\n", cx, cy); |
468 | if (!SDL_Win->IsFullScreen()) { |
469 | // printf("Doing not fullscreen stuff.\n"); |
470 | // We are not in full screen mode, so we want to change the window |
471 | // size to match the resolution in SDL. |
472 | SDL_Win->ResizeTo(width, height); |
473 | |
474 | // And also center the window and reset the drawing offset. |
475 | SDL_Win->MoveTo(cx, cy); |
476 | SDL_Win->SetXYOffset(0, 0); |
477 | } else { |
478 | // printf("Doing fullscreen stuff."); |
479 | // Center the bitmap whenever we are in full screen mode. |
480 | SDL_Win->SetXYOffset(cx, cy); |
481 | } |
482 | |
483 | // Set relevant internal SDL screen flags. |
484 | if (SDL_Win->IsFullScreen()) { |
485 | screen->flags |= SDL_FULLSCREEN; |
486 | } else { |
487 | screen->flags &= ~SDL_FULLSCREEN; |
488 | } |
489 | |
490 | return(1); |
491 | } |
492 | |
493 | static int BE_ToggleFullScreen(_THIS, int fullscreen) |
494 | { |
495 | return BE_SetFullScreen(_this, _this->screen, fullscreen); |
496 | } |
497 | |
498 | /* FIXME: check return values and cleanup here */ |
499 | SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, |
500 | int width, int height, int bpp, Uint32 flags) |
501 | { |
502 | BScreen bscreen; |
503 | BBitmap *bbitmap; |
504 | BRect bounds; |
505 | Uint32 gl_flags = 0; |
506 | |
507 | /* Only RGB works on r5 currently */ |
508 | gl_flags = BGL_RGB; |
509 | if (_this->gl_config.double_buffer) |
510 | gl_flags |= BGL_DOUBLE; |
511 | else |
512 | gl_flags |= BGL_SINGLE; |
513 | if (_this->gl_config.alpha_size > 0 || bpp == 32) |
514 | gl_flags |= BGL_ALPHA; |
515 | if (_this->gl_config.depth_size > 0) |
516 | gl_flags |= BGL_DEPTH; |
517 | if (_this->gl_config.stencil_size > 0) |
518 | gl_flags |= BGL_STENCIL; |
519 | if (_this->gl_config.accum_red_size > 0 |
520 | || _this->gl_config.accum_green_size > 0 |
521 | || _this->gl_config.accum_blue_size > 0 |
522 | || _this->gl_config.accum_alpha_size > 0) |
523 | gl_flags |= BGL_ACCUM; |
524 | |
525 | /* Create the view for this window, using found flags */ |
526 | if ( SDL_Win->CreateView(flags, gl_flags) < 0 ) { |
527 | return(NULL); |
528 | } |
529 | |
530 | current->flags = 0; /* Clear flags */ |
531 | current->w = width; |
532 | current->h = height; |
533 | SDL_Win->SetType(B_TITLED_WINDOW); |
534 | if ( flags & SDL_NOFRAME ) { |
535 | current->flags |= SDL_NOFRAME; |
536 | SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK); |
537 | } else { |
538 | if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) ) { |
539 | current->flags |= SDL_RESIZABLE; |
540 | /* We don't want opaque resizing (TM). :-) */ |
541 | SDL_Win->SetFlags(B_OUTLINE_RESIZE); |
542 | } else { |
543 | SDL_Win->SetFlags(B_NOT_RESIZABLE|B_NOT_ZOOMABLE); |
544 | } |
545 | } |
546 | |
547 | if ( flags & SDL_OPENGL ) { |
548 | current->flags |= SDL_OPENGL; |
549 | current->pitch = 0; |
550 | current->pixels = NULL; |
551 | _this->UpdateRects = NULL; |
552 | } else { |
553 | /* Create the BBitmap framebuffer */ |
554 | bounds.top = 0; bounds.left = 0; |
555 | bounds.right = width-1; |
556 | bounds.bottom = height-1; |
557 | bbitmap = new BBitmap(bounds, bscreen.ColorSpace()); |
558 | if ( ! bbitmap->IsValid() ) { |
559 | SDL_SetError("Couldn't create screen bitmap"); |
560 | delete bbitmap; |
561 | return(NULL); |
562 | } |
563 | current->pitch = bbitmap->BytesPerRow(); |
564 | current->pixels = (void *)bbitmap->Bits(); |
565 | SDL_Win->SetBitmap(bbitmap); |
566 | _this->UpdateRects = BE_NormalUpdate; |
567 | } |
568 | |
569 | /* Set the correct fullscreen mode */ |
570 | BE_SetFullScreen(_this, current, flags & SDL_FULLSCREEN ? 1 : 0); |
571 | |
572 | /* We're done */ |
573 | return(current); |
574 | } |
575 | |
576 | /* Update the current mouse state and position */ |
577 | void BE_UpdateMouse(_THIS) |
578 | { |
579 | BPoint point; |
580 | uint32 buttons; |
581 | |
582 | if ( SDL_Win->Lock() ) { |
583 | /* Get new input state, if still active */ |
584 | if ( SDL_Win->IsActive() ) { |
585 | (SDL_Win->View())->GetMouse(&point, &buttons, true); |
586 | } else { |
587 | point.x = -1; |
588 | point.y = -1; |
589 | } |
590 | SDL_Win->Unlock(); |
591 | |
592 | if ( (point.x >= 0) && (point.x < SDL_VideoSurface->w) && |
593 | (point.y >= 0) && (point.y < SDL_VideoSurface->h) ) { |
594 | SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); |
595 | SDL_PrivateMouseMotion(0, 0, |
596 | (Sint16)point.x, (Sint16)point.y); |
597 | } else { |
598 | SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); |
599 | } |
600 | } |
601 | } |
602 | |
603 | /* We don't actually allow hardware surfaces other than the main one */ |
604 | static int BE_AllocHWSurface(_THIS, SDL_Surface *surface) |
605 | { |
606 | return(-1); |
607 | } |
608 | static void BE_FreeHWSurface(_THIS, SDL_Surface *surface) |
609 | { |
610 | return; |
611 | } |
612 | static int BE_LockHWSurface(_THIS, SDL_Surface *surface) |
613 | { |
614 | return(0); |
615 | } |
616 | static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface) |
617 | { |
618 | return; |
619 | } |
620 | |
621 | static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) |
622 | { |
623 | if ( SDL_Win->BeginDraw() ) { |
624 | int i; |
625 | |
626 | for ( i=0; i<numrects; ++i ) { |
627 | BRect rect; |
628 | |
629 | rect.top = rects[i].y; |
630 | rect.left = rects[i].x; |
631 | rect.bottom = rect.top+rects[i].h-1; |
632 | rect.right = rect.left+rects[i].w-1; |
633 | SDL_Win->DrawAsync(rect); |
634 | } |
635 | SDL_Win->EndDraw(); |
636 | } |
637 | } |
638 | |
639 | #if SDL_VIDEO_OPENGL |
640 | /* Passing a NULL path means load pointers from the application */ |
641 | int BE_GL_LoadLibrary(_THIS, const char *path) |
642 | { |
643 | if (path == NULL) { |
644 | if (_this->gl_config.dll_handle == NULL) { |
645 | image_info info; |
646 | int32 cookie = 0; |
647 | while (get_next_image_info(0,&cookie,&info) == B_OK) { |
648 | void *location = NULL; |
649 | #ifdef __HAIKU__ |
650 | if (get_image_symbol(info.id,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // This is how it actually works in Haiku |
651 | #else |
652 | if (get_image_symbol((image_id)cookie,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // I don't know if that *did* work in BeOS |
653 | #endif |
654 | _this->gl_config.dll_handle = (void*)info.id; |
655 | _this->gl_config.driver_loaded = 1; |
656 | SDL_strlcpy(_this->gl_config.driver_path, "libGL.so", SDL_arraysize(_this->gl_config.driver_path)); |
657 | } |
658 | } |
659 | } |
660 | } else { |
661 | /* |
662 | FIXME None of BeOS libGL.so implementations have exported functions |
663 | to load BGLView, which should be reloaded from new lib. |
664 | So for now just "load" linked libGL.so :( |
665 | */ |
666 | if (_this->gl_config.dll_handle == NULL) { |
667 | return BE_GL_LoadLibrary(_this, NULL); |
668 | } |
669 | |
670 | /* Unload old first */ |
671 | /*if (_this->gl_config.dll_handle != NULL) {*/ |
672 | /* Do not try to unload application itself (if LoadLibrary was called before with NULL ;) */ |
673 | /* image_info info; |
674 | if (get_image_info((image_id)_this->gl_config.dll_handle, &info) == B_OK) { |
675 | if (info.type != B_APP_IMAGE) { |
676 | unload_add_on((image_id)_this->gl_config.dll_handle); |
677 | } |
678 | } |
679 | |
680 | } |
681 | |
682 | if ((_this->gl_config.dll_handle = (void*)load_add_on(path)) != (void*)B_ERROR) { |
683 | _this->gl_config.driver_loaded = 1; |
684 | SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); |
685 | }*/ |
686 | } |
687 | |
688 | if (_this->gl_config.dll_handle != NULL) { |
689 | return 0; |
690 | } else { |
691 | _this->gl_config.dll_handle = NULL; |
692 | _this->gl_config.driver_loaded = 0; |
693 | *_this->gl_config.driver_path = '\0'; |
694 | return -1; |
695 | } |
696 | } |
697 | |
698 | void* BE_GL_GetProcAddress(_THIS, const char *proc) |
699 | { |
700 | if (_this->gl_config.dll_handle != NULL) { |
701 | void *location = NULL; |
702 | status_t err; |
703 | if ((err = get_image_symbol((image_id)_this->gl_config.dll_handle, proc, B_SYMBOL_TYPE_ANY, &location)) == B_OK) { |
704 | return location; |
705 | } else { |
706 | SDL_SetError("Couldn't find OpenGL symbol"); |
707 | return NULL; |
708 | } |
709 | } else { |
710 | SDL_SetError("OpenGL library not loaded"); |
711 | return NULL; |
712 | } |
713 | } |
714 | |
715 | int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) |
716 | { |
717 | /* |
718 | FIXME? Right now BE_GL_GetAttribute shouldn't be called between glBegin() and glEnd() - it doesn't use "cached" values |
719 | */ |
720 | switch (attrib) |
721 | { |
722 | case SDL_GL_RED_SIZE: |
723 | glGetIntegerv(GL_RED_BITS, (GLint*)value); |
724 | break; |
725 | case SDL_GL_GREEN_SIZE: |
726 | glGetIntegerv(GL_GREEN_BITS, (GLint*)value); |
727 | break; |
728 | case SDL_GL_BLUE_SIZE: |
729 | glGetIntegerv(GL_BLUE_BITS, (GLint*)value); |
730 | break; |
731 | case SDL_GL_ALPHA_SIZE: |
732 | glGetIntegerv(GL_ALPHA_BITS, (GLint*)value); |
733 | break; |
734 | case SDL_GL_DOUBLEBUFFER: |
735 | glGetBooleanv(GL_DOUBLEBUFFER, (GLboolean*)value); |
736 | break; |
737 | case SDL_GL_BUFFER_SIZE: |
738 | int v; |
739 | glGetIntegerv(GL_RED_BITS, (GLint*)&v); |
740 | *value = v; |
741 | glGetIntegerv(GL_GREEN_BITS, (GLint*)&v); |
742 | *value += v; |
743 | glGetIntegerv(GL_BLUE_BITS, (GLint*)&v); |
744 | *value += v; |
745 | glGetIntegerv(GL_ALPHA_BITS, (GLint*)&v); |
746 | *value += v; |
747 | break; |
748 | case SDL_GL_DEPTH_SIZE: |
749 | glGetIntegerv(GL_DEPTH_BITS, (GLint*)value); /* Mesa creates 16 only? r5 always 32 */ |
750 | break; |
751 | case SDL_GL_STENCIL_SIZE: |
752 | glGetIntegerv(GL_STENCIL_BITS, (GLint*)value); |
753 | break; |
754 | case SDL_GL_ACCUM_RED_SIZE: |
755 | glGetIntegerv(GL_ACCUM_RED_BITS, (GLint*)value); |
756 | break; |
757 | case SDL_GL_ACCUM_GREEN_SIZE: |
758 | glGetIntegerv(GL_ACCUM_GREEN_BITS, (GLint*)value); |
759 | break; |
760 | case SDL_GL_ACCUM_BLUE_SIZE: |
761 | glGetIntegerv(GL_ACCUM_BLUE_BITS, (GLint*)value); |
762 | break; |
763 | case SDL_GL_ACCUM_ALPHA_SIZE: |
764 | glGetIntegerv(GL_ACCUM_ALPHA_BITS, (GLint*)value); |
765 | break; |
766 | case SDL_GL_STEREO: |
767 | case SDL_GL_MULTISAMPLEBUFFERS: |
768 | case SDL_GL_MULTISAMPLESAMPLES: |
769 | default: |
770 | *value=0; |
771 | return(-1); |
772 | } |
773 | return 0; |
774 | } |
775 | |
776 | int BE_GL_MakeCurrent(_THIS) |
777 | { |
778 | /* FIXME: should we glview->unlock and then glview->lock()? */ |
779 | return 0; |
780 | } |
781 | |
782 | void BE_GL_SwapBuffers(_THIS) |
783 | { |
784 | SDL_Win->SwapBuffers(); |
785 | } |
786 | #endif |
787 | |
788 | /* Is the system palette settable? */ |
789 | int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
790 | { |
791 | int i; |
792 | SDL_Palette *palette; |
793 | const color_map *cmap = BScreen().ColorMap(); |
794 | |
795 | /* Get the screen colormap */ |
796 | palette = _this->screen->format->palette; |
797 | for ( i=0; i<256; ++i ) { |
798 | palette->colors[i].r = cmap->color_list[i].red; |
799 | palette->colors[i].g = cmap->color_list[i].green; |
800 | palette->colors[i].b = cmap->color_list[i].blue; |
801 | } |
802 | return(0); |
803 | } |
804 | |
805 | void BE_VideoQuit(_THIS) |
806 | { |
807 | int i, j; |
808 | |
809 | SDL_Win->Quit(); |
810 | SDL_Win = NULL; |
811 | |
812 | if ( SDL_BlankCursor != NULL ) { |
813 | BE_FreeWMCursor(_this, SDL_BlankCursor); |
814 | SDL_BlankCursor = NULL; |
815 | } |
816 | for ( i=0; i<NUM_MODELISTS; ++i ) { |
817 | if ( SDL_modelist[i] ) { |
818 | for ( j=0; SDL_modelist[i][j]; ++j ) { |
819 | SDL_free(SDL_modelist[i][j]); |
820 | } |
821 | SDL_free(SDL_modelist[i]); |
822 | SDL_modelist[i] = NULL; |
823 | } |
824 | } |
825 | /* Restore the original video mode */ |
826 | if ( _this->screen ) { |
827 | if ( (_this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { |
828 | BScreen bscreen; |
829 | bscreen.SetMode(&saved_mode); |
830 | } |
831 | _this->screen->pixels = NULL; |
832 | } |
833 | |
834 | #if SDL_VIDEO_OPENGL |
835 | if (_this->gl_config.dll_handle != NULL) |
836 | unload_add_on((image_id)_this->gl_config.dll_handle); |
837 | #endif |
838 | |
839 | SDL_QuitBeApp(); |
840 | } |
841 | |
842 | }; /* Extern C */ |