mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Updated gfx API. Replaced gfxSetDoubleBuffering() with gfxSetMode(), and added GfxMode enum. Updated gfx.h comments. Updated gfxGetFramebufferDisplayOffset() for using the aligned width. The new GfxMode_LinearDouble is now used by default, apps must not use gfxGetFramebufferDisplayOffset() with this mode. Apps using gfxGetFramebufferDisplayOffset() must be updated.
This commit is contained in:
parent
4b2a32af59
commit
13b4c74723
@ -14,6 +14,14 @@
|
||||
/// Same as \ref RGBA8 except with alpha=0xff.
|
||||
#define RGBA8_MAXALPHA(r,g,b) RGBA8(r,g,b,0xff)
|
||||
|
||||
/// GfxMode set by \ref gfxSetMode. The default is GfxMode_LinearDouble.
|
||||
typedef enum
|
||||
{
|
||||
GfxMode_TiledSingle, /// Single-buffering with raw tiled (block-linear) framebuffer.
|
||||
GfxMode_TiledDouble, /// Double-buffering with raw tiled (block-linear) framebuffer.
|
||||
GfxMode_LinearDouble /// Double-buffering with linear framebuffer, which is transferred to the actual framebuffer by \ref gfxFlushBuffers().
|
||||
} GfxMode;
|
||||
|
||||
/**
|
||||
* @brief Initializes the graphics subsystem.
|
||||
* @warning Do not use \ref viInitialize when using this function.
|
||||
@ -30,7 +38,7 @@ void gfxExit(void);
|
||||
* @brief Sets the resolution to be used when initializing the graphics subsystem.
|
||||
* @param[in] width Horizontal resolution, in pixels.
|
||||
* @param[in] height Vertical resolution, in pixels.
|
||||
* @note The default resolution is 720p, however you should use \ref gfxGetFramebuffer to get the current width/height.
|
||||
* @note The default resolution is 720p.
|
||||
* @note This can only be used before calling \ref gfxInitDefault, this will use \ref fatalSimple otherwise. If the input is 0, the default resolution will be used during \ref gfxInitDefault. This sets the maximum resolution for the framebuffer, used during \ref gfxInitDefault. This is also used as the current resolution when crop isn't set. The width/height are reset to the default when \ref gfxExit is used.
|
||||
* @note Normally you should only use this when you need a maximum resolution larger than the default, see above.
|
||||
*/
|
||||
@ -61,34 +69,35 @@ void gfxWaitForVsync(void);
|
||||
/// Swaps the framebuffers (for double-buffering).
|
||||
void gfxSwapBuffers(void);
|
||||
|
||||
/// Get the current framebuffer address, with optional output ptrs for the display width/height. The display width/height is adjusted by \ref gfxConfigureCrop and \ref gfxConfigureResolution.
|
||||
/// Get the current framebuffer address, with optional output ptrs for the display framebuffer width/height. The display width/height is adjusted by \ref gfxConfigureCrop and \ref gfxConfigureResolution.
|
||||
u8* gfxGetFramebuffer(u32* width, u32* height);
|
||||
|
||||
/// Get the original framebuffer width/height without crop.
|
||||
/// Get the framebuffer width/height without crop.
|
||||
void gfxGetFramebufferResolution(u32* width, u32* height);
|
||||
|
||||
/// Use this to get the actual byte-size of the buffer for use with memset/etc, do not calculate the byte-size manually with the width and height from \ref gfxGetFramebuffer or \ref gfxGetFramebufferResolution.
|
||||
/// Use this to get the actual byte-size of the framebuffer for use with memset/etc.
|
||||
size_t gfxGetFramebufferSize(void);
|
||||
|
||||
/// Enables or disables double-buffering.
|
||||
void gfxSetDoubleBuffering(bool doubleBuffering);
|
||||
/// Sets the \ref GfxMode.
|
||||
void gfxSetMode(GfxMode mode);
|
||||
|
||||
/// Flushes the framebuffer in the data cache.
|
||||
/// Flushes the framebuffer in the data cache. When \ref GfxMode is GfxMode_LinearDouble, this also transfers the linear-framebuffer to the actual framebuffer.
|
||||
void gfxFlushBuffers(void);
|
||||
|
||||
/// Use this to get the pixel-offset in the framebuffer. Returned value is in pixels, not bytes.
|
||||
/// This implements tegra blocklinear, with hard-coded constants etc.
|
||||
/// Do not use this when \ref GfxMode is GfxMode_LinearDouble.
|
||||
static inline u32 gfxGetFramebufferDisplayOffset(u32 x, u32 y) {
|
||||
u32 tmp_pos;
|
||||
|
||||
extern size_t g_gfx_framebuf_width;
|
||||
extern size_t g_gfx_framebuf_aligned_width;
|
||||
extern size_t g_gfx_framebuf_display_height;
|
||||
|
||||
//if (x >= g_gfx_framebuf_width || y >= g_gfx_framebuf_display_height) return (gfxGetFramebufferSize()-4)/4;//Return the last pixel-offset in the buffer, the data located here is not displayed due to alignment. (Disabled for perf)
|
||||
|
||||
y = g_gfx_framebuf_display_height-1-y;
|
||||
|
||||
tmp_pos = ((y & 127) / 16) + (x/16*8) + ((y/16/8)*(g_gfx_framebuf_width/16*8));
|
||||
tmp_pos = ((y & 127) / 16) + (x/16*8) + ((y/16/8)*(g_gfx_framebuf_aligned_width/16*8));
|
||||
tmp_pos *= 16*16 * 4;
|
||||
|
||||
tmp_pos += ((y%16)/8)*512 + ((x%16)/8)*256 + ((y%8)/2)*64 + ((x%8)/4)*32 + (y%2)*16 + (x%4)*4;//This line is a modified version of code from the Tegra X1 datasheet.
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "types.h"
|
||||
#include "result.h"
|
||||
#include "arm/cache.h"
|
||||
@ -29,12 +30,15 @@ static bufferProducerFence g_gfx_DequeueBuffer_fence;
|
||||
static bufferProducerQueueBufferOutput g_gfx_Connect_QueueBufferOutput;
|
||||
static bufferProducerQueueBufferOutput g_gfx_QueueBuffer_QueueBufferOutput;
|
||||
|
||||
static bool g_gfxDoubleBuf = 1;
|
||||
static GfxMode g_gfxMode = GfxMode_LinearDouble;
|
||||
|
||||
static u8 *g_gfxFramebufLinear;
|
||||
|
||||
size_t g_gfx_framebuf_width=0, g_gfx_framebuf_aligned_width=0;
|
||||
size_t g_gfx_framebuf_height=0, g_gfx_framebuf_aligned_height=0;
|
||||
size_t g_gfx_framebuf_display_width=0, g_gfx_framebuf_display_height=0;
|
||||
size_t g_gfx_singleframebuf_size=0;
|
||||
size_t g_gfx_singleframebuf_linear_size=0;
|
||||
|
||||
static AppletHookCookie g_gfx_autoresolution_applethookcookie;
|
||||
static bool g_gfx_autoresolution_enabled;
|
||||
@ -125,7 +129,7 @@ static Result _gfxDequeueBuffer(void) {
|
||||
bufferProducerFence tmp_fence;
|
||||
bool async=0;
|
||||
|
||||
if (!g_gfxDoubleBuf) {
|
||||
if (g_gfxMode == GfxMode_TiledSingle) {
|
||||
g_gfxCurrentProducerBuffer = -1;
|
||||
return 0;
|
||||
}
|
||||
@ -173,7 +177,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
|
||||
g_gfx_ProducerConnected = 0;
|
||||
g_gfxFramebuf = NULL;
|
||||
g_gfxFramebufSize = 0;
|
||||
g_gfxDoubleBuf = 1;
|
||||
g_gfxMode = GfxMode_LinearDouble;
|
||||
|
||||
memset(g_gfx_ProducerSlotsRequested, 0, sizeof(g_gfx_ProducerSlotsRequested));
|
||||
memset(&g_gfx_DequeueBuffer_fence, 0, sizeof(g_gfx_DequeueBuffer_fence));
|
||||
@ -190,6 +194,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
|
||||
g_gfx_framebuf_aligned_height = (g_gfx_framebuf_height+127) & ~127;//Align to 128.
|
||||
|
||||
g_gfx_singleframebuf_size = g_gfx_framebuf_aligned_width*g_gfx_framebuf_aligned_height*4;
|
||||
g_gfx_singleframebuf_linear_size = g_gfx_framebuf_width*g_gfx_framebuf_height*4;
|
||||
|
||||
g_gfx_BufferInitData.width = g_gfx_framebuf_width;
|
||||
g_gfx_BufferInitData.height = g_gfx_framebuf_height;
|
||||
@ -204,10 +209,18 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
|
||||
g_gfx_BufferInitData.data.buffer_size0 = g_gfx_singleframebuf_size;
|
||||
g_gfx_BufferInitData.data.buffer_size1 = g_gfx_singleframebuf_size;
|
||||
|
||||
rc = viInitialize(servicetype);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
g_gfxFramebufLinear = memalign(0x1000, g_gfx_singleframebuf_linear_size);
|
||||
if (g_gfxFramebufLinear) {
|
||||
memset(g_gfxFramebufLinear, 0, g_gfx_singleframebuf_linear_size);
|
||||
}
|
||||
else {
|
||||
rc = MAKERESULT(Module_Libnx, LibnxError_OutOfMemory);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = viOpenDisplay(DisplayName, &g_gfxDisplay);
|
||||
rc = viInitialize(servicetype);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = viOpenDisplay(DisplayName, &g_gfxDisplay);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = viGetDisplayVsyncEvent(&g_gfxDisplay, &g_gfxDisplayVsyncEvent);
|
||||
|
||||
@ -286,6 +299,9 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L
|
||||
g_gfxDisplayVsyncEvent = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
free(g_gfxFramebufLinear);
|
||||
g_gfxFramebufLinear = NULL;
|
||||
|
||||
g_gfxNativeWindow_ID = 0;
|
||||
g_gfxCurrentBuffer = 0;
|
||||
g_gfxCurrentProducerBuffer = -1;
|
||||
@ -356,6 +372,9 @@ void gfxExit(void)
|
||||
|
||||
viExit();
|
||||
|
||||
free(g_gfxFramebufLinear);
|
||||
g_gfxFramebufLinear = NULL;
|
||||
|
||||
g_gfxInitialized = 0;
|
||||
g_gfxNativeWindow_ID = 0;
|
||||
|
||||
@ -495,6 +514,9 @@ u8* gfxGetFramebuffer(u32* width, u32* height) {
|
||||
if(width) *width = g_gfx_framebuf_display_width;
|
||||
if(height) *height = g_gfx_framebuf_display_height;
|
||||
|
||||
if (g_gfxMode == GfxMode_LinearDouble)
|
||||
return g_gfxFramebufLinear;
|
||||
|
||||
return &g_gfxFramebuf[g_gfxCurrentBuffer*g_gfx_singleframebuf_size];
|
||||
}
|
||||
|
||||
@ -504,15 +526,40 @@ void gfxGetFramebufferResolution(u32* width, u32* height) {
|
||||
}
|
||||
|
||||
size_t gfxGetFramebufferSize(void) {
|
||||
if (g_gfxMode == GfxMode_LinearDouble)
|
||||
return g_gfx_singleframebuf_linear_size;
|
||||
|
||||
return g_gfx_singleframebuf_size;
|
||||
}
|
||||
|
||||
void gfxSetDoubleBuffering(bool doubleBuffering) {
|
||||
g_gfxDoubleBuf = doubleBuffering;
|
||||
void gfxSetMode(GfxMode mode) {
|
||||
g_gfxMode = mode;
|
||||
}
|
||||
|
||||
void gfxFlushBuffers(void) {
|
||||
armDCacheFlush(&g_gfxFramebuf[g_gfxCurrentBuffer*g_gfx_singleframebuf_size], g_gfx_singleframebuf_size);
|
||||
u32 *actual_framebuf = (u32*)&g_gfxFramebuf[g_gfxCurrentBuffer*g_gfx_singleframebuf_size];
|
||||
|
||||
if (g_gfxMode == GfxMode_LinearDouble) {
|
||||
//TODO: Implement block-linear here without re-calculating the entire offset with gfxGetFramebufferDisplayOffset().
|
||||
|
||||
size_t x, y, j, tmpoff;
|
||||
size_t width = g_gfx_framebuf_display_width;
|
||||
size_t height = g_gfx_framebuf_display_height;
|
||||
u32 *in_framebuf = (u32*)g_gfxFramebufLinear;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x+=4) {
|
||||
tmpoff = gfxGetFramebufferDisplayOffset(x, y);
|
||||
for(j=0; j<4; j++) {
|
||||
if (x+j >= width)
|
||||
break;
|
||||
actual_framebuf[tmpoff+j] = in_framebuf[y * width + x+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
armDCacheFlush(actual_framebuf, g_gfx_singleframebuf_size);
|
||||
}
|
||||
|
||||
/*static Result _gfxGetDisplayResolution(u64 *width, u64 *height) {
|
||||
|
@ -547,7 +547,7 @@ PrintConsole* consoleInit(PrintConsole* console) {
|
||||
|
||||
console->consoleInitialised = 1;
|
||||
|
||||
gfxSetDoubleBuffering(false);
|
||||
gfxSetMode(GfxMode_TiledSingle);
|
||||
gfxFlushBuffers();
|
||||
gfxWaitForVsync();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user