-
-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[OGC] Add support for Custom Aspect Ratios #91
base: ogc-sdl-2.28
Are you sure you want to change the base?
Changes from 25 commits
8eaebcf
37151df
62191d5
19e2688
e1f2bfd
6570d34
4a73bb7
fc69931
ab85398
d6efcad
4dc34db
7afc872
016de5f
a5d6187
7fc3f5c
052e287
027d5d2
5219b8f
d1b37b4
412eb51
e254a96
072708b
95c62a7
40e5e47
984d25b
ad259a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ | |
#include <ogc/cache.h> | ||
#include <ogc/gx.h> | ||
#include <ogc/video.h> | ||
#include <ogc/conf.h> | ||
|
||
static const f32 tex_pos[] __attribute__((aligned(32))) = { | ||
0.0, | ||
|
@@ -40,12 +41,32 @@ static const f32 tex_pos[] __attribute__((aligned(32))) = { | |
1.0, | ||
}; | ||
|
||
bool OGC_get_aspect_ratio_dimensions(float *w, float *h) | ||
{ | ||
const char *ratioString; | ||
ratioString = SDL_getenv("SDL_OGC_ASPECT_RATIO"); | ||
|
||
if(ratioString == NULL) { | ||
#ifdef __wii__ | ||
if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) { | ||
*w = 16.0f; | ||
*h = 9.0f; | ||
return true; | ||
} | ||
#endif | ||
*w = 4.0f; | ||
*h = 3.0f; | ||
return true; | ||
} else if(SDL_sscanf(ratioString, "%f:%f", w, h) == 2) return true; | ||
return false; | ||
} | ||
|
||
void OGC_set_viewport(int x, int y, int w, int h) | ||
{ | ||
Mtx44 proj; | ||
|
||
GX_SetViewport(x, y, w, h, 0, 1); | ||
GX_SetScissor(x, y, w, h); | ||
GX_SetViewport(x, y, (w > 640) ? 640 : w, h, 0, 1); | ||
GX_SetScissor(x, y, (w > 640) ? 640 : w, h); | ||
|
||
// matrix, t, b, l, r, n, f | ||
guOrtho(proj, 0, h, 0, w, 0, 1); | ||
Comment on lines
+64
to
68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that GX_SetViewport and GX_SetScissor can be set to the EFB size (that is, we can consider In other words, I would set leave the calls to GX_SetViewport and GX_SetScissor exactly as they were, then call OGC_get_aspect_ratio_dimensions right from within this function and call const float ratio4_3 = 4.0f / 3.0f;
guOrtho(proj, 0, h, 0, w * ratio / ratio4_3, 0, 1); Of course, this needs to be checked. :-) The thing is, if you pass the same values to both functions (GX_SetViewport and guOrtho) you get a 1:1 mapping, which is not what we want for widescreen cases (or for any case where the ratio is not 4/3). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I gave up aspect correcting apps that aren't using 16:9 |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ | |
#include "SDL_ogcgxcommon.h" | ||
#include "SDL_ogcmouse.h" | ||
#include "SDL_ogcpixels.h" | ||
#include "SDL_ogcvideo.h" | ||
|
||
#include "../SDL_sysvideo.h" | ||
#include "../../render/SDL_sysrender.h" | ||
|
@@ -178,6 +179,10 @@ void OGC_draw_cursor(_THIS) | |
int screen_w, screen_h; | ||
float angle = 0.0f; | ||
|
||
float aspect_w = 4.0f; | ||
float aspect_h = 3.0f; | ||
OGC_get_aspect_ratio_dimensions(&aspect_w, &aspect_h); | ||
|
||
if (!mouse || !mouse->cursor_shown || | ||
!mouse->cur_cursor || !mouse->cur_cursor->driverdata) { | ||
return; | ||
|
@@ -195,11 +200,16 @@ void OGC_draw_cursor(_THIS) | |
screen_h = _this->displays[0].current_mode.h; | ||
|
||
curdata = mouse->cur_cursor->driverdata; | ||
OGC_load_texture(curdata->texels, curdata->w, curdata->h, GX_TF_RGBA8, | ||
SDL_ScaleModeNearest); | ||
if (aspect_w > 4.0f && aspect_h > 3.0f) | ||
OGC_load_texture(curdata->texels, curdata->w, curdata->h, GX_TF_RGBA8, | ||
SDL_ScaleModeLinear); | ||
else | ||
OGC_load_texture(curdata->texels, curdata->w, curdata->h, GX_TF_RGBA8, | ||
SDL_ScaleModeNearest); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand what this does, and I'm not sure that the Note that the scaling is done either by the TV or by the VI interface, so I don't think we should be changing how the texture is being filtered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cursor looks very jittery on other aspect ratios, so I changed it to Linear since it wouldn't be as noticeable, but it's still noticeable and I have no idea why it's cutting pixels from the image depending on where it is |
||
|
||
guMtxIdentity(mv); | ||
guMtxScaleApply(mv, mv, screen_w / 640.0f, screen_h / 480.0f, 1.0f); | ||
guMtxScaleApply(mv, mv, screen_w / (480.0f * aspect_w / aspect_h), screen_h / 480.0f, 1.0f); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You cannot do this on the modelview matrix, because then you are actually changing the cursor width, and then if the cursor then gets rotated it will appear wrong. I think that all this code should stay unchanged, and we should only operate on how the OGX_set_viewport function gets called. It sounds a bit silly, since it was me who introduces this scaling, but looking at it now, it appears wrong: we already have the viewport to do the scaling; can you try to just remove this line? And in the call to OGC_set_viewport() below, we should probably pass the EFB dimensions, not the screen dimensions adjusted for the aspect ratio (at least if you follow my suggestion about retrieving the aspect ratio from OGC_set_viewport). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why would I retrieve the aspect ratio from the viewport function tough? I stopped doing a different width for the matrix because it's more correct, an app will look right if it's widescreen There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i made the resize be sceen height dependant |
||
|
||
if (angle != 0.0f) { | ||
Mtx rot; | ||
guMtxRotDeg(rot, 'z', angle); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ | |
|
||
#include <malloc.h> | ||
#include <ogc/color.h> | ||
#include <ogc/conf.h> | ||
#include <ogc/gx.h> | ||
#include <ogc/system.h> | ||
#include <ogc/video.h> | ||
|
@@ -87,13 +88,22 @@ static void OGC_VideoQuit(_THIS); | |
|
||
static void init_display_mode(SDL_DisplayMode *mode, const GXRModeObj *vmode) | ||
{ | ||
float aspect_w = 4.0f; | ||
float aspect_h = 3.0f; | ||
OGC_get_aspect_ratio_dimensions(&aspect_w, &aspect_h); | ||
|
||
u32 format = VI_FORMAT_FROM_MODE(vmode->viTVMode); | ||
|
||
/* Use a fake 32-bpp desktop mode */ | ||
SDL_zero(*mode); | ||
mode->format = SDL_PIXELFORMAT_ARGB8888; | ||
mode->w = vmode->fbWidth; | ||
|
||
mode->h = vmode->efbHeight; | ||
if (aspect_w > 4.0f && aspect_h > 3.0f) { | ||
mode->w = mode->h * aspect_w / aspect_h; | ||
mode->w = (mode->w + 1) & ~1; | ||
} else | ||
mode->w = vmode->fbWidth; | ||
switch (format) { | ||
case VI_DEBUG: | ||
case VI_NTSC: | ||
|
@@ -157,6 +167,20 @@ static void setup_video_mode(_THIS, GXRModeObj *vmode) | |
{ | ||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; | ||
|
||
// TODO: Should I make this only happen if the aspect ratio isn't 4:3? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To simplify things I suggest forgetting about the VI changes for now (have them in a separate PR later), because handing of the CONF_GetAspectRatio() is a bit orthogonal to setting the best video mode. It will make testing and reviewing easier, if we tackle one issue at a time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
if(vmode->viWidth == 240 || vmode->viWidth == 640) | ||
vmode->viWidth = vmode->viWidth + (VI_MAX_WIDTH_NTSC - 640); | ||
|
||
// set Center point | ||
if (VI_FORMAT_FROM_MODE(vmode->viTVMode) == VI_PAL) { | ||
vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2; | ||
vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2; | ||
} else { | ||
vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2; | ||
vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2; | ||
} | ||
|
||
|
||
VIDEO_SetBlack(true); | ||
VIDEO_Configure(vmode); | ||
|
||
|
@@ -170,7 +194,8 @@ static void setup_video_mode(_THIS, GXRModeObj *vmode) | |
VIDEO_Flush(); | ||
|
||
VIDEO_WaitVSync(); | ||
if (vmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); | ||
if (vmode->viTVMode & VI_NON_INTERLACE) | ||
VIDEO_WaitVSync(); | ||
|
||
/* Setup the EFB -> XFB copy operation */ | ||
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight); | ||
|
@@ -277,6 +302,15 @@ int OGC_VideoInit(_THIS) | |
VIDEO_Init(); | ||
|
||
vmode = VIDEO_GetPreferredMode(NULL); | ||
vmode->viWidth = VI_MAX_WIDTH_NTSC; // VI_MAX_WIDTH is the same for all regions | ||
// set Center point | ||
if (VI_FORMAT_FROM_MODE(vmode->viTVMode) == VI_PAL) { | ||
vmode->viXOrigin = (VI_MAX_WIDTH_PAL - vmode->viWidth) / 2; | ||
vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - vmode->viHeight) / 2; | ||
} else { | ||
vmode->viXOrigin = (VI_MAX_WIDTH_NTSC - vmode->viWidth) / 2; | ||
vmode->viYOrigin = (VI_MAX_HEIGHT_NTSC - vmode->viHeight) / 2; | ||
} | ||
|
||
videodata->gp_fifo = memalign(32, DEFAULT_FIFO_SIZE); | ||
memset(videodata->gp_fifo, 0, DEFAULT_FIFO_SIZE); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not really needed to use two floats here. Either do
or
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it's better to cache the result of this function, since we don't expect the variable to change during run-time. If you decide to go with a single float, caching could be achieved like this:
You could even remove the boolean value, and make the function return the float directly; then, if it's 0.0, it means that no ratio has been set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I did it this way was just for accuracy, I feared rounding errors if I didn't use 2 floats
If I just return the ratio that'll be enough though,
Also caching the value would be annoying because I was gonna make a SDL test app that allows you to recreate the window with a different aspect ratio to test the output... But if it's worth it I'll do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made it a float, will cache it when I get the chance