mirror of https://github.com/mgba-emu/mgba.git
Add some NEON resizing code
This commit is contained in:
parent
6e32ade69e
commit
6ca25e44aa
|
@ -18,6 +18,11 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifdef __ARM_NEON
|
||||||
|
void _neon2x(void* dest, void* src, int width, int height);
|
||||||
|
void _neon4x(void* dest, void* src, int width, int height);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct SoftwareRenderer {
|
struct SoftwareRenderer {
|
||||||
struct GBAVideoSoftwareRenderer d;
|
struct GBAVideoSoftwareRenderer d;
|
||||||
struct GBASDLAudio audio;
|
struct GBASDLAudio audio;
|
||||||
|
@ -26,9 +31,11 @@ struct SoftwareRenderer {
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_Texture* tex;
|
SDL_Texture* tex;
|
||||||
SDL_Renderer* sdlRenderer;
|
SDL_Renderer* sdlRenderer;
|
||||||
|
#else
|
||||||
|
int ratio;
|
||||||
|
#endif
|
||||||
int viewportWidth;
|
int viewportWidth;
|
||||||
int viewportHeight;
|
int viewportHeight;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int _GBASDLInit(struct SoftwareRenderer* renderer);
|
static int _GBASDLInit(struct SoftwareRenderer* renderer);
|
||||||
|
@ -47,6 +54,9 @@ int main(int argc, char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderer.viewportWidth = opts.width;
|
||||||
|
renderer.viewportHeight = opts.height;
|
||||||
|
|
||||||
if (!_GBASDLInit(&renderer)) {
|
if (!_GBASDLInit(&renderer)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +75,6 @@ int main(int argc, char** argv) {
|
||||||
GBAMapOptionsToContext(&opts, &context);
|
GBAMapOptionsToContext(&opts, &context);
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
renderer.viewportWidth = opts.width;
|
|
||||||
renderer.viewportHeight = opts.height;
|
|
||||||
renderer.events.fullscreen = opts.fullscreen;
|
renderer.events.fullscreen = opts.fullscreen;
|
||||||
renderer.window = SDL_CreateWindow("GBAc", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer.viewportWidth, renderer.viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer.events.fullscreen));
|
renderer.window = SDL_CreateWindow("GBAc", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer.viewportWidth, renderer.viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer.events.fullscreen));
|
||||||
SDL_GetWindowSize(renderer.window, &renderer.viewportWidth, &renderer.viewportHeight);
|
SDL_GetWindowSize(renderer.window, &renderer.viewportWidth, &renderer.viewportHeight);
|
||||||
|
@ -91,12 +99,23 @@ int main(int argc, char** argv) {
|
||||||
#else
|
#else
|
||||||
SDL_Surface* surface = SDL_GetVideoSurface();
|
SDL_Surface* surface = SDL_GetVideoSurface();
|
||||||
SDL_LockSurface(surface);
|
SDL_LockSurface(surface);
|
||||||
renderer.d.outputBuffer = surface->pixels;
|
|
||||||
|
renderer.ratio = renderer.viewportWidth / VIDEO_HORIZONTAL_PIXELS;
|
||||||
|
if (renderer.ratio == 1) {
|
||||||
|
renderer.d.outputBuffer = surface->pixels;
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
renderer.d.outputBufferStride = surface->pitch / 2;
|
renderer.d.outputBufferStride = surface->pitch / 2;
|
||||||
#else
|
#else
|
||||||
renderer.d.outputBufferStride = surface->pitch / 4;
|
renderer.d.outputBufferStride = surface->pitch / 4;
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
#ifdef COLOR_16_BIT
|
||||||
|
renderer.d.outputBuffer = malloc(240 * 160 * 2);
|
||||||
|
#else
|
||||||
|
renderer.d.outputBuffer = malloc(240 * 160 * 4);
|
||||||
|
#endif
|
||||||
|
renderer.d.outputBufferStride = 240;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GBAThreadStart(&context);
|
GBAThreadStart(&context);
|
||||||
|
@ -128,9 +147,9 @@ static int _GBASDLInit(struct SoftwareRenderer* renderer) {
|
||||||
|
|
||||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
#ifdef COLOR_16_BIT
|
#ifdef COLOR_16_BIT
|
||||||
SDL_SetVideoMode(240, 160, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
|
SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
|
||||||
#else
|
#else
|
||||||
SDL_SetVideoMode(240, 160, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
|
SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -156,6 +175,20 @@ static void _GBASDLRunloop(struct GBAThread* context, struct SoftwareRenderer* r
|
||||||
renderer->d.outputBufferStride /= 4;
|
renderer->d.outputBufferStride /= 4;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
switch (renderer->ratio) {
|
||||||
|
#if defined(__ARM_NEON) && COLOR_16_BIT
|
||||||
|
case 2:
|
||||||
|
_neon2x(surface->pixels, renderer->d.outputBuffer, 240, 160);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
_neon4x(surface->pixels, renderer->d.outputBuffer, 240, 160);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
SDL_Flip(surface);
|
SDL_Flip(surface);
|
||||||
SDL_LockSurface(surface);
|
SDL_LockSurface(surface);
|
||||||
|
|
|
@ -26,6 +26,67 @@ strh r6, [r8], #2
|
||||||
strh r7, [r8], #2
|
strh r7, [r8], #2
|
||||||
subs r10, #8
|
subs r10, #8
|
||||||
bne .L1
|
bne .L1
|
||||||
.L9:
|
|
||||||
pop {r4-r10}
|
pop {r4-r10}
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
|
# r0: Destination
|
||||||
|
# r1: Source
|
||||||
|
# r2: Width
|
||||||
|
# r3: Height
|
||||||
|
.global _neon2x
|
||||||
|
_neon2x:
|
||||||
|
push {r4-r5}
|
||||||
|
lsl r4, r2, #2
|
||||||
|
.n20:
|
||||||
|
mov r2, r4, lsr #4
|
||||||
|
add r5, r0, r4
|
||||||
|
.n21:
|
||||||
|
vld2.32 {d0[], d1[]}, [r1]!
|
||||||
|
vmov d2, d0
|
||||||
|
vmov d3, d1
|
||||||
|
vzip.16 d0, d2
|
||||||
|
vzip.16 d1, d3
|
||||||
|
vst1.32 {q0}, [r0]!
|
||||||
|
vst1.32 {q0}, [r5]!
|
||||||
|
subs r2, #1
|
||||||
|
bne .n21
|
||||||
|
subs r3, #1
|
||||||
|
mov r0, r5
|
||||||
|
bne .n20
|
||||||
|
pop {r4-r5}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.global _neon4x
|
||||||
|
_neon4x:
|
||||||
|
push {r4-r7}
|
||||||
|
lsl r4, r2, #3
|
||||||
|
.n40:
|
||||||
|
mov r2, r4, lsr #5
|
||||||
|
add r5, r0, r4
|
||||||
|
add r6, r5, r4
|
||||||
|
add r7, r6, r4
|
||||||
|
.n41:
|
||||||
|
vld4.16 {d0[], d1[], d2[], d3[]}, [r1]!
|
||||||
|
vst1.16 {d0}, [r0]!
|
||||||
|
vst1.16 {d0}, [r5]!
|
||||||
|
vst1.16 {d0}, [r6]!
|
||||||
|
vst1.16 {d0}, [r7]!
|
||||||
|
vst1.16 {d1}, [r0]!
|
||||||
|
vst1.16 {d1}, [r5]!
|
||||||
|
vst1.16 {d1}, [r6]!
|
||||||
|
vst1.16 {d1}, [r7]!
|
||||||
|
vst1.16 {d2}, [r0]!
|
||||||
|
vst1.16 {d2}, [r5]!
|
||||||
|
vst1.16 {d2}, [r6]!
|
||||||
|
vst1.16 {d2}, [r7]!
|
||||||
|
vst1.16 {d3}, [r0]!
|
||||||
|
vst1.16 {d3}, [r5]!
|
||||||
|
vst1.16 {d3}, [r6]!
|
||||||
|
vst1.16 {d3}, [r7]!
|
||||||
|
subs r2, #1
|
||||||
|
bne .n41
|
||||||
|
subs r3, #1
|
||||||
|
mov r0, r7
|
||||||
|
bne .n40
|
||||||
|
pop {r4-r7}
|
||||||
|
bx lr
|
||||||
|
|
Loading…
Reference in New Issue