mirror of
https://github.com/libretro/RetroArch
synced 2025-04-09 21:45:45 +00:00
OpenDingux: Ensure SDL surface width is a multiple of 16 when using 'sdl_dingux' gfx driver (crash/glitch fix)
This commit is contained in:
parent
c01e8d52a5
commit
6094e2c32a
@ -55,6 +55,7 @@ typedef struct sdl_dingux_video
|
|||||||
SDL_Surface *screen;
|
SDL_Surface *screen;
|
||||||
unsigned frame_width;
|
unsigned frame_width;
|
||||||
unsigned frame_height;
|
unsigned frame_height;
|
||||||
|
unsigned frame_padding;
|
||||||
enum dingux_ipu_filter_type filter_type;
|
enum dingux_ipu_filter_type filter_type;
|
||||||
uint32_t font_colour32;
|
uint32_t font_colour32;
|
||||||
uint16_t font_colour16;
|
uint16_t font_colour16;
|
||||||
@ -126,11 +127,15 @@ static void sdl_dingux_blit_text16(
|
|||||||
unsigned x, unsigned y,
|
unsigned x, unsigned y,
|
||||||
const char *str)
|
const char *str)
|
||||||
{
|
{
|
||||||
|
/* Note: Cannot draw text in padding region
|
||||||
|
* (padding region is never cleared, so
|
||||||
|
* any text pixels would remain as garbage) */
|
||||||
uint16_t *screen_buf = (uint16_t*)vid->screen->pixels;
|
uint16_t *screen_buf = (uint16_t*)vid->screen->pixels;
|
||||||
/* 16 bit - divide pitch by 2 */
|
/* 16 bit - divide pitch by 2 */
|
||||||
uint16_t screen_stride = (uint16_t)(vid->screen->pitch >> 1);
|
uint16_t screen_stride = (uint16_t)(vid->screen->pitch >> 1);
|
||||||
uint16_t screen_width = vid->screen->w;
|
uint16_t screen_width = vid->screen->w;
|
||||||
uint16_t screen_height = vid->screen->h;
|
uint16_t screen_height = vid->screen->h;
|
||||||
|
unsigned x_pos = x + vid->frame_padding;
|
||||||
uint16_t shadow_color_buf[2] = {0};
|
uint16_t shadow_color_buf[2] = {0};
|
||||||
uint16_t color_buf[2];
|
uint16_t color_buf[2];
|
||||||
|
|
||||||
@ -144,7 +149,8 @@ static void sdl_dingux_blit_text16(
|
|||||||
while (!string_is_empty(str))
|
while (!string_is_empty(str))
|
||||||
{
|
{
|
||||||
/* Check for out of bounds x coordinates */
|
/* Check for out of bounds x coordinates */
|
||||||
if (x + FONT_WIDTH_STRIDE + 1 >= screen_width)
|
if (x_pos + FONT_WIDTH_STRIDE + 1 >=
|
||||||
|
screen_width - vid->frame_padding)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Deal with spaces first, for efficiency */
|
/* Deal with spaces first, for efficiency */
|
||||||
@ -169,7 +175,7 @@ static void sdl_dingux_blit_text16(
|
|||||||
|
|
||||||
for (j = 0; j < FONT_HEIGHT; j++)
|
for (j = 0; j < FONT_HEIGHT; j++)
|
||||||
{
|
{
|
||||||
uint32_t buff_offset = ((y + j) * screen_stride) + x;
|
uint32_t buff_offset = ((y + j) * screen_stride) + x_pos;
|
||||||
|
|
||||||
for (i = 0; i < FONT_WIDTH; i++)
|
for (i = 0; i < FONT_WIDTH; i++)
|
||||||
{
|
{
|
||||||
@ -188,7 +194,7 @@ static void sdl_dingux_blit_text16(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x += FONT_WIDTH_STRIDE;
|
x_pos += FONT_WIDTH_STRIDE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,11 +203,15 @@ static void sdl_dingux_blit_text32(
|
|||||||
unsigned x, unsigned y,
|
unsigned x, unsigned y,
|
||||||
const char *str)
|
const char *str)
|
||||||
{
|
{
|
||||||
|
/* Note: Cannot draw text in padding region
|
||||||
|
* (padding region is never cleared, so
|
||||||
|
* any text pixels would remain as garbage) */
|
||||||
uint32_t *screen_buf = (uint32_t*)vid->screen->pixels;
|
uint32_t *screen_buf = (uint32_t*)vid->screen->pixels;
|
||||||
/* 32 bit - divide pitch by 4 */
|
/* 32 bit - divide pitch by 4 */
|
||||||
uint32_t screen_stride = (uint32_t)(vid->screen->pitch >> 2);
|
uint32_t screen_stride = (uint32_t)(vid->screen->pitch >> 2);
|
||||||
uint32_t screen_width = vid->screen->w;
|
uint32_t screen_width = vid->screen->w;
|
||||||
uint32_t screen_height = vid->screen->h;
|
uint32_t screen_height = vid->screen->h;
|
||||||
|
unsigned x_pos = x + vid->frame_padding;
|
||||||
uint32_t shadow_color_buf[2] = {0};
|
uint32_t shadow_color_buf[2] = {0};
|
||||||
uint32_t color_buf[2];
|
uint32_t color_buf[2];
|
||||||
|
|
||||||
@ -215,7 +225,8 @@ static void sdl_dingux_blit_text32(
|
|||||||
while (!string_is_empty(str))
|
while (!string_is_empty(str))
|
||||||
{
|
{
|
||||||
/* Check for out of bounds x coordinates */
|
/* Check for out of bounds x coordinates */
|
||||||
if (x + FONT_WIDTH_STRIDE + 1 >= screen_width)
|
if (x_pos + FONT_WIDTH_STRIDE + 1 >=
|
||||||
|
screen_width - vid->frame_padding)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Deal with spaces first, for efficiency */
|
/* Deal with spaces first, for efficiency */
|
||||||
@ -240,7 +251,7 @@ static void sdl_dingux_blit_text32(
|
|||||||
|
|
||||||
for (j = 0; j < FONT_HEIGHT; j++)
|
for (j = 0; j < FONT_HEIGHT; j++)
|
||||||
{
|
{
|
||||||
uint32_t buff_offset = ((y + j) * screen_stride) + x;
|
uint32_t buff_offset = ((y + j) * screen_stride) + x_pos;
|
||||||
|
|
||||||
for (i = 0; i < FONT_WIDTH; i++)
|
for (i = 0; i < FONT_WIDTH; i++)
|
||||||
{
|
{
|
||||||
@ -259,7 +270,7 @@ static void sdl_dingux_blit_text32(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x += FONT_WIDTH_STRIDE;
|
x_pos += FONT_WIDTH_STRIDE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +481,10 @@ static void sdl_dingux_set_output(
|
|||||||
sdl_dingux_video_t* vid,
|
sdl_dingux_video_t* vid,
|
||||||
unsigned width, unsigned height, bool rgb32)
|
unsigned width, unsigned height, bool rgb32)
|
||||||
{
|
{
|
||||||
uint32_t surface_flags = (vid->vsync) ?
|
/* Surface width must be rounded up to
|
||||||
|
* the nearest multiple of 16 */
|
||||||
|
unsigned sanitized_width = (width + 0xF) & ~0xF;
|
||||||
|
uint32_t surface_flags = (vid->vsync) ?
|
||||||
(SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) :
|
(SDL_HWSURFACE | SDL_TRIPLEBUF | SDL_FULLSCREEN) :
|
||||||
(SDL_HWSURFACE | SDL_FULLSCREEN);
|
(SDL_HWSURFACE | SDL_FULLSCREEN);
|
||||||
|
|
||||||
@ -480,7 +494,7 @@ static void sdl_dingux_set_output(
|
|||||||
|
|
||||||
/* Attempt to change video mode */
|
/* Attempt to change video mode */
|
||||||
vid->screen = SDL_SetVideoMode(
|
vid->screen = SDL_SetVideoMode(
|
||||||
vid->frame_width, vid->frame_height,
|
sanitized_width, vid->frame_height,
|
||||||
rgb32 ? 32 : 16,
|
rgb32 ? 32 : 16,
|
||||||
surface_flags);
|
surface_flags);
|
||||||
|
|
||||||
@ -500,18 +514,43 @@ static void sdl_dingux_set_output(
|
|||||||
rgb32 ? 32 : 16,
|
rgb32 ? 32 : 16,
|
||||||
surface_flags);
|
surface_flags);
|
||||||
|
|
||||||
vid->mode_valid = false;
|
vid->frame_padding = 0;
|
||||||
|
vid->mode_valid = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Determine whether horizontal padding
|
||||||
|
* is required */
|
||||||
|
if (sanitized_width != width)
|
||||||
|
{
|
||||||
|
vid->frame_padding = (sanitized_width - width) >> 1;
|
||||||
|
|
||||||
|
/* To prevent garbage pixels in the padding
|
||||||
|
* region, must zero out pixel buffer */
|
||||||
|
if (SDL_MUSTLOCK(vid->screen))
|
||||||
|
SDL_LockSurface(vid->screen);
|
||||||
|
|
||||||
|
memset(vid->screen->pixels, 0,
|
||||||
|
vid->screen->w * vid->screen->w *
|
||||||
|
(rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)));
|
||||||
|
|
||||||
|
if (SDL_MUSTLOCK(vid->screen))
|
||||||
|
SDL_UnlockSurface(vid->screen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vid->frame_padding = 0;
|
||||||
|
|
||||||
vid->mode_valid = true;
|
vid->mode_valid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl_dingux_blit_frame16(uint16_t* dst, uint16_t* src,
|
static void sdl_dingux_blit_frame16(sdl_dingux_video_t *vid,
|
||||||
unsigned width, unsigned height,
|
uint16_t* src, unsigned width, unsigned height,
|
||||||
unsigned dst_pitch, unsigned src_pitch)
|
unsigned src_pitch)
|
||||||
{
|
{
|
||||||
uint16_t *in_ptr = src;
|
uint16_t *in_ptr = src;
|
||||||
uint16_t *out_ptr = dst;
|
uint16_t *out_ptr = (uint16_t*)vid->screen->pixels;
|
||||||
|
unsigned dst_pitch = vid->screen->pitch;
|
||||||
|
|
||||||
/* If source and destination buffers have the
|
/* If source and destination buffers have the
|
||||||
* same pitch, perform fast copy of raw pixel data */
|
* same pitch, perform fast copy of raw pixel data */
|
||||||
@ -526,6 +565,10 @@ static void sdl_dingux_blit_frame16(uint16_t* dst, uint16_t* src,
|
|||||||
uint16_t out_stride = (uint16_t)(dst_pitch >> 1);
|
uint16_t out_stride = (uint16_t)(dst_pitch >> 1);
|
||||||
size_t y;
|
size_t y;
|
||||||
|
|
||||||
|
/* If SDL surface has horizontal padding,
|
||||||
|
* shift output image to the right */
|
||||||
|
out_ptr += vid->frame_padding;
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
memcpy(out_ptr, in_ptr, width * sizeof(uint16_t));
|
memcpy(out_ptr, in_ptr, width * sizeof(uint16_t));
|
||||||
@ -535,12 +578,13 @@ static void sdl_dingux_blit_frame16(uint16_t* dst, uint16_t* src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl_dingux_blit_frame32(uint32_t* dst, uint32_t* src,
|
static void sdl_dingux_blit_frame32(sdl_dingux_video_t *vid,
|
||||||
unsigned width, unsigned height,
|
uint32_t* src, unsigned width, unsigned height,
|
||||||
unsigned dst_pitch, unsigned src_pitch)
|
unsigned src_pitch)
|
||||||
{
|
{
|
||||||
uint32_t *in_ptr = src;
|
uint32_t *in_ptr = src;
|
||||||
uint32_t *out_ptr = dst;
|
uint32_t *out_ptr = (uint32_t*)vid->screen->pixels;
|
||||||
|
unsigned dst_pitch = vid->screen->pitch;
|
||||||
|
|
||||||
/* If source and destination buffers have the
|
/* If source and destination buffers have the
|
||||||
* same pitch, perform fast copy of raw pixel data */
|
* same pitch, perform fast copy of raw pixel data */
|
||||||
@ -555,6 +599,10 @@ static void sdl_dingux_blit_frame32(uint32_t* dst, uint32_t* src,
|
|||||||
uint32_t out_stride = (uint32_t)(dst_pitch >> 2);
|
uint32_t out_stride = (uint32_t)(dst_pitch >> 2);
|
||||||
size_t y;
|
size_t y;
|
||||||
|
|
||||||
|
/* If SDL surface has horizontal padding,
|
||||||
|
* shift output image to the right */
|
||||||
|
out_ptr += vid->frame_padding;
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
memcpy(out_ptr, in_ptr, width * sizeof(uint32_t));
|
memcpy(out_ptr, in_ptr, width * sizeof(uint32_t));
|
||||||
@ -599,17 +647,11 @@ static bool sdl_dingux_gfx_frame(void *data, const void *frame,
|
|||||||
{
|
{
|
||||||
/* Blit frame to SDL surface */
|
/* Blit frame to SDL surface */
|
||||||
if (vid->rgb32)
|
if (vid->rgb32)
|
||||||
sdl_dingux_blit_frame32(
|
sdl_dingux_blit_frame32(vid, (uint32_t*)frame,
|
||||||
(uint32_t*)vid->screen->pixels,
|
width, height, pitch);
|
||||||
(uint32_t*)frame,
|
|
||||||
width, height,
|
|
||||||
vid->screen->pitch, pitch);
|
|
||||||
else
|
else
|
||||||
sdl_dingux_blit_frame16(
|
sdl_dingux_blit_frame16(vid, (uint16_t*)frame,
|
||||||
(uint16_t*)vid->screen->pixels,
|
width, height, pitch);
|
||||||
(uint16_t*)frame,
|
|
||||||
width, height,
|
|
||||||
vid->screen->pitch, pitch);
|
|
||||||
}
|
}
|
||||||
/* If current display mode is invalid,
|
/* If current display mode is invalid,
|
||||||
* just display an error message */
|
* just display an error message */
|
||||||
@ -634,17 +676,15 @@ static bool sdl_dingux_gfx_frame(void *data, const void *frame,
|
|||||||
SDL_LockSurface(vid->screen);
|
SDL_LockSurface(vid->screen);
|
||||||
|
|
||||||
/* Blit menu texture to SDL surface */
|
/* Blit menu texture to SDL surface */
|
||||||
sdl_dingux_blit_frame16(
|
sdl_dingux_blit_frame16(vid, vid->menu_texture,
|
||||||
(uint16_t*)vid->screen->pixels,
|
|
||||||
vid->menu_texture,
|
|
||||||
SDL_DINGUX_MENU_WIDTH, SDL_DINGUX_MENU_HEIGHT,
|
SDL_DINGUX_MENU_WIDTH, SDL_DINGUX_MENU_HEIGHT,
|
||||||
vid->screen->pitch, SDL_DINGUX_MENU_WIDTH * sizeof(uint16_t));
|
SDL_DINGUX_MENU_WIDTH * sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print OSD text, if required */
|
/* Print OSD text, if required */
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
/* If menu is active, colour depth is overriden
|
/* If menu is active, colour depth is overridden
|
||||||
* to 16 bit */
|
* to 16 bit */
|
||||||
if (vid->rgb32 && !vid->menu_active)
|
if (vid->rgb32 && !vid->menu_active)
|
||||||
sdl_dingux_blit_text32(vid, FONT_WIDTH_STRIDE,
|
sdl_dingux_blit_text32(vid, FONT_WIDTH_STRIDE,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user