Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9f21cf7b38 | ||
![]() |
00396e8a99 | ||
![]() |
66a0594e5d | ||
![]() |
e8825650c6 | ||
![]() |
e2992d276f | ||
![]() |
b6d0b7d876 | ||
![]() |
bbe09c4265 | ||
![]() |
a491a8eb79 | ||
![]() |
c7425b653e | ||
![]() |
100ebd4067 | ||
![]() |
03235602cd | ||
![]() |
4e02e27222 | ||
![]() |
05e8039b7f | ||
![]() |
f4367ad55d | ||
![]() |
bbbadebeae | ||
![]() |
7999093588 | ||
![]() |
dcb3aac861 | ||
![]() |
3d566ac8da | ||
![]() |
f2850e3bfe | ||
![]() |
c22c354f1a | ||
![]() |
9d51a9445d | ||
![]() |
ebf41b6436 | ||
![]() |
8d8979947e | ||
![]() |
81ca5d3575 | ||
![]() |
52cdcb351a | ||
![]() |
5e1bc20126 | ||
![]() |
6b6e9eef80 | ||
![]() |
c23a8015f3 | ||
![]() |
c2226e2182 | ||
![]() |
8f3fda7986 | ||
![]() |
b59cdc3c7c | ||
![]() |
d24e404582 | ||
![]() |
10e929d4bb | ||
![]() |
4ed5536bcc | ||
![]() |
8764804dd5 | ||
![]() |
ac1fad7107 | ||
![]() |
4ada36b6cd |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.*/
|
||||
*~
|
||||
*.3dsx
|
||||
*.elf
|
||||
|
18
LICENSE
Normal file
18
LICENSE
Normal file
@ -0,0 +1,18 @@
|
||||
Copyright (C) 2014-2018 fincs
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
17
Makefile
17
Makefile
@ -9,8 +9,8 @@ endif
|
||||
include $(DEVKITARM)/3ds_rules
|
||||
|
||||
export CITRO3D_MAJOR := 1
|
||||
export CITRO3D_MINOR := 3
|
||||
export CITRO3D_PATCH := 0
|
||||
export CITRO3D_MINOR := 7
|
||||
export CITRO3D_PATCH := 1
|
||||
|
||||
VERSION := $(CITRO3D_MAJOR).$(CITRO3D_MINOR).$(CITRO3D_PATCH)
|
||||
|
||||
@ -22,8 +22,7 @@ VERSION := $(CITRO3D_MAJOR).$(CITRO3D_MINOR).$(CITRO3D_PATCH)
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := citro3d
|
||||
SOURCES := source \
|
||||
source/maths
|
||||
SOURCES := source source/maths
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
@ -32,11 +31,11 @@ INCLUDES := include
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -Werror -mword-relocations \
|
||||
CFLAGS := -g -Wall -Wno-sizeof-array-div -Werror -mword-relocations \
|
||||
-ffunction-sections -fdata-sections \
|
||||
$(ARCH) $(BUILD_CFLAGS)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS -DCITRO3D_BUILD
|
||||
CFLAGS += $(INCLUDE) -D__3DS__ -DCITRO3D_BUILD
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
@ -101,8 +100,8 @@ dist-src:
|
||||
dist: dist-src dist-bin
|
||||
|
||||
install: dist-bin
|
||||
mkdir -p $(DEVKITPRO)/libctru
|
||||
bzip2 -cd citro3d-$(VERSION).tar.bz2 | tar -xf - -C $(DEVKITPRO)/libctru
|
||||
mkdir -p $(DESTDIR)$(DEVKITPRO)/libctru
|
||||
bzip2 -cd citro3d-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/libctru
|
||||
|
||||
lib:
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@ -115,7 +114,7 @@ debug:
|
||||
|
||||
lib/libcitro3d.a : lib release $(SOURCES) $(INCLUDES)
|
||||
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2 -fomit-frame-pointer" \
|
||||
BUILD_CFLAGS="-DNDEBUG=1 -O2 -fomit-frame-pointer -fno-math-errno" \
|
||||
DEPSDIR=$(CURDIR)/release \
|
||||
--no-print-directory -C release \
|
||||
-f $(CURDIR)/Makefile
|
||||
|
@ -11,7 +11,6 @@ enum
|
||||
};
|
||||
|
||||
bool C3D_Init(size_t cmdBufSize);
|
||||
void C3D_FlushAsync(void);
|
||||
void C3D_Fini(void);
|
||||
|
||||
float C3D_GetCmdBufUsage(void);
|
||||
@ -34,23 +33,6 @@ static inline void C3D_ImmDrawRestartPrim(void)
|
||||
GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1);
|
||||
}
|
||||
|
||||
static inline void C3D_FlushAwait(void)
|
||||
{
|
||||
gspWaitForP3D();
|
||||
}
|
||||
|
||||
static inline void C3D_Flush(void)
|
||||
{
|
||||
C3D_FlushAsync();
|
||||
C3D_FlushAwait();
|
||||
}
|
||||
|
||||
static inline void C3D_VideoSync(void)
|
||||
{
|
||||
gspWaitForEvent(GSPGPU_EVENT_VBlank0, false);
|
||||
gfxSwapBuffersGpu();
|
||||
}
|
||||
|
||||
// Fixed vertex attributes
|
||||
C3D_FVec* C3D_FixedAttribGetWritePtr(int id);
|
||||
|
||||
|
@ -7,6 +7,12 @@ typedef struct
|
||||
u32 data[128];
|
||||
} C3D_FogLut;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 diff[8];
|
||||
u32 color[8];
|
||||
} C3D_GasLut;
|
||||
|
||||
static inline float FogLut_CalcZ(float depth, float near, float far)
|
||||
{
|
||||
return far*near/(depth*(far-near)+near);
|
||||
@ -18,3 +24,16 @@ void FogLut_Exp(C3D_FogLut* lut, float density, float gradient, float near, floa
|
||||
void C3D_FogGasMode(GPU_FOGMODE fogMode, GPU_GASMODE gasMode, bool zFlip);
|
||||
void C3D_FogColor(u32 color);
|
||||
void C3D_FogLutBind(C3D_FogLut* lut);
|
||||
|
||||
void GasLut_FromArray(C3D_GasLut* lut, const u32 data[9]);
|
||||
|
||||
void C3D_GasBeginAcc(void);
|
||||
void C3D_GasDeltaZ(float value);
|
||||
|
||||
void C3D_GasAccMax(float value);
|
||||
void C3D_GasAttn(float value);
|
||||
void C3D_GasLightPlanar(float min, float max, float attn);
|
||||
void C3D_GasLightView(float min, float max, float attn);
|
||||
void C3D_GasLightDirection(float dotp);
|
||||
void C3D_GasLutInput(GPU_GASLUTINPUT input);
|
||||
void C3D_GasLutBind(C3D_GasLut* lut);
|
||||
|
@ -77,6 +77,14 @@ enum
|
||||
void C3D_LightEnvFresnel(C3D_LightEnv* env, GPU_FRESNELSEL selector);
|
||||
void C3D_LightEnvBumpMode(C3D_LightEnv* env, GPU_BUMPMODE mode);
|
||||
void C3D_LightEnvBumpSel(C3D_LightEnv* env, int texUnit);
|
||||
|
||||
/**
|
||||
* @brief Configures whether to use the z component of the normal map.
|
||||
* @param[out] env Pointer to light environment structure.
|
||||
* @param[in] enable false if the z component is reconstructed from the xy components
|
||||
* of the normal map, true if the z component is taken from the normal map.
|
||||
*/
|
||||
void C3D_LightEnvBumpNormalZ(C3D_LightEnv *env, bool enable);
|
||||
void C3D_LightEnvShadowMode(C3D_LightEnv* env, u32 mode);
|
||||
void C3D_LightEnvShadowSel(C3D_LightEnv* env, int texUnit);
|
||||
void C3D_LightEnvClampHighlights(C3D_LightEnv* env, bool clamp);
|
||||
|
@ -13,7 +13,12 @@
|
||||
* The one true circumference-to-radius ratio.
|
||||
* See http://tauday.com/tau-manifesto
|
||||
*/
|
||||
#define M_TAU (2*M_PI)
|
||||
#define M_TAU (6.28318530717958647692528676655900576)
|
||||
|
||||
// Define the legacy circle constant as well
|
||||
#ifndef M_PI
|
||||
#define M_PI (M_TAU/2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert an angle from revolutions to radians
|
||||
|
@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include "texture.h"
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
typedef struct C3D_DEPRECATED
|
||||
{
|
||||
C3D_Tex colorBuf, depthBuf;
|
||||
u32 clearColor, clearDepth;
|
||||
int depthFmt;
|
||||
} C3D_RenderBuf;
|
||||
|
||||
C3D_DEPRECATED bool C3D_RenderBufInit(C3D_RenderBuf* rb, int width, int height, int colorFmt, int depthFmt);
|
||||
C3D_DEPRECATED void C3D_RenderBufClearAsync(C3D_RenderBuf* rb);
|
||||
C3D_DEPRECATED void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags);
|
||||
C3D_DEPRECATED void C3D_RenderBufBind(C3D_RenderBuf* rb);
|
||||
C3D_DEPRECATED void C3D_RenderBufDelete(C3D_RenderBuf* rb);
|
||||
|
||||
C3D_DEPRECATED static inline void C3D_RenderBufClear(C3D_RenderBuf* rb)
|
||||
{
|
||||
C3D_RenderBufClearAsync(rb);
|
||||
gspWaitForPSC0();
|
||||
}
|
||||
|
||||
C3D_DEPRECATED static inline void C3D_RenderBufTransfer(C3D_RenderBuf* rb, u32* frameBuf, u32 flags)
|
||||
{
|
||||
C3D_RenderBufTransferAsync(rb, frameBuf, flags);
|
||||
gspWaitForPPF();
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
@ -14,9 +14,7 @@ struct C3D_RenderTarget_tag
|
||||
bool linked;
|
||||
gfxScreen_t screen;
|
||||
gfx3dSide_t side;
|
||||
C3D_ClearBits clearBits;
|
||||
u32 transferFlags;
|
||||
u32 clearColor, clearDepth;
|
||||
};
|
||||
|
||||
// Flags for C3D_FrameBegin
|
||||
@ -35,6 +33,8 @@ bool C3D_FrameDrawOn(C3D_RenderTarget* target);
|
||||
void C3D_FrameSplit(u8 flags);
|
||||
void C3D_FrameEnd(u8 flags);
|
||||
|
||||
void C3D_FrameEndHook(void (* hook)(void*), void* param);
|
||||
|
||||
float C3D_GetDrawingTime(void);
|
||||
float C3D_GetProcessingTime(void);
|
||||
|
||||
@ -62,9 +62,18 @@ public:
|
||||
C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF colorFmt, C3D_DEPTHTYPE depthFmt);
|
||||
C3D_RenderTarget* C3D_RenderTargetCreateFromTex(C3D_Tex* tex, GPU_TEXFACE face, int level, C3D_DEPTHTYPE depthFmt);
|
||||
void C3D_RenderTargetDelete(C3D_RenderTarget* target);
|
||||
void C3D_RenderTargetSetClear(C3D_RenderTarget* target, C3D_ClearBits clearBits, u32 clearColor, u32 clearDepth);
|
||||
void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags);
|
||||
|
||||
void C3D_SafeDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags);
|
||||
void C3D_SafeTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags);
|
||||
void C3D_SafeMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1);
|
||||
static inline void C3D_RenderTargetDetachOutput(C3D_RenderTarget* target)
|
||||
{
|
||||
C3D_RenderTargetSetOutput(NULL, target->screen, target->side, 0);
|
||||
}
|
||||
|
||||
static inline void C3D_RenderTargetClear(C3D_RenderTarget* target, C3D_ClearBits clearBits, u32 clearColor, u32 clearDepth)
|
||||
{
|
||||
C3D_FrameBufClear(&target->frameBuf, clearBits, clearColor, clearDepth);
|
||||
}
|
||||
|
||||
void C3D_SyncDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags);
|
||||
void C3D_SyncTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags);
|
||||
void C3D_SyncMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1);
|
||||
|
@ -4,20 +4,22 @@
|
||||
typedef struct
|
||||
{
|
||||
u16 srcRgb, srcAlpha;
|
||||
u16 opRgb, opAlpha;
|
||||
union
|
||||
{
|
||||
u32 opAll;
|
||||
struct { u32 opRgb:12, opAlpha:12; };
|
||||
};
|
||||
u16 funcRgb, funcAlpha;
|
||||
u32 color;
|
||||
u16 scaleRgb, scaleAlpha;
|
||||
} C3D_TexEnv;
|
||||
|
||||
enum
|
||||
typedef enum
|
||||
{
|
||||
C3D_RGB = BIT(0),
|
||||
C3D_Alpha = BIT(1),
|
||||
C3D_Both = C3D_RGB | C3D_Alpha,
|
||||
};
|
||||
|
||||
void TexEnv_Init(C3D_TexEnv* env);
|
||||
} C3D_TexEnvMode;
|
||||
|
||||
C3D_TexEnv* C3D_GetTexEnv(int id);
|
||||
void C3D_SetTexEnv(int id, C3D_TexEnv* env);
|
||||
@ -26,29 +28,57 @@ void C3D_DirtyTexEnv(C3D_TexEnv* env);
|
||||
void C3D_TexEnvBufUpdate(int mode, int mask);
|
||||
void C3D_TexEnvBufColor(u32 color);
|
||||
|
||||
static inline void C3D_TexEnvSrc(C3D_TexEnv* env, int mode, int s1, int s2, int s3)
|
||||
static inline void C3D_TexEnvInit(C3D_TexEnv* env)
|
||||
{
|
||||
int param = GPU_TEVSOURCES(s1, s2, s3);
|
||||
if (mode & C3D_RGB)
|
||||
env->srcRgb = GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0);
|
||||
env->srcAlpha = env->srcRgb;
|
||||
env->opAll = 0;
|
||||
env->funcRgb = GPU_REPLACE;
|
||||
env->funcAlpha = env->funcRgb;
|
||||
env->color = 0xFFFFFFFF;
|
||||
env->scaleRgb = GPU_TEVSCALE_1;
|
||||
env->scaleAlpha = GPU_TEVSCALE_1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _C3D_DEFAULT(x) = x
|
||||
#else
|
||||
#define _C3D_DEFAULT(x)
|
||||
#endif
|
||||
|
||||
static inline void C3D_TexEnvSrc(C3D_TexEnv* env, C3D_TexEnvMode mode,
|
||||
GPU_TEVSRC s1,
|
||||
GPU_TEVSRC s2 _C3D_DEFAULT(GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSRC s3 _C3D_DEFAULT(GPU_PRIMARY_COLOR))
|
||||
{
|
||||
int param = GPU_TEVSOURCES((int)s1, (int)s2, (int)s3);
|
||||
if ((int)mode & C3D_RGB)
|
||||
env->srcRgb = param;
|
||||
if (mode & C3D_Alpha)
|
||||
if ((int)mode & C3D_Alpha)
|
||||
env->srcAlpha = param;
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvOp(C3D_TexEnv* env, int mode, int o1, int o2, int o3)
|
||||
static inline void C3D_TexEnvOpRgb(C3D_TexEnv* env,
|
||||
GPU_TEVOP_RGB o1,
|
||||
GPU_TEVOP_RGB o2 _C3D_DEFAULT(GPU_TEVOP_RGB_SRC_COLOR),
|
||||
GPU_TEVOP_RGB o3 _C3D_DEFAULT(GPU_TEVOP_RGB_SRC_COLOR))
|
||||
{
|
||||
int param = GPU_TEVOPERANDS(o1, o2, o3);
|
||||
if (mode & C3D_RGB)
|
||||
env->opRgb = param;
|
||||
if (mode & C3D_Alpha)
|
||||
env->opAlpha = param;
|
||||
env->opRgb = GPU_TEVOPERANDS((int)o1, (int)o2, (int)o3);
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvFunc(C3D_TexEnv* env, int mode, int param)
|
||||
static inline void C3D_TexEnvOpAlpha(C3D_TexEnv* env,
|
||||
GPU_TEVOP_A o1,
|
||||
GPU_TEVOP_A o2 _C3D_DEFAULT(GPU_TEVOP_A_SRC_ALPHA),
|
||||
GPU_TEVOP_A o3 _C3D_DEFAULT(GPU_TEVOP_A_SRC_ALPHA))
|
||||
{
|
||||
if (mode & C3D_RGB)
|
||||
env->opAlpha = GPU_TEVOPERANDS((int)o1, (int)o2, (int)o3);
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvFunc(C3D_TexEnv* env, C3D_TexEnvMode mode, GPU_COMBINEFUNC param)
|
||||
{
|
||||
if ((int)mode & C3D_RGB)
|
||||
env->funcRgb = param;
|
||||
if (mode & C3D_Alpha)
|
||||
if ((int)mode & C3D_Alpha)
|
||||
env->funcAlpha = param;
|
||||
}
|
||||
|
||||
@ -57,10 +87,12 @@ static inline void C3D_TexEnvColor(C3D_TexEnv* env, u32 color)
|
||||
env->color = color;
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvScale(C3D_TexEnv* env, int mode, int param)
|
||||
static inline void C3D_TexEnvScale(C3D_TexEnv* env, int mode, GPU_TEVSCALE param)
|
||||
{
|
||||
if (mode & C3D_RGB)
|
||||
env->scaleRgb = param;
|
||||
if (mode & C3D_Alpha)
|
||||
env->scaleAlpha = param;
|
||||
}
|
||||
|
||||
#undef _C3D_DEFAULT
|
||||
|
@ -41,7 +41,7 @@ typedef struct
|
||||
};
|
||||
} C3D_Tex;
|
||||
|
||||
typedef struct ALIGN(8)
|
||||
typedef struct CTR_ALIGN(8)
|
||||
{
|
||||
u16 width;
|
||||
u16 height;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#ifdef _3DS
|
||||
#if defined(__3DS__) || defined(_3DS)
|
||||
#include <3ds.h>
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
|
@ -27,7 +27,6 @@ extern "C" {
|
||||
#include "c3d/fog.h"
|
||||
|
||||
#include "c3d/framebuffer.h"
|
||||
#include "c3d/renderbuffer.h" // Deprecated
|
||||
#include "c3d/renderqueue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
215
include/tex3ds.h
Normal file
215
include/tex3ds.h
Normal file
@ -0,0 +1,215 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017
|
||||
* Michael Theall (mtheall)
|
||||
*
|
||||
* This file is part of citro3d.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from the
|
||||
* use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/** @file tex3ds.h
|
||||
* @brief tex3ds support
|
||||
*/
|
||||
#pragma once
|
||||
#ifdef CITRO3D_BUILD
|
||||
#include "c3d/texture.h"
|
||||
#else
|
||||
#include <citro3d.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Subtexture
|
||||
* @note If top < bottom, the subtexture is rotated 1/4 revolution counter-clockwise
|
||||
*/
|
||||
typedef struct Tex3DS_SubTexture
|
||||
{
|
||||
u16 width; ///< Sub-texture width (pixels)
|
||||
u16 height; ///< Sub-texture height (pixels)
|
||||
float left; ///< Left u-coordinate
|
||||
float top; ///< Top v-coordinate
|
||||
float right; ///< Right u-coordinate
|
||||
float bottom; ///< Bottom v-coordinate
|
||||
} Tex3DS_SubTexture;
|
||||
|
||||
/** @brief Texture */
|
||||
typedef struct Tex3DS_Texture_s* Tex3DS_Texture;
|
||||
|
||||
/** @brief Import Tex3DS texture
|
||||
* @param[in] input Input data
|
||||
* @param[in] insize Size of the input data
|
||||
* @param[out] tex citro3d texture
|
||||
* @param[out] texcube citro3d texcube
|
||||
* @param[in] vram Whether to store textures in VRAM
|
||||
* @returns Tex3DS texture
|
||||
*/
|
||||
Tex3DS_Texture Tex3DS_TextureImport(const void* input, size_t insize, C3D_Tex* tex, C3D_TexCube* texcube, bool vram);
|
||||
|
||||
/** @brief Import Tex3DS texture
|
||||
*
|
||||
* @description
|
||||
* For example, use this if you want to import from a large file without
|
||||
* pulling the entire file into memory.
|
||||
*
|
||||
* @param[out] tex citro3d texture
|
||||
* @param[out] texcube citro3d texcube
|
||||
* @param[in] vram Whether to store textures in VRAM
|
||||
* @param[in] callback Data callback
|
||||
* @param[in] userdata User data passed to callback
|
||||
* @returns Tex3DS texture
|
||||
*/
|
||||
Tex3DS_Texture Tex3DS_TextureImportCallback(C3D_Tex* tex, C3D_TexCube* texcube, bool vram, decompressCallback callback, void* userdata);
|
||||
|
||||
/** @brief Import Tex3DS texture
|
||||
*
|
||||
* Starts reading at the current file descriptor's offset. The file
|
||||
* descriptor's position is left at the end of the decoded data. On error, the
|
||||
* file descriptor's position is indeterminate.
|
||||
*
|
||||
* @param[in] fd Open file descriptor
|
||||
* @param[out] tex citro3d texture
|
||||
* @param[out] texcube citro3d texcube
|
||||
* @param[in] vram Whether to store textures in VRAM
|
||||
* @returns Tex3DS texture
|
||||
*/
|
||||
Tex3DS_Texture Tex3DS_TextureImportFD(int fd, C3D_Tex* tex, C3D_TexCube* texcube, bool vram);
|
||||
|
||||
/** @brief Import Tex3DS texture
|
||||
*
|
||||
* Starts reading at the current file stream's offset. The file stream's
|
||||
* position is left at the end of the decoded data. On error, the file
|
||||
* stream's position is indeterminate.
|
||||
*
|
||||
* @param[in] fp Open file stream
|
||||
* @param[out] tex citro3d texture
|
||||
* @param[out] texcube citro3d texcube
|
||||
* @param[in] vram Whether to store textures in VRAM
|
||||
* @returns Tex3DS texture
|
||||
*/
|
||||
Tex3DS_Texture Tex3DS_TextureImportStdio(FILE* fp, C3D_Tex* tex, C3D_TexCube* texcube, bool vram);
|
||||
|
||||
/** @brief Get number of subtextures
|
||||
* @param[in] texture Tex3DS texture
|
||||
* @returns Number of subtextures
|
||||
*/
|
||||
size_t Tex3DS_GetNumSubTextures(const Tex3DS_Texture texture);
|
||||
|
||||
/** @brief Get subtexture
|
||||
* @param[in] texture Tex3DS texture
|
||||
* @param[in] index Subtexture index
|
||||
* @returns Subtexture info
|
||||
*/
|
||||
const Tex3DS_SubTexture* Tex3DS_GetSubTexture(const Tex3DS_Texture texture, size_t index);
|
||||
|
||||
/** @brief Check if subtexture is rotated
|
||||
* @param[in] subtex Subtexture to check
|
||||
* @returns whether subtexture is rotated
|
||||
*/
|
||||
static inline bool
|
||||
Tex3DS_SubTextureRotated(const Tex3DS_SubTexture* subtex)
|
||||
{
|
||||
return subtex->top < subtex->bottom;
|
||||
}
|
||||
|
||||
/** @brief Get bottom-left texcoords
|
||||
* @param[in] subtex Subtexture
|
||||
* @param[out] u u-coordinate
|
||||
* @param[out] v v-coordinate
|
||||
*/
|
||||
static inline void
|
||||
Tex3DS_SubTextureBottomLeft(const Tex3DS_SubTexture* subtex, float* u, float* v)
|
||||
{
|
||||
if (!Tex3DS_SubTextureRotated(subtex))
|
||||
{
|
||||
*u = subtex->left;
|
||||
*v = subtex->bottom;
|
||||
} else
|
||||
{
|
||||
*u = subtex->bottom;
|
||||
*v = subtex->left;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Get bottom-right texcoords
|
||||
* @param[in] subtex Subtexture
|
||||
* @param[out] u u-coordinate
|
||||
* @param[out] v v-coordinate
|
||||
*/
|
||||
static inline void
|
||||
Tex3DS_SubTextureBottomRight(const Tex3DS_SubTexture* subtex, float* u, float* v)
|
||||
{
|
||||
if (!Tex3DS_SubTextureRotated(subtex))
|
||||
{
|
||||
*u = subtex->right;
|
||||
*v = subtex->bottom;
|
||||
} else
|
||||
{
|
||||
*u = subtex->bottom;
|
||||
*v = subtex->right;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Get top-left texcoords
|
||||
* @param[in] subtex Subtexture
|
||||
* @param[out] u u-coordinate
|
||||
* @param[out] v v-coordinate
|
||||
*/
|
||||
static inline void
|
||||
Tex3DS_SubTextureTopLeft(const Tex3DS_SubTexture* subtex, float* u, float* v)
|
||||
{
|
||||
if (!Tex3DS_SubTextureRotated(subtex))
|
||||
{
|
||||
*u = subtex->left;
|
||||
*v = subtex->top;
|
||||
} else
|
||||
{
|
||||
*u = subtex->top;
|
||||
*v = subtex->left;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Get top-right texcoords
|
||||
* @param[in] subtex Subtexture
|
||||
* @param[out] u u-coordinate
|
||||
* @param[out] v v-coordinate
|
||||
*/
|
||||
static inline void
|
||||
Tex3DS_SubTextureTopRight(const Tex3DS_SubTexture* subtex, float* u, float* v)
|
||||
{
|
||||
if (!Tex3DS_SubTextureRotated(subtex))
|
||||
{
|
||||
*u = subtex->right;
|
||||
*v = subtex->top;
|
||||
} else
|
||||
{
|
||||
*u = subtex->top;
|
||||
*v = subtex->right;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Free Tex3DS texture
|
||||
* @param[in] texture Tex3DS texture to free
|
||||
*/
|
||||
void Tex3DS_TextureFree(Tex3DS_Texture texture);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -8,14 +8,6 @@ C3D_Context __C3D_Context;
|
||||
|
||||
static aptHookCookie hookCookie;
|
||||
|
||||
__attribute__((weak)) void C3Di_RenderQueueWaitDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
__attribute__((weak)) void C3Di_RenderQueueExit(void)
|
||||
{
|
||||
}
|
||||
|
||||
__attribute__((weak)) void C3Di_LightEnvUpdate(C3D_LightEnv* env)
|
||||
{
|
||||
(void)env;
|
||||
@ -36,6 +28,11 @@ __attribute__((weak)) void C3Di_ProcTexDirty(C3D_Context* ctx)
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void C3Di_GasUpdate(C3D_Context* ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
@ -45,22 +42,27 @@ static void C3Di_AptEventHook(APT_HookType hookType, C3D_UNUSED void* param)
|
||||
case APTHOOK_ONSUSPEND:
|
||||
{
|
||||
C3Di_RenderQueueWaitDone();
|
||||
C3Di_RenderQueueDisableVBlank();
|
||||
break;
|
||||
}
|
||||
case APTHOOK_ONRESTORE:
|
||||
{
|
||||
C3Di_RenderQueueEnableVBlank();
|
||||
ctx->flags |= C3DiF_AttrInfo | C3DiF_BufInfo | C3DiF_Effect | C3DiF_FrameBuf
|
||||
| C3DiF_Viewport | C3DiF_Scissor | C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode
|
||||
| C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv;
|
||||
| C3DiF_TexAll | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_LightEnv | C3DiF_Gas;
|
||||
|
||||
C3Di_DirtyUniforms(GPU_VERTEX_SHADER);
|
||||
C3Di_DirtyUniforms(GPU_GEOMETRY_SHADER);
|
||||
|
||||
ctx->fixedAttribDirty |= ctx->fixedAttribEverDirty;
|
||||
ctx->gasFlags |= C3DiG_BeginAcc | C3DiG_AccStage | C3DiG_RenderStage;
|
||||
|
||||
C3D_LightEnv* env = ctx->lightEnv;
|
||||
if (ctx->fogLut)
|
||||
ctx->flags |= C3DiF_FogLut;
|
||||
if (ctx->gasLut)
|
||||
ctx->flags |= C3DiF_GasLut;
|
||||
if (env)
|
||||
C3Di_LightEnvDirty(env);
|
||||
C3Di_ProcTexDirty(ctx);
|
||||
@ -94,10 +96,6 @@ bool C3D_Init(size_t cmdBufSize)
|
||||
return false;
|
||||
}
|
||||
|
||||
GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0);
|
||||
GX_BindQueue(&ctx->gxQueue);
|
||||
gxCmdQueueRun(&ctx->gxQueue);
|
||||
|
||||
ctx->flags = C3DiF_Active | C3DiF_TexEnvBuf | C3DiF_TexEnvAll | C3DiF_Effect | C3DiF_TexStatus | C3DiF_TexAll;
|
||||
|
||||
// TODO: replace with direct struct access
|
||||
@ -124,11 +122,12 @@ bool C3D_Init(size_t cmdBufSize)
|
||||
ctx->tex[i] = NULL;
|
||||
|
||||
for (i = 0; i < 6; i ++)
|
||||
TexEnv_Init(&ctx->texEnv[i]);
|
||||
C3D_TexEnvInit(&ctx->texEnv[i]);
|
||||
|
||||
ctx->fixedAttribDirty = 0;
|
||||
ctx->fixedAttribEverDirty = 0;
|
||||
|
||||
C3Di_RenderQueueInit();
|
||||
aptHook(&hookCookie, C3Di_AptEventHook, NULL);
|
||||
|
||||
return true;
|
||||
@ -161,12 +160,6 @@ void C3Di_UpdateContext(void)
|
||||
int i;
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (ctx->flags & C3DiF_Program)
|
||||
{
|
||||
shaderProgramConfigure(ctx->program, (ctx->flags & C3DiF_VshCode) != 0, (ctx->flags & C3DiF_GshCode) != 0);
|
||||
ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode);
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_FrameBuf)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_FrameBuf;
|
||||
@ -192,6 +185,12 @@ void C3Di_UpdateContext(void)
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, ctx->scissor, 3);
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_Program)
|
||||
{
|
||||
shaderProgramConfigure(ctx->program, (ctx->flags & C3DiF_VshCode) != 0, (ctx->flags & C3DiF_GshCode) != 0);
|
||||
ctx->flags &= ~(C3DiF_Program | C3DiF_VshCode | C3DiF_GshCode);
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_AttrInfo)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_AttrInfo;
|
||||
@ -233,9 +232,14 @@ void C3Di_UpdateContext(void)
|
||||
if (ctx->flags & C3DiF_TexStatus)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_TexStatus;
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, ctx->texConfig);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0xB, ctx->texConfig);
|
||||
// Clear texture cache if requested *after* configuring texture units
|
||||
if (ctx->texConfig & BIT(16))
|
||||
{
|
||||
ctx->texConfig &= ~BIT(16);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_TEXUNIT_CONFIG, 0x4, BIT(16));
|
||||
}
|
||||
GPUCMD_AddWrite(GPUREG_TEXUNIT0_SHADOW, ctx->texShadow);
|
||||
ctx->texConfig &= ~BIT(16); // Remove clear-texture-cache flag
|
||||
}
|
||||
|
||||
if (ctx->flags & (C3DiF_ProcTex | C3DiF_ProcTexColorLut | C3DiF_ProcTexLutAll))
|
||||
@ -249,7 +253,7 @@ void C3Di_UpdateContext(void)
|
||||
GPUCMD_AddWrite(GPUREG_FOG_COLOR, ctx->fogClr);
|
||||
}
|
||||
|
||||
if (ctx->flags & C3DiF_FogLut)
|
||||
if ((ctx->flags & C3DiF_FogLut) && (ctx->texEnvBuf&7) != GPU_NO_FOG)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_FogLut;
|
||||
if (ctx->fogLut)
|
||||
@ -259,6 +263,9 @@ void C3Di_UpdateContext(void)
|
||||
}
|
||||
}
|
||||
|
||||
if ((ctx->texEnvBuf&7) == GPU_GAS)
|
||||
C3Di_GasUpdate(ctx);
|
||||
|
||||
if (ctx->flags & C3DiF_TexEnvAll)
|
||||
{
|
||||
for (i = 0; i < 6; i ++)
|
||||
@ -320,25 +327,6 @@ bool C3Di_SplitFrame(u32** pBuf, u32* pSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
void C3D_FlushAsync(void)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
u32* cmdBuf;
|
||||
u32 cmdBufSize;
|
||||
C3Di_SplitFrame(&cmdBuf, &cmdBufSize);
|
||||
GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0);
|
||||
|
||||
//take advantage of GX_FlushCacheRegions to flush gsp heap
|
||||
extern u32 __ctru_linear_heap;
|
||||
extern u32 __ctru_linear_heap_size;
|
||||
GX_FlushCacheRegions(cmdBuf, cmdBufSize*4, (u32 *) __ctru_linear_heap, __ctru_linear_heap_size, NULL, 0);
|
||||
GX_ProcessCommandList(cmdBuf, cmdBufSize*4, 0x0);
|
||||
}
|
||||
|
||||
float C3D_GetCmdBufUsage(void)
|
||||
{
|
||||
return C3Di_GetContext()->cmdBufUsage;
|
||||
@ -351,11 +339,8 @@ void C3D_Fini(void)
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
C3Di_RenderQueueExit();
|
||||
aptUnhook(&hookCookie);
|
||||
gxCmdQueueStop(&ctx->gxQueue);
|
||||
gxCmdQueueWait(&ctx->gxQueue, -1);
|
||||
GX_BindQueue(NULL);
|
||||
C3Di_RenderQueueExit();
|
||||
free(ctx->gxQueue.entries);
|
||||
linearFree(ctx->cmdBuf);
|
||||
ctx->flags = 0;
|
||||
|
@ -93,6 +93,7 @@ void C3Di_EffectBind(C3D_Effect* e)
|
||||
GPUCMD_AddWrite(GPUREG_FACECULLING_CONFIG, e->cullMode & 0x3);
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHMAP_SCALE, (u32*)&e->zScale, 2);
|
||||
GPUCMD_AddIncrementalWrites(GPUREG_FRAGOP_ALPHA_TEST, (u32*)&e->alphaTest, 4);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_GAS_DELTAZ_DEPTH, 0x8, (u32)GPU_MAKEGASDEPTHFUNC((e->depthTest>>4)&7) << 24);
|
||||
GPUCMD_AddWrite(GPUREG_BLEND_COLOR, e->blendClr);
|
||||
GPUCMD_AddWrite(GPUREG_BLEND_FUNC, e->alphaBlend);
|
||||
GPUCMD_AddWrite(GPUREG_LOGIC_OP, e->clrLogicOp);
|
||||
|
184
source/gas.c
Normal file
184
source/gas.c
Normal file
@ -0,0 +1,184 @@
|
||||
#include "internal.h"
|
||||
|
||||
static inline u32 calc_diff(u32 a, u32 b, int pos)
|
||||
{
|
||||
float fa = ((a>>pos)&0xFF)/255.0f;
|
||||
float fb = ((b>>pos)&0xFF)/255.0f;
|
||||
float x = fb-fa;
|
||||
u32 diff = 0;
|
||||
if (x < 0)
|
||||
{
|
||||
diff = 0x80;
|
||||
x = -x;
|
||||
}
|
||||
diff |= (u32)(x*0x7F);
|
||||
return diff<<pos;
|
||||
}
|
||||
|
||||
static inline u32 conv_u8(float x, int pos)
|
||||
{
|
||||
if (x < 0.0f) x = 0.0f;
|
||||
else if (x > 1.0f) x = 1.0f;
|
||||
return ((u32)x*255)<<pos;
|
||||
}
|
||||
|
||||
static inline u32 color_diff(u32 a, u32 b)
|
||||
{
|
||||
return calc_diff(a,b,0) | calc_diff(a,b,8) | calc_diff(a,b,16);
|
||||
}
|
||||
|
||||
void GasLut_FromArray(C3D_GasLut* lut, const u32 data[9])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= 8; i ++)
|
||||
{
|
||||
if (i < 8)
|
||||
lut->color[i] = data[i];
|
||||
if (i > 0)
|
||||
lut->diff[i-1] = color_diff(data[i-1], data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void C3D_GasBeginAcc(void)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->gasFlags |= C3DiG_BeginAcc;
|
||||
}
|
||||
|
||||
void C3D_GasDeltaZ(float value)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasDeltaZ = (u32)(value*0x100);
|
||||
ctx->gasFlags |= C3DiG_AccStage;
|
||||
}
|
||||
|
||||
void C3D_GasAccMax(float value)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasAccMax = f32tof16(1.0f / value);
|
||||
ctx->gasFlags |= C3DiG_SetAccMax;
|
||||
}
|
||||
|
||||
void C3D_GasAttn(float value)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasAttn = f32tof16(value);
|
||||
ctx->gasFlags |= C3DiG_RenderStage;
|
||||
}
|
||||
|
||||
void C3D_GasLightPlanar(float min, float max, float attn)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasLightXY = conv_u8(min,0) | conv_u8(max,8) | conv_u8(attn,16);
|
||||
ctx->gasFlags |= C3DiG_RenderStage;
|
||||
}
|
||||
|
||||
void C3D_GasLightView(float min, float max, float attn)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasLightZ = conv_u8(min,0) | conv_u8(max,8) | conv_u8(attn,16);
|
||||
ctx->gasFlags |= C3DiG_RenderStage;
|
||||
}
|
||||
|
||||
void C3D_GasLightDirection(float dotp)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasLightZColor &= ~0xFF;
|
||||
ctx->gasLightZColor |= conv_u8(dotp,0);
|
||||
ctx->gasFlags |= C3DiG_RenderStage;
|
||||
}
|
||||
|
||||
void C3D_GasLutInput(GPU_GASLUTINPUT input)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
ctx->flags |= C3DiF_Gas;
|
||||
ctx->gasLightZColor &= ~0x100;
|
||||
ctx->gasLightZColor |= (input&1)<<8;
|
||||
ctx->gasFlags |= C3DiG_RenderStage;
|
||||
}
|
||||
|
||||
void C3D_GasLutBind(C3D_GasLut* lut)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
if (lut)
|
||||
{
|
||||
ctx->flags |= C3DiF_GasLut;
|
||||
ctx->gasLut = lut;
|
||||
} else
|
||||
ctx->flags &= ~C3DiF_GasLut;
|
||||
}
|
||||
|
||||
void C3Di_GasUpdate(C3D_Context* ctx)
|
||||
{
|
||||
if (ctx->flags & C3DiF_Gas)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_Gas;
|
||||
u32 gasFlags = ctx->gasFlags;
|
||||
ctx->gasFlags = 0;
|
||||
|
||||
if (gasFlags & C3DiG_BeginAcc)
|
||||
GPUCMD_AddMaskedWrite(GPUREG_GAS_ACCMAX_FEEDBACK, 0x3, 0);
|
||||
if (gasFlags & C3DiG_AccStage)
|
||||
GPUCMD_AddMaskedWrite(GPUREG_GAS_DELTAZ_DEPTH, 0x7, ctx->gasDeltaZ);
|
||||
if (gasFlags & C3DiG_SetAccMax)
|
||||
GPUCMD_AddWrite(GPUREG_GAS_ACCMAX, ctx->gasAccMax);
|
||||
if (gasFlags & C3DiG_RenderStage)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_GAS_ATTENUATION, ctx->gasAttn);
|
||||
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_XY, ctx->gasLightXY);
|
||||
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_Z, ctx->gasLightZ);
|
||||
GPUCMD_AddWrite(GPUREG_GAS_LIGHT_Z_COLOR, ctx->gasLightZColor);
|
||||
}
|
||||
}
|
||||
if (ctx->flags & C3DiF_GasLut)
|
||||
{
|
||||
ctx->flags &= ~C3DiF_GasLut;
|
||||
if (ctx->gasLut)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_GAS_LUT_INDEX, 0);
|
||||
GPUCMD_AddWrites(GPUREG_GAS_LUT_DATA, (u32*)ctx->gasLut, 16);
|
||||
}
|
||||
}
|
||||
}
|
@ -52,6 +52,12 @@ typedef struct
|
||||
u32 fogClr;
|
||||
C3D_FogLut* fogLut;
|
||||
|
||||
u16 gasAttn, gasAccMax;
|
||||
u32 gasLightXY, gasLightZ, gasLightZColor;
|
||||
u32 gasDeltaZ : 24;
|
||||
u32 gasFlags : 8;
|
||||
C3D_GasLut* gasLut;
|
||||
|
||||
C3D_ProcTex* procTex;
|
||||
C3D_ProcTexLut* procTexLut[3];
|
||||
C3D_ProcTexColorLut* procTexColorLut;
|
||||
@ -83,6 +89,8 @@ enum
|
||||
C3DiF_ProcTex = BIT(15),
|
||||
C3DiF_ProcTexColorLut = BIT(16),
|
||||
C3DiF_FogLut = BIT(17),
|
||||
C3DiF_Gas = BIT(18),
|
||||
C3DiF_GasLut = BIT(19),
|
||||
|
||||
#define C3DiF_ProcTexLut(n) BIT(20+(n))
|
||||
C3DiF_ProcTexLutAll = 7 << 20,
|
||||
@ -92,6 +100,14 @@ enum
|
||||
C3DiF_TexEnvAll = 0x3F << 26,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
C3DiG_BeginAcc = BIT(0),
|
||||
C3DiG_AccStage = BIT(1),
|
||||
C3DiG_SetAccMax = BIT(2),
|
||||
C3DiG_RenderStage = BIT(3),
|
||||
};
|
||||
|
||||
static inline C3D_Context* C3Di_GetContext(void)
|
||||
{
|
||||
extern C3D_Context __C3D_Context;
|
||||
@ -108,6 +124,18 @@ static inline bool C3Di_TexIs2D(C3D_Tex* tex)
|
||||
return !typeIsCube(C3D_TexGetType(tex));
|
||||
}
|
||||
|
||||
static inline bool addrIsVRAM(const void* addr)
|
||||
{
|
||||
u32 vaddr = (u32)addr;
|
||||
return vaddr >= OS_VRAM_VADDR && vaddr < OS_VRAM_VADDR + OS_VRAM_SIZE;
|
||||
}
|
||||
|
||||
static inline vramAllocPos addrGetVRAMBank(const void* addr)
|
||||
{
|
||||
u32 vaddr = (u32)addr;
|
||||
return vaddr < OS_VRAM_VADDR + OS_VRAM_SIZE/2 ? VRAM_ALLOC_A : VRAM_ALLOC_B;
|
||||
}
|
||||
|
||||
void C3Di_UpdateContext(void);
|
||||
void C3Di_AttrInfoBind(C3D_AttrInfo* info);
|
||||
void C3Di_BufInfoBind(C3D_BufInfo* info);
|
||||
@ -115,6 +143,7 @@ void C3Di_FrameBufBind(C3D_FrameBuf* fb);
|
||||
void C3Di_TexEnvBind(int id, C3D_TexEnv* env);
|
||||
void C3Di_SetTex(int unit, C3D_Tex* tex);
|
||||
void C3Di_EffectBind(C3D_Effect* effect);
|
||||
void C3Di_GasUpdate(C3D_Context* ctx);
|
||||
|
||||
void C3Di_LightMtlBlend(C3D_Light* light);
|
||||
|
||||
@ -123,3 +152,9 @@ void C3Di_LoadShaderUniforms(shaderInstance_s* si);
|
||||
void C3Di_ClearShaderUniforms(GPU_SHADER_TYPE type);
|
||||
|
||||
bool C3Di_SplitFrame(u32** pBuf, u32* pSize);
|
||||
|
||||
void C3Di_RenderQueueInit(void);
|
||||
void C3Di_RenderQueueExit(void);
|
||||
void C3Di_RenderQueueWaitDone(void);
|
||||
void C3Di_RenderQueueEnableVBlank(void);
|
||||
void C3Di_RenderQueueDisableVBlank(void);
|
||||
|
@ -250,6 +250,14 @@ void C3D_LightEnvBumpSel(C3D_LightEnv* env, int texUnit)
|
||||
env->flags |= C3DF_LightEnv_Dirty;
|
||||
}
|
||||
|
||||
void C3D_LightEnvBumpNormalZ(C3D_LightEnv *env, bool usez) {
|
||||
if (usez)
|
||||
env->conf.config[0] |= BIT(30);
|
||||
else
|
||||
env->conf.config[0] &= ~BIT(30);
|
||||
env->flags |= C3DF_LightEnv_Dirty;
|
||||
}
|
||||
|
||||
void C3D_LightEnvShadowMode(C3D_LightEnv* env, u32 mode)
|
||||
{
|
||||
mode &= 0xF<<16;
|
||||
|
@ -2,54 +2,61 @@
|
||||
|
||||
C3D_FQuat Quat_FromMtx(const C3D_Mtx* m)
|
||||
{
|
||||
//Taken from Gamasutra:
|
||||
//http://www.gamasutra.com/view/feature/131686/rotating_objects_using_quaternions.php
|
||||
//Expanded upon from:
|
||||
//http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
||||
// Original algorithm taken from here (with some optimizations):
|
||||
// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
|
||||
// Layout of the algorithm:
|
||||
// First, we select a large (non-zero!) component "P" in the output quaternion (q)
|
||||
// (we can test this just by looking at the diagonal of the matrix)
|
||||
// Second, we calculate q' which is our desired output quaternion (q) scaled by 4P
|
||||
// (this can be done with simple additions; the 4P factor is large and non-zero thanks to above)
|
||||
// Third, we normalize q' to finally obtain q
|
||||
// (this will work because normalize(kq) = q for any k scalar and q unit quaternion)
|
||||
|
||||
//Variables we need.
|
||||
float trace, sqrtTrace;
|
||||
C3D_FQuat q;
|
||||
C3D_FVec diagonal = FVec4_New(m->r[0].x, m->r[1].y, m->r[2].z, 1.0f);
|
||||
|
||||
//Check the main diagonal of the passed-in matrix for positive/negative signs.
|
||||
trace = m->r[0].x + m->r[1].y + m->r[2].z;
|
||||
if (trace > 0.0f)
|
||||
// Check if x^2 + y^2 >= z^2 + w^2
|
||||
if (diagonal.z <= 0.0f)
|
||||
{
|
||||
//Diagonal is positive.
|
||||
sqrtTrace = sqrtf(trace + 1.0f);
|
||||
q.w = sqrtTrace / 2.0f;
|
||||
sqrtTrace = 0.5 / sqrtTrace;
|
||||
q.x = (m->r[1].z - m->r[2].y) * sqrtTrace;
|
||||
q.y = (m->r[2].x - m->r[0].z) * sqrtTrace;
|
||||
q.z = (m->r[0].y - m->r[1].x) * sqrtTrace;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Diagonal is negative or equals to zero. We need to identify which major diagonal element has the greatest value.
|
||||
if (m->r[0].x > m->r[1].y && m->r[0].x > m->r[2].z)
|
||||
// Check if |x| >= |y|
|
||||
if (diagonal.x >= diagonal.y)
|
||||
{
|
||||
sqrtTrace = 2.0f * sqrtf(1.0f + m->r[0].x - m->r[1].y - m->r[2].z);
|
||||
q.w = (m->r[2].y - m->r[1].z) / sqrtTrace;
|
||||
q.x = 0.25f * sqrtTrace;
|
||||
q.y = (m->r[0].y - m->r[1].x) / sqrtTrace;
|
||||
q.z = (m->r[0].z - m->r[2].x) / sqrtTrace;
|
||||
}
|
||||
else if (m->r[1].y > m->r[2].z)
|
||||
{
|
||||
sqrtTrace = 2.0f * sqrtf(1.0f + m->r[1].y - m->r[0].x - m->r[2].z);
|
||||
q.w = (m->r[0].z - m->r[2].x) / sqrtTrace;
|
||||
q.x = (m->r[0].y - m->r[1].x) / sqrtTrace;
|
||||
q.y = 0.25f * sqrtTrace;
|
||||
q.z = (m->r[1].z - m->r[2].y) / sqrtTrace;
|
||||
// X case
|
||||
q.x = diagonal.w + diagonal.x - diagonal.y - diagonal.z;
|
||||
q.y = m->r[1].x + m->r[0].y;
|
||||
q.z = m->r[2].x + m->r[0].z;
|
||||
q.w = m->r[2].y - m->r[1].z;
|
||||
}
|
||||
else
|
||||
{
|
||||
sqrtTrace = 2.0f * sqrtf(1.0f + m->r[2].z - m->r[0].x - m->r[1].y);
|
||||
q.w = (m->r[1].x - m->r[0].y) / sqrtTrace;
|
||||
q.x = (m->r[0].z - m->r[2].x) / sqrtTrace;
|
||||
q.y = (m->r[1].z - m->r[2].y) / sqrtTrace;
|
||||
q.z = 0.25f * sqrtTrace;
|
||||
// Y case
|
||||
q.x = m->r[1].x + m->r[0].y;
|
||||
q.y = diagonal.w - diagonal.x + diagonal.y - diagonal.z;
|
||||
q.z = m->r[2].y + m->r[1].z;
|
||||
q.w = m->r[0].z - m->r[2].x;
|
||||
}
|
||||
}
|
||||
return q;
|
||||
else
|
||||
{
|
||||
// Check if |z| >= |w|
|
||||
if (-diagonal.x >= diagonal.y)
|
||||
{
|
||||
// Z case
|
||||
q.x = m->r[2].x + m->r[0].z;
|
||||
q.y = m->r[2].y + m->r[1].z;
|
||||
q.z = diagonal.w - diagonal.x - diagonal.y + diagonal.z;
|
||||
q.w = m->r[1].x - m->r[0].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// W case
|
||||
q.x = m->r[2].y - m->r[1].z;
|
||||
q.y = m->r[0].z - m->r[2].x;
|
||||
q.z = m->r[1].x - m->r[0].y;
|
||||
q.w = diagonal.w + diagonal.x + diagonal.y + diagonal.z;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the quaternion
|
||||
return Quat_Normalize(q);
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
#define CITRO3D_NO_DEPRECATION
|
||||
#include "internal.h"
|
||||
#include <c3d/base.h>
|
||||
#include <c3d/renderbuffer.h>
|
||||
|
||||
static const u8 colorFmtSizes[] = {2,1,0,0,0};
|
||||
static const u8 depthFmtSizes[] = {0,0,1,2};
|
||||
|
||||
static inline u16 getColorBufFillFlag(int fmt)
|
||||
{
|
||||
if (fmt < 0) return 0;
|
||||
return BIT(0) | ((u32)colorFmtSizes[fmt] << 8);
|
||||
}
|
||||
|
||||
static inline u16 getDepthBufFillFlag(int fmt)
|
||||
{
|
||||
if (fmt < 0) return 0;
|
||||
return BIT(0) | ((u32)depthFmtSizes[fmt] << 8);
|
||||
}
|
||||
|
||||
static inline GPU_TEXCOLOR colorFmtFromDepthFmt(int fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case GPU_RB_DEPTH16:
|
||||
return GPU_RGB565;
|
||||
case GPU_RB_DEPTH24:
|
||||
return GPU_RGB8;
|
||||
case GPU_RB_DEPTH24_STENCIL8:
|
||||
return GPU_RGBA8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool C3D_RenderBufInit(C3D_RenderBuf* rb, int width, int height, int colorFmt, int depthFmt)
|
||||
{
|
||||
memset(rb, 0, sizeof(*rb));
|
||||
|
||||
rb->depthFmt = depthFmt;
|
||||
rb->clearColor = rb->clearDepth = 0;
|
||||
|
||||
if (colorFmt < 0)
|
||||
return false;
|
||||
if (!C3D_TexInitVRAM(&rb->colorBuf, width, height, colorFmt))
|
||||
return false;
|
||||
|
||||
if (depthFmt >= 0)
|
||||
{
|
||||
if (!C3D_TexInitVRAM(&rb->depthBuf, width, height, colorFmtFromDepthFmt(depthFmt)))
|
||||
{
|
||||
C3D_TexDelete(&rb->colorBuf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void C3D_RenderBufClearAsync(C3D_RenderBuf* rb)
|
||||
{
|
||||
GX_MemoryFill(
|
||||
(u32*)rb->colorBuf.data, rb->clearColor, (u32*)((u8*)rb->colorBuf.data+rb->colorBuf.size), getColorBufFillFlag(rb->colorBuf.fmt),
|
||||
(u32*)rb->depthBuf.data, rb->clearDepth, (u32*)((u8*)rb->depthBuf.data+rb->depthBuf.size), getDepthBufFillFlag(rb->depthFmt));
|
||||
}
|
||||
|
||||
void C3D_RenderBufTransferAsync(C3D_RenderBuf* rb, u32* frameBuf, u32 flags)
|
||||
{
|
||||
u32 dim = GX_BUFFER_DIM((u32)rb->colorBuf.width, (u32)rb->colorBuf.height);
|
||||
GX_DisplayTransfer((u32*)rb->colorBuf.data, dim, frameBuf, dim, flags);
|
||||
}
|
||||
|
||||
void C3D_RenderBufBind(C3D_RenderBuf* rb)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
C3D_FrameBuf* fb = &ctx->fb;
|
||||
ctx->flags |= C3DiF_FrameBuf;
|
||||
fb->colorBuf = rb->colorBuf.data;
|
||||
fb->depthBuf = rb->depthBuf.data;
|
||||
fb->width = rb->colorBuf.width;
|
||||
fb->height = rb->colorBuf.height;
|
||||
fb->colorFmt = (GPU_COLORBUF)rb->colorBuf.fmt;
|
||||
fb->depthFmt = rb->depthFmt >= 0 ? (GPU_DEPTHBUF)rb->depthFmt : GPU_RB_DEPTH16;
|
||||
fb->block32 = false;
|
||||
fb->colorMask = 0xF;
|
||||
fb->depthMask = 0x2;
|
||||
C3D_SetViewport(0, 0, rb->colorBuf.width, rb->colorBuf.height);
|
||||
}
|
||||
|
||||
void C3D_RenderBufDelete(C3D_RenderBuf* rb)
|
||||
{
|
||||
C3D_TexDelete(&rb->colorBuf);
|
||||
C3D_TexDelete(&rb->depthBuf);
|
||||
}
|
@ -8,19 +8,15 @@ static C3D_RenderTarget *linkedTarget[3];
|
||||
|
||||
static TickCounter gpuTime, cpuTime;
|
||||
|
||||
#define STAGE_HAS_TRANSFER(n) BIT(0+(n))
|
||||
#define STAGE_HAS_ANY_TRANSFER (7<<0)
|
||||
#define STAGE_NEED_TRANSFER(n) BIT(3+(n))
|
||||
#define STAGE_NEED_TOP_TRANSFER (STAGE_NEED_TRANSFER(0)|STAGE_NEED_TRANSFER(1))
|
||||
#define STAGE_NEED_BOT_TRANSFER STAGE_NEED_TRANSFER(2)
|
||||
#define STAGE_WAIT_TRANSFER BIT(6)
|
||||
|
||||
static bool initialized;
|
||||
static bool inFrame, inSafeTransfer, measureGpuTime;
|
||||
static u8 frameStage;
|
||||
static bool needSwapTop, needSwapBot, isTopStereo;
|
||||
static float framerate = 60.0f;
|
||||
static float framerateCounter[2] = { 60.0f, 60.0f };
|
||||
static u32 frameCounter[2];
|
||||
static void (* frameEndCb)(void*);
|
||||
static void* frameEndCbData;
|
||||
|
||||
static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target);
|
||||
|
||||
static bool framerateLimit(int id)
|
||||
{
|
||||
@ -35,50 +31,12 @@ static bool framerateLimit(int id)
|
||||
|
||||
static void onVBlank0(C3D_UNUSED void* unused)
|
||||
{
|
||||
if (frameStage & STAGE_NEED_TOP_TRANSFER)
|
||||
{
|
||||
C3D_RenderTarget *left = linkedTarget[0], *right = linkedTarget[1];
|
||||
if (left && !(frameStage&STAGE_NEED_TRANSFER(0)))
|
||||
left = NULL;
|
||||
if (right && !(frameStage&STAGE_NEED_TRANSFER(1)))
|
||||
right = NULL;
|
||||
if (gfxIs3D() && !right)
|
||||
right = left;
|
||||
|
||||
frameStage &= ~STAGE_NEED_TOP_TRANSFER;
|
||||
if (left || right)
|
||||
{
|
||||
frameStage |= STAGE_WAIT_TRANSFER;
|
||||
if (left)
|
||||
C3D_FrameBufTransfer(&left->frameBuf, GFX_TOP, GFX_LEFT, left->transferFlags);
|
||||
if (right)
|
||||
C3D_FrameBufTransfer(&right->frameBuf, GFX_TOP, GFX_RIGHT, right->transferFlags);
|
||||
if (left && left->clearBits)
|
||||
C3D_FrameBufClear(&left->frameBuf, left->clearBits, left->clearColor, left->clearDepth);
|
||||
if (right && right != left && right->clearBits)
|
||||
C3D_FrameBufClear(&right->frameBuf, right->clearBits, right->clearColor, right->clearDepth);
|
||||
gfxConfigScreen(GFX_TOP, false);
|
||||
}
|
||||
}
|
||||
if (framerateLimit(0))
|
||||
frameCounter[0]++;
|
||||
}
|
||||
|
||||
static void onVBlank1(C3D_UNUSED void* unused)
|
||||
{
|
||||
if (frameStage & STAGE_NEED_BOT_TRANSFER)
|
||||
{
|
||||
frameStage &= ~STAGE_NEED_BOT_TRANSFER;
|
||||
C3D_RenderTarget* target = linkedTarget[2];
|
||||
if (target)
|
||||
{
|
||||
frameStage |= STAGE_WAIT_TRANSFER;
|
||||
C3D_FrameBufTransfer(&target->frameBuf, GFX_BOTTOM, GFX_LEFT, target->transferFlags);
|
||||
if (target->clearBits)
|
||||
C3D_FrameBufClear(&target->frameBuf, target->clearBits, target->clearColor, target->clearDepth);
|
||||
gfxConfigScreen(GFX_BOTTOM, false);
|
||||
}
|
||||
}
|
||||
if (framerateLimit(1))
|
||||
frameCounter[1]++;
|
||||
}
|
||||
@ -99,12 +57,18 @@ static void onQueueFinish(gxCmdQueue_s* queue)
|
||||
gxCmdQueueClear(queue);
|
||||
}
|
||||
}
|
||||
else if (frameStage & STAGE_WAIT_TRANSFER)
|
||||
frameStage &= ~STAGE_WAIT_TRANSFER;
|
||||
else
|
||||
{
|
||||
u8 needs = frameStage & STAGE_HAS_ANY_TRANSFER;
|
||||
frameStage = (frameStage&~STAGE_HAS_ANY_TRANSFER) | (needs<<3);
|
||||
if (needSwapTop)
|
||||
{
|
||||
gfxScreenSwapBuffers(GFX_TOP, isTopStereo);
|
||||
needSwapTop = false;
|
||||
}
|
||||
if (needSwapBot)
|
||||
{
|
||||
gfxScreenSwapBuffers(GFX_BOTTOM, false);
|
||||
needSwapBot = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,72 +94,60 @@ static bool C3Di_WaitAndClearQueue(s64 timeout)
|
||||
gxCmdQueue_s* queue = &C3Di_GetContext()->gxQueue;
|
||||
if (!gxCmdQueueWait(queue, timeout))
|
||||
return false;
|
||||
if (timeout==0 && frameStage)
|
||||
return false;
|
||||
while (frameStage)
|
||||
gspWaitForAnyEvent();
|
||||
gxCmdQueueStop(queue);
|
||||
gxCmdQueueClear(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void C3Di_RenderQueueInit(void)
|
||||
void C3Di_RenderQueueEnableVBlank(void)
|
||||
{
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, onVBlank0, NULL, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, onVBlank1, NULL, false);
|
||||
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, onQueueFinish, NULL);
|
||||
}
|
||||
|
||||
static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target);
|
||||
void C3Di_RenderQueueDisableVBlank(void)
|
||||
{
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, NULL, NULL, false);
|
||||
}
|
||||
|
||||
void C3Di_RenderQueueInit(void)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
C3Di_RenderQueueEnableVBlank();
|
||||
|
||||
GX_BindQueue(&ctx->gxQueue);
|
||||
gxCmdQueueSetCallback(&ctx->gxQueue, onQueueFinish, NULL);
|
||||
gxCmdQueueRun(&ctx->gxQueue);
|
||||
}
|
||||
|
||||
void C3Di_RenderQueueExit(void)
|
||||
{
|
||||
int i;
|
||||
C3D_RenderTarget *a, *next;
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL);
|
||||
GX_BindQueue(NULL);
|
||||
|
||||
C3Di_RenderQueueDisableVBlank();
|
||||
|
||||
for (i = 0; i < 3; i ++)
|
||||
linkedTarget[i] = NULL;
|
||||
|
||||
for (a = firstTarget; a; a = next)
|
||||
{
|
||||
next = a->next;
|
||||
C3Di_RenderTargetDestroy(a);
|
||||
}
|
||||
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, NULL, NULL, false);
|
||||
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL);
|
||||
|
||||
for (i = 0; i < 3; i ++)
|
||||
linkedTarget[i] = NULL;
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
void C3Di_RenderQueueWaitDone(void)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
}
|
||||
|
||||
static bool checkRenderQueueInit(void)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return false;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
C3Di_RenderQueueInit();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float C3D_FrameRate(float fps)
|
||||
{
|
||||
float old = framerate;
|
||||
@ -210,13 +162,17 @@ float C3D_FrameRate(float fps)
|
||||
|
||||
bool C3D_FrameBegin(u8 flags)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
if (inFrame) return false;
|
||||
|
||||
if (flags & C3D_FRAME_SYNCDRAW)
|
||||
C3D_FrameSync();
|
||||
if (!C3Di_WaitAndClearQueue((flags & C3D_FRAME_NONBLOCK) ? 0 : -1))
|
||||
return false;
|
||||
|
||||
inFrame = true;
|
||||
osTickCounterStart(&cpuTime);
|
||||
GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -241,10 +197,15 @@ void C3D_FrameSplit(u8 flags)
|
||||
void C3D_FrameEnd(u8 flags)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
if (!inFrame) return;
|
||||
|
||||
if (frameEndCb)
|
||||
frameEndCb(frameEndCbData);
|
||||
|
||||
C3D_FrameSplit(flags);
|
||||
inFrame = false;
|
||||
GPUCMD_SetBuffer(NULL, 0, 0);
|
||||
osTickCounterUpdate(&cpuTime);
|
||||
inFrame = false;
|
||||
|
||||
// Flush the entire linear memory if the user did not explicitly mandate to flush the command list
|
||||
if (!(flags & GX_CMDLIST_FLUSH))
|
||||
@ -256,29 +217,35 @@ void C3D_FrameEnd(u8 flags)
|
||||
|
||||
int i;
|
||||
C3D_RenderTarget* target;
|
||||
isTopStereo = false;
|
||||
for (i = 2; i >= 0; i --)
|
||||
{
|
||||
target = linkedTarget[i];
|
||||
if (!target || !target->used)
|
||||
continue;
|
||||
target->used = false;
|
||||
frameStage |= STAGE_HAS_TRANSFER(i);
|
||||
C3D_FrameBufTransfer(&target->frameBuf, target->screen, target->side, target->transferFlags);
|
||||
if (target->screen == GFX_TOP)
|
||||
{
|
||||
needSwapTop = true;
|
||||
if (target->side == GFX_RIGHT)
|
||||
isTopStereo = true;
|
||||
}
|
||||
else if (target->screen == GFX_BOTTOM)
|
||||
needSwapBot = true;
|
||||
}
|
||||
|
||||
for (target = firstTarget; target; target = target->next)
|
||||
{
|
||||
if (!target->used || !target->clearBits)
|
||||
continue;
|
||||
target->used = false;
|
||||
C3D_FrameBufClear(&target->frameBuf, target->clearBits, target->clearColor, target->clearDepth);
|
||||
}
|
||||
|
||||
GPUCMD_SetBuffer(ctx->cmdBuf, ctx->cmdBufSize, 0);
|
||||
measureGpuTime = true;
|
||||
osTickCounterStart(&gpuTime);
|
||||
gxCmdQueueRun(&ctx->gxQueue);
|
||||
}
|
||||
|
||||
void C3D_FrameEndHook(void (* hook)(void*), void* param)
|
||||
{
|
||||
frameEndCb = hook;
|
||||
frameEndCbData = param;
|
||||
}
|
||||
|
||||
float C3D_GetDrawingTime(void)
|
||||
{
|
||||
return osTickCounterRead(&gpuTime);
|
||||
@ -310,8 +277,6 @@ static void C3Di_RenderTargetFinishInit(C3D_RenderTarget* target)
|
||||
|
||||
C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF colorFmt, C3D_DEPTHTYPE depthFmt)
|
||||
{
|
||||
if (!checkRenderQueueInit()) goto _fail0;
|
||||
|
||||
GPU_DEPTHBUF depthFmtReal = GPU_RB_DEPTH16;
|
||||
void* depthBuf = NULL;
|
||||
void* colorBuf = vramAlloc(C3D_CalcColorBufSize(width,height,colorFmt));
|
||||
@ -319,7 +284,10 @@ C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF col
|
||||
if (C3D_DEPTHTYPE_OK(depthFmt))
|
||||
{
|
||||
depthFmtReal = C3D_DEPTHTYPE_VAL(depthFmt);
|
||||
depthBuf = vramAlloc(C3D_CalcDepthBufSize(width,height,depthFmtReal));
|
||||
size_t depthSize = C3D_CalcDepthBufSize(width,height,depthFmtReal);
|
||||
vramAllocPos vramBank = addrGetVRAMBank(colorBuf);
|
||||
depthBuf = vramAllocAt(depthSize, vramBank ^ VRAM_ALLOC_ANY); // Attempt opposite bank first...
|
||||
if (!depthBuf) depthBuf = vramAllocAt(depthSize, vramBank); // ... if that fails, attempt same bank
|
||||
if (!depthBuf) goto _fail1;
|
||||
}
|
||||
|
||||
@ -348,8 +316,7 @@ _fail0:
|
||||
|
||||
C3D_RenderTarget* C3D_RenderTargetCreateFromTex(C3D_Tex* tex, GPU_TEXFACE face, int level, C3D_DEPTHTYPE depthFmt)
|
||||
{
|
||||
if (!checkRenderQueueInit()) return NULL;
|
||||
|
||||
if (!addrIsVRAM(tex->data)) return NULL; // Render targets must be in VRAM
|
||||
C3D_RenderTarget* target = C3Di_RenderTargetNew();
|
||||
if (!target) return NULL;
|
||||
|
||||
@ -359,7 +326,10 @@ C3D_RenderTarget* C3D_RenderTargetCreateFromTex(C3D_Tex* tex, GPU_TEXFACE face,
|
||||
if (C3D_DEPTHTYPE_OK(depthFmt))
|
||||
{
|
||||
GPU_DEPTHBUF depthFmtReal = C3D_DEPTHTYPE_VAL(depthFmt);
|
||||
void* depthBuf = vramAlloc(C3D_CalcDepthBufSize(fb->width,fb->height,depthFmtReal));
|
||||
size_t depthSize = C3D_CalcDepthBufSize(fb->width,fb->height,depthFmtReal);
|
||||
vramAllocPos vramBank = addrGetVRAMBank(tex->data);
|
||||
void* depthBuf = vramAllocAt(depthSize, vramBank ^ VRAM_ALLOC_ANY); // Attempt opposite bank first...
|
||||
if (!depthBuf) depthBuf = vramAllocAt(depthSize, vramBank); // ... if that fails, attempt same bank
|
||||
if (!depthBuf)
|
||||
{
|
||||
free(target);
|
||||
@ -392,39 +362,35 @@ void C3D_RenderTargetDelete(C3D_RenderTarget* target)
|
||||
{
|
||||
if (inFrame)
|
||||
svcBreak(USERBREAK_PANIC); // Shouldn't happen.
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
if (target->linked)
|
||||
C3D_RenderTargetDetachOutput(target);
|
||||
else
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
C3Di_RenderTargetDestroy(target);
|
||||
}
|
||||
|
||||
void C3D_RenderTargetSetClear(C3D_RenderTarget* target, C3D_ClearBits clearBits, u32 clearColor, u32 clearDepth)
|
||||
{
|
||||
if (!target->frameBuf.colorBuf) clearBits &= ~C3D_CLEAR_COLOR;
|
||||
if (!target->frameBuf.depthBuf) clearBits &= ~C3D_CLEAR_DEPTH;
|
||||
|
||||
C3D_ClearBits oldClearBits = target->clearBits;
|
||||
target->clearBits = clearBits;
|
||||
target->clearColor = clearColor;
|
||||
target->clearDepth = clearDepth;
|
||||
|
||||
if (clearBits &~ oldClearBits)
|
||||
C3D_FrameBufClear(&target->frameBuf, clearBits, clearColor, clearDepth);
|
||||
}
|
||||
|
||||
void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags)
|
||||
{
|
||||
int id = 0;
|
||||
if (screen==GFX_BOTTOM) id = 2;
|
||||
else if (side==GFX_RIGHT) id = 1;
|
||||
if (linkedTarget[id])
|
||||
{
|
||||
linkedTarget[id]->linked = false;
|
||||
if (!inFrame)
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
}
|
||||
linkedTarget[id] = target;
|
||||
target->linked = true;
|
||||
target->transferFlags = transferFlags;
|
||||
target->screen = screen;
|
||||
target->side = side;
|
||||
if (target)
|
||||
{
|
||||
target->linked = true;
|
||||
target->transferFlags = transferFlags;
|
||||
target->screen = screen;
|
||||
target->side = side;
|
||||
}
|
||||
}
|
||||
|
||||
void C3D_SafeDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags)
|
||||
static void C3Di_SafeDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags)
|
||||
{
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
inSafeTransfer = true;
|
||||
@ -432,7 +398,7 @@ void C3D_SafeDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32
|
||||
gxCmdQueueRun(&C3Di_GetContext()->gxQueue);
|
||||
}
|
||||
|
||||
void C3D_SafeTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags)
|
||||
static void C3Di_SafeTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags)
|
||||
{
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
inSafeTransfer = true;
|
||||
@ -440,10 +406,49 @@ void C3D_SafeTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 siz
|
||||
gxCmdQueueRun(&C3Di_GetContext()->gxQueue);
|
||||
}
|
||||
|
||||
void C3D_SafeMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1)
|
||||
static void C3Di_SafeMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1)
|
||||
{
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
inSafeTransfer = true;
|
||||
GX_MemoryFill(buf0a, buf0v, buf0e, control0, buf1a, buf1v, buf1e, control1);
|
||||
gxCmdQueueRun(&C3Di_GetContext()->gxQueue);
|
||||
}
|
||||
|
||||
void C3D_SyncDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags)
|
||||
{
|
||||
if (inFrame)
|
||||
{
|
||||
C3D_FrameSplit(0);
|
||||
GX_DisplayTransfer(inadr, indim, outadr, outdim, flags);
|
||||
} else
|
||||
{
|
||||
C3Di_SafeDisplayTransfer(inadr, indim, outadr, outdim, flags);
|
||||
gspWaitForPPF();
|
||||
}
|
||||
}
|
||||
|
||||
void C3D_SyncTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags)
|
||||
{
|
||||
if (inFrame)
|
||||
{
|
||||
C3D_FrameSplit(0);
|
||||
GX_TextureCopy(inadr, indim, outadr, outdim, size, flags);
|
||||
} else
|
||||
{
|
||||
C3Di_SafeTextureCopy(inadr, indim, outadr, outdim, size, flags);
|
||||
gspWaitForPPF();
|
||||
}
|
||||
}
|
||||
|
||||
void C3D_SyncMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1)
|
||||
{
|
||||
if (inFrame)
|
||||
{
|
||||
C3D_FrameSplit(0);
|
||||
GX_MemoryFill(buf0a, buf0v, buf0e, control0, buf1a, buf1v, buf1e, control1);
|
||||
} else
|
||||
{
|
||||
C3Di_SafeMemoryFill(buf0a, buf0v, buf0e, control0, buf1a, buf1v, buf1e, control1);
|
||||
gspWaitForPSC0();
|
||||
}
|
||||
}
|
||||
|
241
source/tex3ds.c
Normal file
241
source/tex3ds.c
Normal file
@ -0,0 +1,241 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017
|
||||
* Michael Theall (mtheall)
|
||||
*
|
||||
* This file is part of citro3d.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from the
|
||||
* use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/** @file tex3ds.c
|
||||
* @brief Tex3DS routines
|
||||
*/
|
||||
#include <tex3ds.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/** @brief Tex3DS texture
|
||||
*/
|
||||
struct Tex3DS_Texture_s
|
||||
{
|
||||
u16 numSubTextures; ///< Number of subtextures
|
||||
u16 width; ///< Texture width
|
||||
u16 height; ///< Texture height
|
||||
u8 format; ///< Texture format
|
||||
u8 mipmapLevels; ///< Number of mipmaps
|
||||
Tex3DS_SubTexture subTextures[]; ///< Subtextures
|
||||
};
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u16 numSubTextures;
|
||||
u8 width_log2 : 3;
|
||||
u8 height_log2 : 3;
|
||||
u8 type : 1;
|
||||
u8 format;
|
||||
u8 mipmapLevels;
|
||||
} Tex3DSi_Header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 width, height;
|
||||
u16 left, top, right, bottom;
|
||||
} Tex3DSi_SubTexture;
|
||||
|
||||
static inline bool Tex3DSi_ReadData(decompressCallback callback, void** userdata, void* buffer, size_t size, size_t* insize)
|
||||
{
|
||||
if (callback)
|
||||
return callback(*userdata, buffer, size) == size;
|
||||
if (size > *insize)
|
||||
return false;
|
||||
|
||||
memcpy(buffer, *userdata, size);
|
||||
*userdata = (u8*)*userdata + size;
|
||||
*insize -= size;
|
||||
return true;
|
||||
}
|
||||
|
||||
static Tex3DS_Texture
|
||||
Tex3DSi_ImportCommon(C3D_Tex* tex, C3D_TexCube* texcube, bool vram, decompressCallback callback, void* userdata, size_t insize)
|
||||
{
|
||||
// Read header
|
||||
Tex3DSi_Header hdr;
|
||||
if (!Tex3DSi_ReadData(callback, &userdata, &hdr, sizeof(hdr), &insize))
|
||||
return NULL;
|
||||
|
||||
// Allocate space for header + subtextures
|
||||
Tex3DS_Texture texture = (Tex3DS_Texture)malloc(sizeof(struct Tex3DS_Texture_s) + hdr.numSubTextures*sizeof(Tex3DS_SubTexture));
|
||||
if (!texture)
|
||||
return NULL;
|
||||
|
||||
// Fill texture metadata structure
|
||||
texture->numSubTextures = hdr.numSubTextures;
|
||||
texture->width = 1 << (hdr.width_log2 + 3);
|
||||
texture->height = 1 << (hdr.height_log2 + 3);
|
||||
texture->format = hdr.format;
|
||||
texture->mipmapLevels = hdr.mipmapLevels;
|
||||
|
||||
// Read subtexture info
|
||||
for (size_t i = 0; i < hdr.numSubTextures; i ++)
|
||||
{
|
||||
Tex3DSi_SubTexture subtex;
|
||||
if (!Tex3DSi_ReadData(callback, &userdata, &subtex, sizeof(Tex3DSi_SubTexture), &insize))
|
||||
{
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
texture->subTextures[i].width = subtex.width;
|
||||
texture->subTextures[i].height = subtex.height;
|
||||
texture->subTextures[i].left = subtex.left / 1024.0f;
|
||||
texture->subTextures[i].top = subtex.top / 1024.0f;
|
||||
texture->subTextures[i].right = subtex.right / 1024.0f;
|
||||
texture->subTextures[i].bottom = subtex.bottom / 1024.0f;
|
||||
}
|
||||
|
||||
// Allocate texture memory
|
||||
C3D_TexInitParams params;
|
||||
params.width = texture->width;
|
||||
params.height = texture->height;
|
||||
params.maxLevel = texture->mipmapLevels;
|
||||
params.format = texture->format;
|
||||
params.type = (GPU_TEXTURE_MODE_PARAM)hdr.type;
|
||||
params.onVram = vram;
|
||||
if (!C3D_TexInitWithParams(tex, texcube, params))
|
||||
{
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get texture size, including mipmaps
|
||||
size_t base_texsize = C3D_TexCalcTotalSize(tex->size, texture->mipmapLevels);
|
||||
size_t texsize = base_texsize;
|
||||
|
||||
// If this is a cubemap/skybox, there are 6 textures
|
||||
if (params.type == GPU_TEX_CUBE_MAP)
|
||||
texsize *= 6;
|
||||
|
||||
if (vram)
|
||||
{
|
||||
// Allocate staging buffer in linear memory
|
||||
void* texdata = linearAlloc(texsize);
|
||||
if (!texdata)
|
||||
{
|
||||
C3D_TexDelete(tex);
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Decompress into staging buffer for VRAM upload
|
||||
if (!decompress(texdata, texsize, callback, userdata, insize))
|
||||
{
|
||||
linearFree(texdata);
|
||||
C3D_TexDelete(tex);
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Flush buffer to prepare DMA to VRAM
|
||||
GSPGPU_FlushDataCache(texdata, texsize);
|
||||
|
||||
size_t texcount = 1;
|
||||
if (params.type == GPU_TEX_CUBE_MAP)
|
||||
texcount = 6;
|
||||
|
||||
// Upload texture(s) to VRAM
|
||||
for (size_t i = 0; i < texcount; ++i)
|
||||
C3D_TexLoadImage(tex, (u8*)texdata + i * base_texsize, i, -1);
|
||||
|
||||
linearFree(texdata);
|
||||
} else if (params.type == GPU_TEX_CUBE_MAP)
|
||||
{
|
||||
decompressIOVec iov[6];
|
||||
|
||||
// Setup IO vectors
|
||||
for (size_t i = 0; i < 6; ++i)
|
||||
{
|
||||
u32 size;
|
||||
iov[i].data = C3D_TexCubeGetImagePtr(tex, i, -1, &size);
|
||||
iov[i].size = size;
|
||||
}
|
||||
|
||||
// Decompress into texture memory
|
||||
if (!decompressV(iov, 6, callback, userdata, insize))
|
||||
{
|
||||
C3D_TexDelete(tex);
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
{
|
||||
u32 size;
|
||||
void* data = C3D_Tex2DGetImagePtr(tex, -1, &size);
|
||||
|
||||
// Decompress into texture memory
|
||||
if (!decompress(data, size, callback, userdata, insize))
|
||||
{
|
||||
C3D_TexDelete(tex);
|
||||
free(texture);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
Tex3DS_Texture
|
||||
Tex3DS_TextureImport(const void* input, size_t insize, C3D_Tex* tex, C3D_TexCube* texcube, bool vram)
|
||||
{
|
||||
return Tex3DSi_ImportCommon(tex, texcube, vram, NULL, (void*)input, insize);
|
||||
}
|
||||
|
||||
Tex3DS_Texture
|
||||
Tex3DS_TextureImportCallback(C3D_Tex* tex, C3D_TexCube* texcube, bool vram, decompressCallback callback, void* userdata)
|
||||
{
|
||||
return Tex3DSi_ImportCommon(tex, texcube, vram, callback, userdata, 0);
|
||||
}
|
||||
|
||||
Tex3DS_Texture
|
||||
Tex3DS_TextureImportFD(int fd, C3D_Tex* tex, C3D_TexCube* texcube, bool vram)
|
||||
{
|
||||
return Tex3DSi_ImportCommon(tex, texcube, vram, decompressCallback_FD, &fd, 0);
|
||||
}
|
||||
|
||||
Tex3DS_Texture
|
||||
Tex3DS_TextureImportStdio(FILE* fp, C3D_Tex* tex, C3D_TexCube* texcube, bool vram)
|
||||
{
|
||||
return Tex3DSi_ImportCommon(tex, texcube, vram, decompressCallback_Stdio, fp, 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
Tex3DS_GetNumSubTextures(const Tex3DS_Texture texture)
|
||||
{
|
||||
return texture->numSubTextures;
|
||||
}
|
||||
|
||||
const Tex3DS_SubTexture*
|
||||
Tex3DS_GetSubTexture(const Tex3DS_Texture texture, size_t index)
|
||||
{
|
||||
if (index < texture->numSubTextures)
|
||||
return &texture->subTextures[index];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Tex3DS_TextureFree(Tex3DS_Texture texture)
|
||||
{
|
||||
free(texture);
|
||||
}
|
@ -1,18 +1,5 @@
|
||||
#include "internal.h"
|
||||
|
||||
void TexEnv_Init(C3D_TexEnv* env)
|
||||
{
|
||||
env->srcRgb = GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0);
|
||||
env->srcAlpha = env->srcRgb;
|
||||
env->opRgb = GPU_TEVOPERANDS(0,0,0);
|
||||
env->opAlpha = env->opRgb;
|
||||
env->funcRgb = GPU_REPLACE;
|
||||
env->funcAlpha = env->funcRgb;
|
||||
env->color = 0xFFFFFFFF;
|
||||
env->scaleRgb = GPU_TEVSCALE_1;
|
||||
env->scaleAlpha = GPU_TEVSCALE_1;
|
||||
}
|
||||
|
||||
C3D_TexEnv* C3D_GetTexEnv(int id)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
@ -31,8 +18,11 @@ void C3D_SetTexEnv(int id, C3D_TexEnv* env)
|
||||
if (!(ctx->flags & C3DiF_Active))
|
||||
return;
|
||||
|
||||
memcpy(&ctx->texEnv[id], env, sizeof(*env));
|
||||
ctx->flags |= C3DiF_TexEnv(id);
|
||||
if (env)
|
||||
memcpy(&ctx->texEnv[id], env, sizeof(*env));
|
||||
else
|
||||
C3D_TexEnvInit(&ctx->texEnv[id]);
|
||||
}
|
||||
|
||||
void C3D_DirtyTexEnv(C3D_TexEnv* env)
|
||||
|
@ -30,10 +30,13 @@ static inline size_t fmtSize(GPU_TEXCOLOR fmt)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool addrIsVRAM(const void* addr)
|
||||
static inline bool checkTexSize(u32 size)
|
||||
{
|
||||
u32 vaddr = (u32)addr;
|
||||
return vaddr >= 0x1F000000 && vaddr < 0x1F600000;
|
||||
if (size < 8 || size > 1024)
|
||||
return false;
|
||||
if (size & (size-1))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void allocFree(void* addr)
|
||||
@ -59,7 +62,7 @@ static void C3Di_TexCubeDelete(C3D_TexCube* cube)
|
||||
|
||||
bool C3D_TexInitWithParams(C3D_Tex* tex, C3D_TexCube* cube, C3D_TexInitParams p)
|
||||
{
|
||||
if ((p.width|p.height) & 7) return false;
|
||||
if (!checkTexSize(p.width) || !checkTexSize(p.height)) return false;
|
||||
|
||||
bool isCube = typeIsCube(p.type);
|
||||
if (isCube && !cube) return false;
|
||||
@ -116,10 +119,7 @@ void C3D_TexLoadImage(C3D_Tex* tex, const void* data, GPU_TEXFACE face, int leve
|
||||
if (!addrIsVRAM(out))
|
||||
memcpy(out, data, size);
|
||||
else
|
||||
{
|
||||
C3D_SafeTextureCopy((u32*)data, 0, (u32*)out, 0, size, 8);
|
||||
gspWaitForPPF();
|
||||
}
|
||||
C3D_SyncTextureCopy((u32*)data, 0, (u32*)out, 0, size, 8);
|
||||
}
|
||||
|
||||
static void C3Di_DownscaleRGBA8(u32* dst, const u32* src[4])
|
||||
@ -178,11 +178,10 @@ void C3D_TexGenerateMipmap(C3D_Tex* tex, GPU_TEXFACE face)
|
||||
u32 dst_height = src_height>>1;
|
||||
|
||||
/* Doesn't work due to size restriction bullshit
|
||||
C3D_SafeDisplayTransfer(
|
||||
C3D_SyncDisplayTransfer(
|
||||
(u32*)src, GX_BUFFER_DIM(src_width,src_height),
|
||||
(u32*)dst, GX_BUFFER_DIM(dst_width,dst_height),
|
||||
transfer_flags);
|
||||
gspWaitForPPF();
|
||||
*/
|
||||
|
||||
u32 i,j;
|
||||
@ -260,6 +259,7 @@ void C3D_TexShadowParams(bool perspective, float bias)
|
||||
iBias = BIT(24)-1;
|
||||
|
||||
ctx->texShadow = (iBias &~ 1) | (perspective ? 0 : 1);
|
||||
ctx->flags |= C3DiF_TexStatus;
|
||||
}
|
||||
|
||||
void C3Di_SetTex(int unit, C3D_Tex* tex)
|
||||
|
@ -47,10 +47,10 @@ ICON :=
|
||||
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O3 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
-ffunction-sections \
|
||||
$(ARCH)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||
CFLAGS += $(INCLUDE) -D__3DS__
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++11
|
||||
|
||||
|
@ -7,7 +7,7 @@ OFILES := $(addprefix build/,$(CXXFILES:.cpp=.o)) \
|
||||
DFILES := $(wildcard build/*.d)
|
||||
|
||||
CFLAGS := -Wall -g -pipe -I../../include --coverage
|
||||
CXXFLAGS := $(CFLAGS) -std=gnu++11 -DGLM_FORCE_RADIANS
|
||||
CXXFLAGS := $(CFLAGS) $(CPPFLAGS) -std=gnu++11 -DGLM_FORCE_RADIANS
|
||||
LDFLAGS := $(ARCH) -pipe -lm --coverage
|
||||
|
||||
.PHONY: all clean lcov
|
||||
|
@ -953,13 +953,15 @@ check_quaternion(generator_t &gen, distribution_t &dist)
|
||||
|
||||
// check conversion to matrix
|
||||
{
|
||||
C3D_FQuat q = randomQuat(gen, dist);
|
||||
C3D_FQuat q = Quat_Normalize(randomQuat(gen, dist));
|
||||
glm::quat g = loadQuat(q);
|
||||
|
||||
C3D_Mtx m;
|
||||
Mtx_FromQuat(&m, q);
|
||||
|
||||
assert(m == glm::mat4_cast(g));
|
||||
|
||||
C3D_FQuat q2 = Quat_FromMtx(&m);
|
||||
assert(q2 == q || q2 == FVec4_Negate(q));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user