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 int GetDestOffset(int x, int y, int dest_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)
|
||||
|
|
@ -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)
|
||||
{
|
||||
SDL_VideoData *internal = (SDL_VideoData *)_this->internal;
|
||||
SDL_WindowData *drv_data = window->internal;
|
||||
SDL_Surface *surface;
|
||||
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
|
||||
framebuffer = gfxGetFramebuffer(drv_data->screen, GFX_LEFT, &width, &height);
|
||||
framebuffer = gfxGetFramebuffer(drv_data->screen, drv_data->side, &width, &height);
|
||||
bufsize = width * height * 4;
|
||||
|
||||
if (SDL_BYTESPERPIXEL(surface->format) == 2)
|
||||
|
|
@ -91,7 +92,32 @@ bool SDL_N3DS_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window
|
|||
else
|
||||
CopyFramebuffertoN3DS_32(framebuffer, (Dimensions){ width, height },
|
||||
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;
|
||||
}
|
||||
|
|
@ -147,10 +173,11 @@ static int GetSourceOffset(int x, int y, int 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);
|
||||
gfxScreenSwapBuffers(screen, false);
|
||||
if(swap)
|
||||
gfxScreenSwapBuffers(screen, gfxIs3D());
|
||||
}
|
||||
|
||||
void SDL_N3DS_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#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 void N3DS_VideoQuit(SDL_VideoDevice *_this);
|
||||
|
|
@ -44,6 +44,7 @@ static void N3DS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
|||
struct SDL_DisplayData
|
||||
{
|
||||
gfxScreen_t screen;
|
||||
gfx3dSide_t side;
|
||||
};
|
||||
|
||||
struct SDL_DisplayModeData
|
||||
|
|
@ -127,8 +128,9 @@ static bool N3DS_VideoInit(SDL_VideoDevice *_this)
|
|||
gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
|
||||
hidInit();
|
||||
|
||||
internal->top_display = AddN3DSDisplay(GFX_TOP);
|
||||
internal->touch_display = AddN3DSDisplay(GFX_BOTTOM);
|
||||
internal->top_left_display = AddN3DSDisplay(GFX_TOP, GFX_LEFT);
|
||||
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_SwkbInit();
|
||||
|
|
@ -136,7 +138,7 @@ static bool N3DS_VideoInit(SDL_VideoDevice *_this)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool AddN3DSDisplay(gfxScreen_t screen)
|
||||
static bool AddN3DSDisplay(gfxScreen_t screen, gfx3dSide_t side)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
SDL_DisplayModeData *modedata;
|
||||
|
|
@ -150,6 +152,7 @@ static bool AddN3DSDisplay(gfxScreen_t screen)
|
|||
SDL_zero(display);
|
||||
|
||||
display_driver_data->screen = screen;
|
||||
display_driver_data->side = side;
|
||||
|
||||
modedata = SDL_malloc(sizeof(SDL_DisplayModeData));
|
||||
if (!modedata) {
|
||||
|
|
@ -163,7 +166,7 @@ static bool AddN3DSDisplay(gfxScreen_t screen)
|
|||
mode.internal = modedata;
|
||||
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.internal = display_driver_data;
|
||||
|
||||
|
|
@ -228,7 +231,12 @@ static bool N3DS_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *disp
|
|||
}
|
||||
|
||||
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->h = display->current_mode->h;
|
||||
return true;
|
||||
|
|
@ -243,6 +251,7 @@ static bool N3DS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Pr
|
|||
}
|
||||
display_data = SDL_GetDisplayDriverDataForWindow(window);
|
||||
window_data->screen = display_data->screen;
|
||||
window_data->side = display_data->side;
|
||||
window->internal = window_data;
|
||||
SDL_SetKeyboardFocus(window);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -29,13 +29,19 @@
|
|||
|
||||
struct SDL_VideoData
|
||||
{
|
||||
int top_display;
|
||||
int top_left_display;
|
||||
int top_right_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
|
||||
{
|
||||
gfxScreen_t screen; /**< Keeps track of which N3DS screen is targeted */
|
||||
gfx3dSide_t side;
|
||||
};
|
||||
|
||||
#endif // SDL_n3dsvideo_h_
|
||||
|
|
|
|||
Loading…
Reference in New Issue