Add variable GPU buffer size and System Font textures

This commit is contained in:
Thomas Edvalson
2016-05-15 22:40:51 -04:00
parent 08241ffbfa
commit 9c8aed7cdb
7 changed files with 154 additions and 17 deletions
+8
View File
@@ -216,6 +216,13 @@ public :
////////////////////////////////////////////////////////////
bool loadFromImage(const Image& image, const IntRect& area = IntRect());
#ifndef EMULATION
bool loadFromPreprocessedFile(const std::string& filename, size_t width, size_t height, GPU_TEXCOLOR format);
bool loadFromPreprocessedMemory(void *data, size_t size, size_t width, size_t height, GPU_TEXCOLOR format, bool copyData = true);
C3D_Tex* getNativeTexture() { return m_texture; }
#endif
////////////////////////////////////////////////////////////
/// \brief Return the size of the texture
///
@@ -501,6 +508,7 @@ private :
unsigned int m_texture; ///< Internal texture identifier
#else
C3D_Tex* m_texture; ///< Internal texture identifier
bool m_ownsData; ///< Check if this object owns the data and needs to free it
#endif
};
+5 -1
View File
@@ -24,7 +24,11 @@ public:
void render();
void run();
void exit();
Game();
#ifdef EMULATION
Game(size_t gpuCommandBufSize = 0);
#else
Game(size_t gpuCommandBufSize = C3D_DEFAULT_CMDBUF_SIZE);
#endif
virtual ~Game();
protected:
Window windowTop, windowBottom;
+2 -2
View File
@@ -5,9 +5,9 @@ namespace
C3D_MtxStack projectionMatrix, modelviewMatrix, textureMatrix;
}
void CitroInit()
void CitroInit(size_t commandBufferSize)
{
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
C3D_Init(commandBufferSize);
// Configure attributes for use with the vertex shader
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
+1 -1
View File
@@ -1,7 +1,7 @@
#pragma once
#include <citro3d.h>
void CitroInit();
void CitroInit(size_t commandBufferSize);
void CitroDestroy();
void CitroBindUniforms(shaderProgram_s* program);
void CitroUpdateMatrixStacks();
+117 -10
View File
@@ -37,6 +37,8 @@
#include <cstring>
#include <iostream>
#include <c3d/texture.h>
#include <cpp3ds/System/FileInputStream.hpp>
#include <cpp3ds/System/FileSystem.hpp>
#include "CitroHelpers.hpp"
// Note: vertical flip flag set so 0,0 is top left of texture
@@ -124,6 +126,7 @@ m_texture (nullptr),
m_isSmooth (false),
m_isRepeated (false),
m_pixelsFlipped(false),
m_ownsData (true),
m_cacheId (getUniqueId())
{
@@ -138,6 +141,7 @@ m_texture (nullptr),
m_isSmooth (copy.m_isSmooth),
m_isRepeated (copy.m_isRepeated),
m_pixelsFlipped(false),
m_ownsData (true),
m_cacheId (getUniqueId())
{
if (copy.m_texture)
@@ -148,12 +152,11 @@ m_cacheId (getUniqueId())
////////////////////////////////////////////////////////////
Texture::~Texture()
{
// Destroy the OpenGL texture
if (m_texture)
{
if (m_ownsData)
C3D_TexDelete(m_texture);
if (m_texture)
delete m_texture;
}
}
@@ -295,6 +298,74 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
}
////////////////////////////////////////////////////////////
bool Texture::loadFromPreprocessedFile(const std::string& filename, size_t width, size_t height, GPU_TEXCOLOR format)
{
if (filename.empty())
return false;
FileInputStream file;
file.open(filename);
size_t size = file.getSize();
void *data = malloc(size);
file.read(data, size);
bool ret = loadFromPreprocessedMemory(data, size, width, height, format, true);
free(data);
return ret;
}
////////////////////////////////////////////////////////////
bool Texture::loadFromPreprocessedMemory(void *data, size_t size, size_t width, size_t height, GPU_TEXCOLOR format, bool copyData)
{
if (!data)
return false;
m_ownsData = copyData;
m_size.x = width;
m_size.y = height;
m_actualSize = m_size;
m_pixelsFlipped = false;
ensureGlContext();
// Create the citro3d texture, or delete if already created
if (!m_texture)
m_texture = new C3D_Tex();
else
C3D_TexDelete(m_texture);
if (!m_texture)
return false;
if (copyData)
{
C3D_TexInit(m_texture, width, height, format);
C3D_TexUpload(m_texture, data);
}
else
m_texture->data = data;
m_texture->size = size;
m_texture->fmt = format;
m_texture->height = height;
m_texture->width = width;
C3D_TexSetWrap(m_texture,
m_isRepeated ? GPU_REPEAT : GPU_CLAMP_TO_EDGE,
m_isRepeated ? GPU_REPEAT : GPU_CLAMP_TO_EDGE);
C3D_TexSetFilter(m_texture,
m_isSmooth ? GPU_LINEAR : GPU_NEAREST,
m_isSmooth ? GPU_LINEAR : GPU_NEAREST);
m_cacheId = getUniqueId();
return true;
}
////////////////////////////////////////////////////////////
Vector2u Texture::getSize() const
{
@@ -312,9 +383,19 @@ Image Texture::copyToImage() const
// Create an array of pixels
std::vector<Uint8> pixels(m_size.x * m_size.y * 4);
u32 *data = (u32*)malloc(m_texture->size);
u32 *data = (u32*)linearAlloc(m_texture->size);
imageUntile32((u8*)data, (u8*)m_texture->data, 0, 0, m_texture->width, m_texture->height, m_texture->width, m_texture->height);
if (m_texture->width < 64 || m_texture->height < 64)
imageUntile32((u8*)data, (u8*)m_texture->data, 0, 0, m_texture->width, m_texture->height, m_texture->width, m_texture->height);
else
{
u32 dim = GX_BUFFER_DIM(m_texture->width, m_texture->height);
GX_DisplayTransfer((u32*)m_texture->data, dim, data, dim, TEXTURE_TRANSFER_FLAGS);
gspWaitForPPF();
GSPGPU_FlushDataCache(data, m_texture->size);
for (int i = 0; i < m_texture->width * m_texture->height; ++i)
data[i] = __builtin_bswap32(data[i]);
}
if ((m_size == m_actualSize) && !m_pixelsFlipped)
{
@@ -354,7 +435,7 @@ Image Texture::copyToImage() const
Image image;
image.create(m_size.x, m_size.y, &pixels[0]);
free(data);
linearFree(data);
return image;
}
@@ -376,11 +457,37 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
if (pixels && m_texture)
{
u8* dest = (u8*)m_texture->data;
if (m_texture->width < 64 || m_texture->height < 64)
{
u8* dest = (u8*)m_texture->data;
imageTile32(dest, pixels, x, y, width, height, m_texture->width, m_texture->height);
imageTile32(dest, pixels, x, y, width, height, m_texture->width, m_texture->height);
C3D_TexFlush(m_texture);
C3D_TexFlush(m_texture);
}
else
{
const u32 *pixels32 = reinterpret_cast<const u32*>(pixels);
u32 *data = (u32*)linearAlloc(m_texture->size);
u32 dim = GX_BUFFER_DIM(m_texture->width, m_texture->height);
GX_DisplayTransfer((u32*)m_texture->data, dim, data, dim, TEXTURE_TRANSFER_FLAGS);
gspWaitForPPF();
for (int h = 0; h < height; ++h)
{
for (int w = 0; w < width; ++w)
{
data[(y+h)*m_texture->width+x+w] = __builtin_bswap32(pixels32[(h*width) + w]);
}
}
GSPGPU_FlushDataCache(data, m_texture->size);
GX_DisplayTransfer(data, dim, (u32*)m_texture->data, dim, TEXTURE_TRANSFER_FLAGS | GX_TRANSFER_OUT_TILED(1));
gspWaitForPPF();
linearFree(data);
}
m_pixelsFlipped = false;
m_cacheId = getUniqueId();
+20 -2
View File
@@ -8,6 +8,8 @@
namespace cpp3ds {
// System font sheets to be fetched and released by Game
cpp3ds::Texture *system_font_textures = nullptr;
//Apt hook cookie
static aptHookCookie apt_hook_cookie;
@@ -21,12 +23,12 @@ static void apt_clock_hook(APT_HookType hook, void* param)
}
Game::Game()
Game::Game(size_t gpuCommandBufSize)
: m_triggerExit(false)
{
if (!Console::isEnabled() && !Console::isEnabledBasic())
gfxInitDefault();
CitroInit();
CitroInit(gpuCommandBufSize);
osSetSpeedupEnable(true);
Service::enable(RomFS);
I18n::getInstance(); // Init and load localization file(s)
@@ -39,11 +41,27 @@ Game::Game()
if (!Shader::Default.loadBinary(defaultShader.data, defaultShader.size, Shader::Vertex)){
err() << "Failed to load default_shader.vsh from cpp3ds core.";
}
// Load system font texture sheets
if (R_SUCCEEDED(fontEnsureMapped()))
{
TGLP_s* glyphInfo = fontGetGlyphInfo();
system_font_textures = new cpp3ds::Texture[glyphInfo->nSheets];
for (int i = 0; i < glyphInfo->nSheets; ++i)
{
system_font_textures[i].loadFromPreprocessedMemory(
fontGetGlyphSheetTex(i), glyphInfo->sheetSize,
glyphInfo->sheetWidth, glyphInfo->sheetHeight,
(GPU_TEXCOLOR)glyphInfo->sheetFmt, false);
system_font_textures[i].setSmooth(true);
}
}
}
Game::~Game()
{
delete[] system_font_textures;
Service::disable(All);
CitroDestroy();
gfxExit();
+1 -1
View File
@@ -9,7 +9,7 @@
namespace cpp3ds {
Game::Game()
Game::Game(size_t gpuCommandBufSize)
: m_triggerExit(false)
{
priv::ensureExtensionsInit();