#include "SDL_internal.h"
#ifdef SDL_VIDEO_DRIVER_HAIKU
#include <AppKit.h>
#include <InterfaceKit.h>
#include "SDL_bmodes.h"
#include "SDL_BWin.h"
#ifdef SDL_VIDEO_OPENGL
#include "SDL_bopengl.h"
#endif
#include "../../core/haiku/SDL_BApp.h"
#ifdef __cplusplus
extern "C" {
#endif
#define WRAP_BMODE 1
#if WRAP_BMODE
struct SDL_DisplayModeData {
display_mode *bmode;
};
#endif
static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window)
{
return (SDL_BWin *)(window->internal);
}
static SDL_INLINE SDL_BLooper *_GetBeLooper()
{
return SDL_Looper;
}
static SDL_INLINE display_mode * _ExtractBMode(SDL_DisplayMode *mode)
{
#if WRAP_BMODE
return mode->internal->bmode;
#else
return (display_mode *)mode->internal;
#endif
}
static void get_refresh_rate(display_mode &mode, int *numerator, int *denominator)
{
*numerator = (mode.timing.pixel_clock * 1000);
*denominator = (mode.timing.h_total * mode.timing.v_total);
}
#if 0#endif
SDL_PixelFormat HAIKU_ColorSpaceToSDLPxFormat(uint32 colorspace)
{
switch (colorspace) {
case B_CMAP8:
return SDL_PIXELFORMAT_INDEX8;
break;
case B_RGB15:
case B_RGBA15:
case B_RGB15_BIG:
case B_RGBA15_BIG:
return SDL_PIXELFORMAT_XRGB1555;
break;
case B_RGB16:
case B_RGB16_BIG:
return SDL_PIXELFORMAT_RGB565;
break;
case B_RGB24:
case B_RGB24_BIG:
return SDL_PIXELFORMAT_BGR24;
break;
case B_RGB32:
case B_RGBA32:
case B_RGB32_BIG:
case B_RGBA32_BIG:
return SDL_PIXELFORMAT_XRGB8888;
break;
}
SDL_SetError("Invalid color space");
return SDL_PIXELFORMAT_UNKNOWN;
}
static void _BDisplayModeToSdlDisplayMode(display_mode *bmode, SDL_DisplayMode *mode)
{
SDL_zerop(mode);
mode->w = bmode->virtual_width;
mode->h = bmode->virtual_height;
get_refresh_rate(*bmode, &mode->refresh_rate_numerator, &mode->refresh_rate_denominator);
#if WRAP_BMODE
SDL_DisplayModeData *data = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData));
data->bmode = bmode;
mode->internal = data;
#else
mode->internal = bmode;
#endif
mode->format = HAIKU_ColorSpaceToSDLPxFormat(bmode->space);
}
static void _AddDisplay(BScreen *screen)
{
SDL_DisplayMode mode;
display_mode bmode;
screen->GetMode(&bmode);
_BDisplayModeToSdlDisplayMode(&bmode, &mode);
SDL_AddBasicVideoDisplay(&mode);
}
bool HAIKU_InitModes(SDL_VideoDevice *_this)
{
BScreen screen;
_AddDisplay(&screen);
return true;
}
void HAIKU_QuitModes(SDL_VideoDevice *_this)
{
return;
}
bool HAIKU_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
{
BScreen bscreen;
BRect rc = bscreen.Frame();
rect->x = (int)rc.left;
rect->y = (int)rc.top;
rect->w = (int)rc.Width() + 1;
rect->h = (int)rc.Height() + 1;
return true;
}
bool HAIKU_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display)
{
BScreen bscreen;
SDL_DisplayMode mode;
display_mode this_bmode;
display_mode *bmodes;
uint32 count, i;
bscreen.GetModeList(&bmodes, &count);
bscreen.GetMode(&this_bmode);
for (i = 0; i < count; ++i) {
if (bmodes[i].space == this_bmode.space) {
_BDisplayModeToSdlDisplayMode(&bmodes[i], &mode);
SDL_AddFullscreenDisplayMode(display, &mode);
}
}
free(bmodes); return true;
}
bool HAIKU_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
{
BScreen bscreen;
if (!bscreen.IsValid()) {
return SDL_SetError("Invalid screen");
}
display_mode *bmode = _ExtractBMode(mode);
uint32 c = 0, i;
display_mode *bmode_list;
bscreen.GetModeList(&bmode_list, &c);
for (i = 0; i < c; ++i) {
if ( bmode_list[i].space == bmode->space &&
bmode_list[i].virtual_width == bmode->virtual_width &&
bmode_list[i].virtual_height == bmode->virtual_height ) {
bmode = &bmode_list[i];
break;
}
}
if (bscreen.SetMode(bmode) != B_OK) {
return SDL_SetError("Bad video mode");
}
free(bmode_list);
#ifdef SDL_VIDEO_OPENGL
#endif
return true;
}
#ifdef __cplusplus
}
#endif
#endif