mirror of https://github.com/libsdl-org/SDL.git
(N3DS) Add support for 3D rendering
This commit is contained in:
parent
7f14eb33c6
commit
656b5cd042
|
|
@ -39,7 +39,7 @@ static void CopyFramebuffertoN3DS_24(u8 *dest, const Dimensions dest_dim, const
|
||||||
static void CopyFramebuffertoN3DS_32(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim);
|
static void CopyFramebuffertoN3DS_32(u32 *dest, const Dimensions dest_dim, const u32 *source, const Dimensions source_dim);
|
||||||
static int GetDestOffset(int x, int y, int dest_width);
|
static int GetDestOffset(int x, int y, int dest_width);
|
||||||
static int GetSourceOffset(int x, int y, int source_width);
|
static int GetSourceOffset(int x, int y, int source_width);
|
||||||
static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen);
|
static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen, bool swap);
|
||||||
|
|
||||||
|
|
||||||
bool SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch)
|
bool SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, void **pixels, int *pitch)
|
||||||
|
|
@ -67,6 +67,7 @@ bool SDL_N3DS_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
|
||||||
|
|
||||||
bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
||||||
{
|
{
|
||||||
|
SDL_VideoData *internal = (SDL_VideoData *)_this->internal;
|
||||||
SDL_WindowData *drv_data = window->internal;
|
SDL_WindowData *drv_data = window->internal;
|
||||||
SDL_Surface *surface;
|
SDL_Surface *surface;
|
||||||
u16 width, height;
|
u16 width, height;
|
||||||
|
|
@ -79,7 +80,7 @@ bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the N3DS internal framebuffer and its size
|
// Get the N3DS internal framebuffer and its size
|
||||||
framebuffer = gfxGetFramebuffer(drv_data->screen, GFX_LEFT, &width, &height);
|
framebuffer = gfxGetFramebuffer(drv_data->screen, drv_data->side, &width, &height);
|
||||||
bufsize = width * height * 4;
|
bufsize = width * height * 4;
|
||||||
|
|
||||||
if (SDL_BYTESPERPIXEL(surface->format) == 2)
|
if (SDL_BYTESPERPIXEL(surface->format) == 2)
|
||||||
|
|
@ -91,7 +92,32 @@ bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
|
||||||
else
|
else
|
||||||
CopyFramebuffertoN3DS_32(framebuffer, (Dimensions){ width, height },
|
CopyFramebuffertoN3DS_32(framebuffer, (Dimensions){ width, height },
|
||||||
surface->pixels, (Dimensions){ surface->w, surface->h });
|
surface->pixels, (Dimensions){ surface->w, surface->h });
|
||||||
FlushN3DSBuffer(framebuffer, bufsize, drv_data->screen);
|
|
||||||
|
if(gfxIs3D() == false || drv_data->screen == GFX_BOTTOM)
|
||||||
|
FlushN3DSBuffer(framebuffer, bufsize, drv_data->screen, true);
|
||||||
|
|
||||||
|
else if(drv_data->screen == GFX_TOP) {
|
||||||
|
// We have to check if both screens are ready because if we can only
|
||||||
|
// swap both at the same time.
|
||||||
|
|
||||||
|
if(drv_data->side == GFX_LEFT)
|
||||||
|
internal->top_left_ready = true;
|
||||||
|
|
||||||
|
else if(drv_data->side == GFX_RIGHT)
|
||||||
|
internal->top_right_ready = true;
|
||||||
|
|
||||||
|
if(internal->top_left_ready && internal->top_right_ready) {
|
||||||
|
internal->top_left_ready = false;
|
||||||
|
internal->top_right_ready = false;
|
||||||
|
|
||||||
|
// This is safe because both screens share the same size
|
||||||
|
framebuffer = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height);
|
||||||
|
FlushN3DSBuffer(framebuffer, bufsize, GFX_TOP, false);
|
||||||
|
|
||||||
|
framebuffer = gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, &width, &height);
|
||||||
|
FlushN3DSBuffer(framebuffer, bufsize, GFX_TOP, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -147,10 +173,11 @@ static int GetSourceOffset(int x, int y, int source_width)
|
||||||
return x + y * source_width;
|
return x + y * source_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen)
|
static void FlushN3DSBuffer(const void *buffer, u32 bufsize, gfxScreen_t screen, bool swap)
|
||||||
{
|
{
|
||||||
GSPGPU_FlushDataCache(buffer, bufsize);
|
GSPGPU_FlushDataCache(buffer, bufsize);
|
||||||
gfxScreenSwapBuffers(screen, false);
|
if(swap)
|
||||||
|
gfxScreenSwapBuffers(screen, gfxIs3D());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#define N3DSVID_DRIVER_NAME "n3ds"
|
#define N3DSVID_DRIVER_NAME "n3ds"
|
||||||
|
|
||||||
static bool AddN3DSDisplay(gfxScreen_t screen);
|
static bool AddN3DSDisplay(gfxScreen_t screen, gfx3dSide_t side);
|
||||||
|
|
||||||
static bool N3DS_VideoInit(SDL_VideoDevice *_this);
|
static bool N3DS_VideoInit(SDL_VideoDevice *_this);
|
||||||
static void N3DS_VideoQuit(SDL_VideoDevice *_this);
|
static void N3DS_VideoQuit(SDL_VideoDevice *_this);
|
||||||
|
|
@ -44,6 +44,7 @@ static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||||
struct SDL_DisplayData
|
struct SDL_DisplayData
|
||||||
{
|
{
|
||||||
gfxScreen_t screen;
|
gfxScreen_t screen;
|
||||||
|
gfx3dSide_t side;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDL_DisplayModeData
|
struct SDL_DisplayModeData
|
||||||
|
|
@ -127,8 +128,9 @@ static bool N3DS_VideoInit(SDL_VideoDevice *_this)
|
||||||
gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
|
gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
|
||||||
hidInit();
|
hidInit();
|
||||||
|
|
||||||
internal->top_display = AddN3DSDisplay(GFX_TOP);
|
internal->top_left_display = AddN3DSDisplay(GFX_TOP, GFX_LEFT);
|
||||||
internal->touch_display = AddN3DSDisplay(GFX_BOTTOM);
|
internal->top_right_display = AddN3DSDisplay(GFX_TOP, GFX_RIGHT);
|
||||||
|
internal->touch_display = AddN3DSDisplay(GFX_BOTTOM, GFX_LEFT); // Bottom screen is always left
|
||||||
|
|
||||||
N3DS_InitTouch();
|
N3DS_InitTouch();
|
||||||
N3DS_SwkbInit();
|
N3DS_SwkbInit();
|
||||||
|
|
@ -136,7 +138,7 @@ static bool N3DS_VideoInit(SDL_VideoDevice *_this)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool AddN3DSDisplay(gfxScreen_t screen)
|
static bool AddN3DSDisplay(gfxScreen_t screen, gfx3dSide_t side)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
SDL_DisplayModeData *modedata;
|
SDL_DisplayModeData *modedata;
|
||||||
|
|
@ -150,6 +152,7 @@ static bool AddN3DSDisplay(gfxScreen_t screen)
|
||||||
SDL_zero(display);
|
SDL_zero(display);
|
||||||
|
|
||||||
display_driver_data->screen = screen;
|
display_driver_data->screen = screen;
|
||||||
|
display_driver_data->side = side;
|
||||||
|
|
||||||
modedata = SDL_malloc(sizeof(SDL_DisplayModeData));
|
modedata = SDL_malloc(sizeof(SDL_DisplayModeData));
|
||||||
if (!modedata) {
|
if (!modedata) {
|
||||||
|
|
@ -163,7 +166,7 @@ static bool AddN3DSDisplay(gfxScreen_t screen)
|
||||||
mode.internal = modedata;
|
mode.internal = modedata;
|
||||||
modedata->fmt = GSP_RGBA8_OES;
|
modedata->fmt = GSP_RGBA8_OES;
|
||||||
|
|
||||||
display.name = (screen == GFX_TOP) ? "N3DS top screen" : "N3DS bottom screen";
|
display.name = (screen == GFX_BOTTOM) ? "N3DS bottom screen" : (side == GFX_LEFT) ? "N3DS top screen" : "N3DS right screen";
|
||||||
display.desktop_mode = mode;
|
display.desktop_mode = mode;
|
||||||
display.internal = display_driver_data;
|
display.internal = display_driver_data;
|
||||||
|
|
||||||
|
|
@ -228,7 +231,12 @@ static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *disp
|
||||||
}
|
}
|
||||||
|
|
||||||
rect->x = 0;
|
rect->x = 0;
|
||||||
rect->y = (driver_data->screen == GFX_TOP) ? 0 : GSP_SCREEN_WIDTH;
|
rect->y = 0;
|
||||||
|
if(driver_data->screen == GFX_BOTTOM)
|
||||||
|
rect->y = GSP_SCREEN_WIDTH;
|
||||||
|
if(driver_data->screen == GFX_TOP && driver_data->side == GFX_RIGHT)
|
||||||
|
rect->y = GSP_SCREEN_WIDTH * 2;
|
||||||
|
|
||||||
rect->w = display->current_mode->w;
|
rect->w = display->current_mode->w;
|
||||||
rect->h = display->current_mode->h;
|
rect->h = display->current_mode->h;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -243,6 +251,7 @@ static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Pr
|
||||||
}
|
}
|
||||||
display_data = SDL_GetDisplayDriverDataForWindow(window);
|
display_data = SDL_GetDisplayDriverDataForWindow(window);
|
||||||
window_data->screen = display_data->screen;
|
window_data->screen = display_data->screen;
|
||||||
|
window_data->side = display_data->side;
|
||||||
window->internal = window_data;
|
window->internal = window_data;
|
||||||
SDL_SetKeyboardFocus(window);
|
SDL_SetKeyboardFocus(window);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,19 @@
|
||||||
|
|
||||||
struct SDL_VideoData
|
struct SDL_VideoData
|
||||||
{
|
{
|
||||||
int top_display;
|
int top_left_display;
|
||||||
|
int top_right_display;
|
||||||
int touch_display;
|
int touch_display;
|
||||||
|
|
||||||
|
// The following two variables keep track of if it is ready to swap the buffers
|
||||||
|
bool top_left_ready;
|
||||||
|
bool top_right_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDL_WindowData
|
struct SDL_WindowData
|
||||||
{
|
{
|
||||||
gfxScreen_t screen; /**< Keeps track of which N3DS screen is targeted */
|
gfxScreen_t screen; /**< Keeps track of which N3DS screen is targeted */
|
||||||
|
gfx3dSide_t side;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SDL_n3dsvideo_h_
|
#endif // SDL_n3dsvideo_h_
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue