src/video/haiku/SDL_bmodes.cc
author Alex Szpakowski <slime73@gmail.com>
Sun, 26 May 2019 18:53:36 -0300
changeset 12757 96bca5da4965
parent 12503 806492103856
permissions -rw-r--r--
iOS: return SDL_GetWindowSize from SDL_GL_GetDrawableSize if there's no GLES view in the window (matches the behaviour of SDL_GL_GetDrawableSize on other platforms). Addresses bug #4629.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_HAIKU
    24 
    25 #include <AppKit.h>
    26 #include <InterfaceKit.h>
    27 #include "SDL_bmodes.h"
    28 #include "SDL_BWin.h"
    29 
    30 #if SDL_VIDEO_OPENGL
    31 #include "SDL_bopengl.h"
    32 #endif
    33 
    34 #include "../../main/haiku/SDL_BApp.h"
    35 
    36 #ifdef __cplusplus
    37 extern "C" {
    38 #endif
    39 
    40 
    41 #define WRAP_BMODE 1 /* FIXME: Some debate as to whether this is necessary */
    42 
    43 #if WRAP_BMODE
    44 /* This wrapper is here so that the driverdata can be freed without freeing
    45    the display_mode structure */
    46 struct SDL_DisplayModeData {
    47     display_mode *bmode;
    48 };
    49 #endif
    50 
    51 static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
    52     return ((SDL_BWin*)(window->driverdata));
    53 }
    54 
    55 static SDL_INLINE SDL_BApp *_GetBeApp() {
    56     return ((SDL_BApp*)be_app);
    57 }
    58 
    59 static SDL_INLINE display_mode * _ExtractBMode(SDL_DisplayMode *mode) {
    60 #if WRAP_BMODE
    61     return ((SDL_DisplayModeData*)mode->driverdata)->bmode;
    62 #else
    63     return (display_mode*)(mode->driverdata);
    64 #endif
    65 }
    66 
    67 /* Copied from haiku/trunk/src/preferences/screen/ScreenMode.cpp */
    68 static float get_refresh_rate(display_mode &mode) {
    69     return float(mode.timing.pixel_clock * 1000)
    70         / float(mode.timing.h_total * mode.timing.v_total);
    71 }
    72 
    73 
    74 #if 0
    75 /* TODO:
    76  * This is a useful debugging tool.  Uncomment and insert into code as needed.
    77  */
    78 void _SpoutModeData(display_mode *bmode) {
    79     printf("BMode:\n");
    80     printf("\tw,h = (%i,%i)\n", bmode->virtual_width, bmode->virtual_height);
    81     printf("\th,v = (%i,%i)\n", bmode->h_display_start, 
    82             bmode->v_display_start);
    83     if(bmode->flags) {
    84         printf("\tFlags:\n");
    85         if(bmode->flags & B_SCROLL) {
    86             printf("\t\tB_SCROLL\n");
    87         }
    88         if(bmode->flags & B_8_BIT_DAC) {
    89             printf("\t\tB_8_BIT_DAC\n");
    90         }
    91         if(bmode->flags & B_HARDWARE_CURSOR) {
    92             printf("\t\tB_HARDWARE_CURSOR\n");
    93         }
    94         if(bmode->flags & B_PARALLEL_ACCESS) {
    95             printf("\t\tB_PARALLEL_ACCESS\n");
    96         }
    97         if(bmode->flags & B_DPMS) {
    98             printf("\t\tB_DPMS\n");
    99         }
   100         if(bmode->flags & B_IO_FB_NA) {
   101             printf("\t\tB_IO_FB_NA\n");
   102         }
   103     }
   104     printf("\tTiming:\n");
   105     printf("\t\tpx clock: %i\n", bmode->timing.pixel_clock);
   106     printf("\t\th - display: %i sync start: %i sync end: %i total: %i\n",
   107         bmode->timing.h_display, bmode->timing.h_sync_start,
   108         bmode->timing.h_sync_end, bmode->timing.h_total);
   109     printf("\t\tv - display: %i sync start: %i sync end: %i total: %i\n",
   110         bmode->timing.v_display, bmode->timing.v_sync_start,
   111         bmode->timing.v_sync_end, bmode->timing.v_total);
   112     if(bmode->timing.flags) {
   113         printf("\t\tFlags:\n");
   114         if(bmode->timing.flags & B_BLANK_PEDESTAL) {
   115             printf("\t\t\tB_BLANK_PEDESTAL\n");
   116         }
   117         if(bmode->timing.flags & B_TIMING_INTERLACED) {
   118             printf("\t\t\tB_TIMING_INTERLACED\n");
   119         }
   120         if(bmode->timing.flags & B_POSITIVE_HSYNC) {
   121             printf("\t\t\tB_POSITIVE_HSYNC\n");
   122         }
   123         if(bmode->timing.flags & B_POSITIVE_VSYNC) {
   124             printf("\t\t\tB_POSITIVE_VSYNC\n");
   125         }
   126         if(bmode->timing.flags & B_SYNC_ON_GREEN) {
   127             printf("\t\t\tB_SYNC_ON_GREEN\n");
   128         }
   129     }
   130 }
   131 #endif
   132 
   133 
   134 
   135 int32 HAIKU_ColorSpaceToBitsPerPixel(uint32 colorspace)
   136 {
   137     int bitsperpixel;
   138 
   139     bitsperpixel = 0;
   140     switch (colorspace) {
   141         case B_CMAP8:
   142         bitsperpixel = 8;
   143         break;
   144         case B_RGB15:
   145         case B_RGBA15:
   146         case B_RGB15_BIG:
   147         case B_RGBA15_BIG:
   148         bitsperpixel = 15;
   149         break;
   150         case B_RGB16:
   151         case B_RGB16_BIG:
   152         bitsperpixel = 16;
   153         break;
   154         case B_RGB32:
   155         case B_RGBA32:
   156         case B_RGB32_BIG:
   157         case B_RGBA32_BIG:
   158         bitsperpixel = 32;
   159         break;
   160         default:
   161         break;
   162     }
   163     return(bitsperpixel);
   164 }
   165 
   166 int32 HAIKU_BPPToSDLPxFormat(int32 bpp) {
   167     /* Translation taken from SDL_windowsmodes.c */
   168     switch (bpp) {
   169     case 32:
   170         return SDL_PIXELFORMAT_RGB888;
   171         break;
   172     case 24:    /* May not be supported by Haiku */
   173         return SDL_PIXELFORMAT_RGB24;
   174         break;
   175     case 16:
   176         return SDL_PIXELFORMAT_RGB565;
   177         break;
   178     case 15:
   179         return SDL_PIXELFORMAT_RGB555;
   180         break;
   181     case 8:
   182         return SDL_PIXELFORMAT_INDEX8;
   183         break;
   184     case 4:        /* May not be supported by Haiku */
   185         return SDL_PIXELFORMAT_INDEX4LSB;
   186         break;
   187     }
   188 
   189     /* May never get here, but safer and needed to shut up compiler */
   190     SDL_SetError("Invalid bpp value");
   191     return 0;       
   192 }
   193 
   194 static void _BDisplayModeToSdlDisplayMode(display_mode *bmode,
   195         SDL_DisplayMode *mode) {
   196     mode->w = bmode->virtual_width;
   197     mode->h = bmode->virtual_height;
   198     mode->refresh_rate = (int)get_refresh_rate(*bmode);
   199 
   200 #if WRAP_BMODE
   201     SDL_DisplayModeData *data = (SDL_DisplayModeData*)SDL_calloc(1,
   202         sizeof(SDL_DisplayModeData));
   203     data->bmode = bmode;
   204     
   205     mode->driverdata = data;
   206 
   207 #else
   208 
   209     mode->driverdata = bmode;
   210 #endif
   211 
   212     /* Set the format */
   213     int32 bpp = HAIKU_ColorSpaceToBitsPerPixel(bmode->space);
   214     mode->format = HAIKU_BPPToSDLPxFormat(bpp);
   215 }
   216 
   217 /* Later, there may be more than one monitor available */
   218 static void _AddDisplay(BScreen *screen) {
   219     SDL_VideoDisplay display;
   220     SDL_DisplayMode *mode = (SDL_DisplayMode*)SDL_calloc(1,
   221         sizeof(SDL_DisplayMode));
   222     display_mode *bmode = (display_mode*)SDL_calloc(1, sizeof(display_mode));
   223     screen->GetMode(bmode);
   224 
   225     _BDisplayModeToSdlDisplayMode(bmode, mode);
   226     
   227     SDL_zero(display);
   228     display.desktop_mode = *mode;
   229     display.current_mode = *mode;
   230     
   231     SDL_AddVideoDisplay(&display);
   232 }
   233 
   234 /*
   235  * Functions called by SDL
   236  */
   237 
   238 int HAIKU_InitModes(_THIS) {
   239     BScreen screen;
   240 
   241     /* TODO: When Haiku supports multiple display screens, call
   242        _AddDisplayScreen() for each of them. */
   243     _AddDisplay(&screen);
   244     return 0;
   245 }
   246 
   247 int HAIKU_QuitModes(_THIS) {
   248     /* FIXME: Nothing really needs to be done here at the moment? */
   249     return 0;
   250 }
   251 
   252 
   253 int HAIKU_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect) {
   254     BScreen bscreen;
   255     BRect rc = bscreen.Frame();
   256     rect->x = (int)rc.left;
   257     rect->y = (int)rc.top;
   258     rect->w = (int)rc.Width() + 1;
   259     rect->h = (int)rc.Height() + 1;
   260     return 0;
   261 }
   262 
   263 void HAIKU_GetDisplayModes(_THIS, SDL_VideoDisplay *display) {
   264     /* Get the current screen */
   265     BScreen bscreen;
   266 
   267     /* Iterate through all of the modes */
   268     SDL_DisplayMode mode;
   269     display_mode this_bmode;
   270     display_mode *bmodes;
   271     uint32 count, i;
   272     
   273     /* Get graphics-hardware supported modes */
   274     bscreen.GetModeList(&bmodes, &count);
   275     bscreen.GetMode(&this_bmode);
   276     
   277     for(i = 0; i < count; ++i) {
   278         // FIXME: Apparently there are errors with colorspace changes
   279         if (bmodes[i].space == this_bmode.space) {
   280             _BDisplayModeToSdlDisplayMode(&bmodes[i], &mode);
   281             SDL_AddDisplayMode(display, &mode);
   282         }
   283     }
   284     free(bmodes);
   285 }
   286 
   287 
   288 int HAIKU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode){
   289     /* Get the current screen */
   290     BScreen bscreen;
   291     if(!bscreen.IsValid()) {
   292         printf(__FILE__": %d - ERROR: BAD SCREEN\n", __LINE__);
   293     }
   294 
   295     /* Set the mode using the driver data */
   296     display_mode *bmode = _ExtractBMode(mode);
   297 
   298 
   299     /* FIXME: Is the first option always going to be the right one? */
   300     uint32 c = 0, i;
   301     display_mode *bmode_list;
   302     bscreen.GetModeList(&bmode_list, &c);
   303     for(i = 0; i < c; ++i) {
   304         if(    bmode_list[i].space == bmode->space &&
   305             bmode_list[i].virtual_width == bmode->virtual_width &&
   306             bmode_list[i].virtual_height == bmode->virtual_height ) {
   307                 bmode = &bmode_list[i];
   308                 break;
   309         }
   310     }
   311 
   312     if(bscreen.SetMode(bmode) != B_OK) {
   313         return SDL_SetError("Bad video mode");
   314     }
   315     
   316     free(bmode_list);
   317     
   318 #if SDL_VIDEO_OPENGL
   319     /* FIXME: Is there some way to reboot the OpenGL context?  This doesn't
   320        help */
   321 //    HAIKU_GL_RebootContexts(_this);
   322 #endif
   323 
   324     return 0;
   325 }
   326 
   327 #ifdef __cplusplus
   328 }
   329 #endif
   330 
   331 #endif /* SDL_VIDEO_DRIVER_HAIKU */
   332 
   333 /* vi: set ts=4 sw=4 expandtab: */