#pragma once
#include "ppsspp_config.h"
#include "Common/CommonTypes.h"
#include "Common/Swap.h"
#include "GPU/GPU.h"
#include "GPU/ge_constants.h"
#include "GPU/Common/ShaderCommon.h"
#include "Common/Math/SIMDHeaders.h"
class PointerWrap;
struct GPUgstate {
union {
u32 cmdmem[256];
struct {
u32 nop,
vaddr,
iaddr,
pad00,
prim,
bezier,
spline,
boundBox,
jump,
bjump,
call,
ret,
end,
pad01,
signal,
finish,
base,
pad02,
vertType,
offsetAddr,
origin,
region1,
region2,
lightingEnable,
lightEnable[4],
depthClampEnable,
cullfaceEnable,
textureMapEnable,
fogEnable,
ditherEnable,
alphaBlendEnable,
alphaTestEnable,
zTestEnable,
stencilTestEnable,
antiAliasEnable,
patchCullEnable,
colorTestEnable,
logicOpEnable,
pad03,
boneMatrixNumber,
boneMatrixData,
morphwgt[8],
pad04[2],
patchdivision,
patchprimitive,
patchfacing,
pad04_a,
worldmtxnum,
worldmtxdata,
viewmtxnum,
viewmtxdata,
projmtxnum,
projmtxdata,
texmtxnum,
texmtxdata,
viewportxscale,
viewportyscale,
viewportzscale,
viewportxcenter,
viewportycenter,
viewportzcenter,
texscaleu,
texscalev,
texoffsetu,
texoffsetv,
offsetx,
offsety,
pad111[2],
shademodel,
reversenormals,
pad222,
materialupdate,
materialemissive,
materialambient,
materialdiffuse,
materialspecular,
materialalpha,
pad333[2],
materialspecularcoef,
ambientcolor,
ambientalpha,
lmode,
ltype[4],
lpos[12],
ldir[12],
latt[12],
lconv[4],
lcutoff[4],
lcolor[12],
cullmode,
fbptr,
fbwidth,
zbptr,
zbwidth,
texaddr[8],
texbufwidth[8],
clutaddr,
clutaddrupper,
transfersrc,
transfersrcw,
transferdst,
transferdstw,
padxxx[2],
texsize[8],
texmapmode,
texshade,
texmode,
texformat,
loadclut,
clutformat,
texfilter,
texwrap,
texlevel,
texfunc,
texenvcolor,
texflush,
texsync,
fog1,
fog2,
fogcolor,
texlodslope,
padxxxxxx,
framebufpixformat,
clearmode,
scissor1,
scissor2,
minz,
maxz,
colortest,
colorref,
colortestmask,
alphatest,
stenciltest,
stencilop,
ztestfunc,
blend,
blendfixa,
blendfixb,
dithmtx[4],
lop,
zmsk,
pmskc,
pmska,
transferstart,
transfersrcpos,
transferdstpos,
pad99,
transfersize,
pad100,
imm_vscx,
imm_vscy,
imm_vscz,
imm_vtcs,
imm_vtct,
imm_vtcq,
imm_cv,
imm_ap,
imm_fc,
imm_scv;
u32 pad05[0xFF- 0xF9];
};
};
float worldMatrix[12];
float viewMatrix[12];
float projMatrix[16];
float tgenMatrix[12];
float boneMatrix[12 * 8];
u32 getFrameBufRawAddress() const { return fbptr & 0x1FFFF0; }
u32 getFrameBufAddress() const { return 0x44000000 | getFrameBufRawAddress(); }
GEBufferFormat FrameBufFormat() const { return static_cast<GEBufferFormat>(framebufpixformat & 3); }
int FrameBufStride() const { return fbwidth&0x7FC; }
u32 getDepthBufRawAddress() const { return zbptr & 0x1FFFF0; }
u32 getDepthBufAddress() const { return 0x44600000 | getDepthBufRawAddress(); }
int DepthBufStride() const { return zbwidth&0x7FC; }
bool isModeClear() const { return clearmode & 1; }
bool isFogEnabled() const { return fogEnable & 1; }
float getFogCoef1() const { return getFloat24(fog1); }
float getFogCoef2() const { return getFloat24(fog2); }
bool isCullEnabled() const { return cullfaceEnable & 1; }
GECullMode getCullMode() const { return (GECullMode)(cullmode & 1); }
bool isClearModeColorMask() const { return (clearmode&0x100) != 0; }
bool isClearModeAlphaMask() const { return (clearmode&0x200) != 0; }
bool isClearModeDepthMask() const { return (clearmode&0x400) != 0; }
u32 getClearModeColorMask() const { return ((clearmode&0x100) ? 0 : 0xFFFFFF) | ((clearmode&0x200) ? 0 : 0xFF000000); }
GEBlendSrcFactor getBlendFuncA() const { return (GEBlendSrcFactor)(blend & 0xF); }
GEBlendDstFactor getBlendFuncB() const { return (GEBlendDstFactor)((blend >> 4) & 0xF); }
u32 getFixA() const { return blendfixa & 0xFFFFFF; }
u32 getFixB() const { return blendfixb & 0xFFFFFF; }
GEBlendMode getBlendEq() const { return static_cast<GEBlendMode>((blend >> 8) & 0x7); }
bool isAlphaBlendEnabled() const { return alphaBlendEnable & 1; }
bool isAntiAliasEnabled() const { return antiAliasEnable & 1; }
bool isDitherEnabled() const { return ditherEnable & 1; }
int getDitherValue(int x, int y) const {
u8 raw = (dithmtx[y & 3] >> ((x & 3) * 4)) & 0xF;
return ((s8)(raw << 4)) >> 4;
}
u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); }
u8 getStencilWriteMask() const { return pmska & 0xFF; }
bool isLogicOpEnabled() const { return logicOpEnable & 1; }
GELogicOp getLogicOp() const { return static_cast<GELogicOp>(lop & 0xF); }
bool isDepthTestEnabled() const { return zTestEnable & 1; }
bool isDepthWriteEnabled() const { return !(zmsk & 1); }
GEComparison getDepthTestFunction() const { return static_cast<GEComparison>(ztestfunc & 0x7); }
u16 getDepthRangeMin() const { return minz & 0xFFFF; }
u16 getDepthRangeMax() const { return maxz & 0xFFFF; }
bool isStencilTestEnabled() const { return stencilTestEnable & 1; }
GEComparison getStencilTestFunction() const { return static_cast<GEComparison>(stenciltest & 0x7); }
int getStencilTestRef() const { return (stenciltest>>8) & 0xFF; }
int getStencilTestMask() const { return (stenciltest>>16) & 0xFF; }
GEStencilOp getStencilOpSFail() const { return static_cast<GEStencilOp>(stencilop & 0x7); }
GEStencilOp getStencilOpZFail() const { return static_cast<GEStencilOp>((stencilop>>8) & 0x7); }
GEStencilOp getStencilOpZPass() const { return static_cast<GEStencilOp>((stencilop>>16) & 0x7); }
bool isAlphaTestEnabled() const { return alphaTestEnable & 1; }
GEComparison getAlphaTestFunction() const { return static_cast<GEComparison>(alphatest & 0x7); }
int getAlphaTestRef() const { return (alphatest >> 8) & 0xFF; }
int getAlphaTestMask() const { return (alphatest >> 16) & 0xFF; }
bool isColorTestEnabled() const { return colorTestEnable & 1; }
GEComparison getColorTestFunction() const { return static_cast<GEComparison>(colortest & 0x3); }
u32 getColorTestRef() const { return colorref & 0xFFFFFF; }
u32 getColorTestMask() const { return colortestmask & 0xFFFFFF; }
u32 getTextureAddress(int level) const { return (texaddr[level] & 0xFFFFF0) | ((texbufwidth[level] << 8) & 0x0F000000); }
int getTextureWidth(int level) const { return 1 << (texsize[level] & 0xf);}
int getTextureHeight(int level) const { return 1 << ((texsize[level] >> 8) & 0xf);}
u16 getTextureDimension(int level) const { return texsize[level] & 0xf0f;}
GETexLevelMode getTexLevelMode() const { return static_cast<GETexLevelMode>(texlevel & 0x3); }
int getTexLevelOffset16() const { return (int)(s8)((texlevel >> 16) & 0xFF); }
bool isTextureMapEnabled() const { return textureMapEnable & 1; }
GETexFunc getTextureFunction() const { return static_cast<GETexFunc>(texfunc & 0x7); }
bool isColorDoublingEnabled() const { return (texfunc & 0x10000) != 0; }
bool isTextureAlphaUsed() const { return (texfunc & 0x100) != 0; }
GETextureFormat getTextureFormat() const { return static_cast<GETextureFormat>(texformat & 0xF); }
bool isTextureFormatIndexed() const { return (texformat & 4) != 0; }
int getTextureEnvColRGB() const { return texenvcolor & 0x00FFFFFF; }
u32 getClutAddress() const { return (clutaddr & 0x00FFFFF0) | ((clutaddrupper << 8) & 0x0F000000); }
int getClutLoadBytes() const { return getClutLoadBlocks() * 32; }
int getClutLoadBlocks() const {
if ((loadclut & 0x7F) == 0x40)
return 0x40;
return loadclut & 0x3F;
}
GEPaletteFormat getClutPaletteFormat() const { return static_cast<GEPaletteFormat>(clutformat & 3); }
int getClutIndexShift() const { return (clutformat >> 2) & 0x1F; }
int getClutIndexMask() const { return (clutformat >> 8) & 0xFF; }
int getClutIndexStartPos() const { return ((clutformat >> 16) & 0x1F) << 4; }
u32 transformClutIndex(u32 index) const {
u32 mask = getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 0xFF : 0x1FF;
return ((index >> getClutIndexShift()) & getClutIndexMask()) | (getClutIndexStartPos() & mask);
}
bool isClutIndexSimple() const { return (clutformat & ~3) == 0xC500FF00; }
bool isTextureSwizzled() const { return texmode & 1; }
bool isClutSharedForMipmaps() const { return (texmode & 0x100) == 0; }
bool isMipmapEnabled() const { return (texfilter & 4) != 0; }
bool isMipmapFilteringEnabled() const { return (texfilter & 2) != 0; }
bool isMinifyFilteringEnabled() const { return (texfilter & 1) != 0; }
bool isMagnifyFilteringEnabled() const { return (texfilter >> 8) & 1; }
int getTextureMaxLevel() const { return (texmode >> 16) & 0x7; }
float getTextureLodSlope() const { return getFloat24(texlodslope); }
bool isLightingEnabled() const { return lightingEnable & 1; }
bool isLightChanEnabled(int chan) const { return lightEnable[chan] & 1; }
GELightComputation getLightComputation(int chan) const { return static_cast<GELightComputation>(ltype[chan] & 0x3); }
bool isUsingPoweredDiffuseLight(int chan) const { return getLightComputation(chan) == GE_LIGHTCOMP_ONLYPOWDIFFUSE; }
bool isUsingSpecularLight(int chan) const { return getLightComputation(chan) == GE_LIGHTCOMP_BOTH; }
bool isUsingSecondaryColor() const { return lmode & 1; }
GELightType getLightType(int chan) const { return static_cast<GELightType>((ltype[chan] >> 8) & 3); }
bool isDirectionalLight(int chan) const { return getLightType(chan) == GE_LIGHTTYPE_DIRECTIONAL; }
bool isPointLight(int chan) const { return getLightType(chan) == GE_LIGHTTYPE_POINT; }
bool isSpotLight(int chan) const { return getLightType(chan) >= GE_LIGHTTYPE_SPOT; }
GEShadeMode getShadeMode() const { return static_cast<GEShadeMode>(shademodel & 1); }
unsigned int getAmbientA() const { return ambientalpha&0xFF; }
unsigned int getAmbientRGBA() const { return (ambientcolor&0xFFFFFF) | ((ambientalpha&0xFF)<<24); }
unsigned int getMaterialUpdate() const { return materialupdate & 7; }
unsigned int getMaterialAmbientR() const { return materialambient&0xFF; }
unsigned int getMaterialAmbientG() const { return (materialambient>>8)&0xFF; }
unsigned int getMaterialAmbientB() const { return (materialambient>>16)&0xFF; }
unsigned int getMaterialAmbientA() const { return materialalpha&0xFF; }
unsigned int getMaterialAmbientRGBA() const { return (materialambient & 0x00FFFFFF) | (materialalpha << 24); }
unsigned int getMaterialDiffuse() const { return materialdiffuse & 0xffffff; }
unsigned int getMaterialEmissive() const { return materialemissive & 0xffffff; }
unsigned int getMaterialSpecular() const { return materialspecular & 0xffffff; }
float getMaterialSpecularCoef() const { return getFloat24(materialspecularcoef); }
unsigned int getLightAmbientColor(int chan) const { return lcolor[chan*3]&0xFFFFFF; }
unsigned int getDiffuseColor(int chan) const { return lcolor[1+chan*3]&0xFFFFFF; }
unsigned int getSpecularColor(int chan) const { return lcolor[2+chan*3]&0xFFFFFF; }
int getPatchDivisionU() const { return patchdivision & 0x7F; }
int getPatchDivisionV() const { return (patchdivision >> 8) & 0x7F; }
GETexMapMode getUVGenMode() const { return static_cast<GETexMapMode>(texmapmode & 3);}
GETexProjMapMode getUVProjMode() const { return static_cast<GETexProjMapMode>((texmapmode >> 8) & 3);}
int getUVLS0() const { return texshade & 0x3; }
int getUVLS1() const { return (texshade >> 8) & 0x3; }
bool isTexCoordClampedS() const { return texwrap & 1; }
bool isTexCoordClampedT() const { return (texwrap >> 8) & 1; }
int getScissorX1() const { return scissor1 & 0x3FF; }
int getScissorY1() const { return (scissor1 >> 10) & 0x3FF; }
int getScissorX2() const { return scissor2 & 0x3FF; }
int getScissorY2() const { return (scissor2 >> 10) & 0x3FF; }
int getRegionRateX() const { return 0x100 + (region1 & 0x3FF); }
int getRegionRateY() const { return 0x100 + ((region1 >> 10) & 0x3FF); }
int getRegionX2() const { return (region2 & 0x3FF); }
int getRegionY2() const { return (region2 >> 10) & 0x3FF; }
bool isDepthClampEnabled() const { return depthClampEnable & 1; }
float getViewportXScale() const { return getFloat24(viewportxscale); }
float getViewportYScale() const { return getFloat24(viewportyscale); }
float getViewportZScale() const { return getFloat24(viewportzscale); }
float getViewportXCenter() const { return getFloat24(viewportxcenter); }
float getViewportYCenter() const { return getFloat24(viewportycenter); }
float getViewportZCenter() const { return getFloat24(viewportzcenter); }
int getOffsetX16() const { return offsetx & 0xFFFF; }
int getOffsetY16() const { return offsety & 0xFFFF; }
float getOffsetX() const { return (float)getOffsetX16() / 16.0f; }
float getOffsetY() const { return (float)getOffsetY16() / 16.0f; }
bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; }
bool areNormalsReversed() const { return reversenormals & 1; }
bool isSkinningEnabled() const { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); }
int getNumMorphWeights() const { return ((vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT) + 1; }
GEPatchPrimType getPatchPrimitiveType() const { return static_cast<GEPatchPrimType>(patchprimitive & 3); }
bool isPatchNormalsReversed() const { return patchfacing & 1; }
u32 getTransferSrcAddress() const { return (transfersrc & 0xFFFFF0) | ((transfersrcw & 0xFF0000) << 8); }
u32 getTransferSrcStride() const { int stride = transfersrcw & 0x7F8; return stride > 0x400 ? 0 : stride; }
int getTransferSrcX() const { return (transfersrcpos >> 0) & 0x3FF; }
int getTransferSrcY() const { return (transfersrcpos >> 10) & 0x3FF; }
u32 getTransferDstAddress() const { return (transferdst & 0xFFFFF0) | ((transferdstw & 0xFF0000) << 8); }
u32 getTransferDstStride() const { int stride = transferdstw & 0x7F8; return stride > 0x400 ? 0 : stride; }
int getTransferDstX() const { return (transferdstpos >> 0) & 0x3FF; }
int getTransferDstY() const { return (transferdstpos >> 10) & 0x3FF; }
int getTransferWidth() const { return ((transfersize >> 0) & 0x3FF) + 1; }
int getTransferHeight() const { return ((transfersize >> 10) & 0x3FF) + 1; }
int getTransferBpp() const { return (transferstart & 1) ? 4 : 2; }
void FastLoadBoneMatrix(u32 addr);
static void Reset();
void Save(u32_le *ptr);
void Restore(const u32_le *ptr);
};
bool vertTypeIsSkinningEnabled(u32 vertType);
inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); }
inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; }
struct UVScale {
float uScale, vScale;
float uOff, vOff;
};
#define FLAG_BIT(x) (1 << x)
enum {
GPU_USE_DUALSOURCE_BLEND = FLAG_BIT(0),
GPU_USE_LIGHT_UBERSHADER = FLAG_BIT(1),
GPU_USE_FRAGMENT_TEST_CACHE = FLAG_BIT(2),
GPU_USE_VS_RANGE_CULLING = FLAG_BIT(3),
GPU_USE_BLEND_MINMAX = FLAG_BIT(4),
GPU_USE_LOGIC_OP = FLAG_BIT(5),
GPU_USE_FRAGMENT_UBERSHADER = FLAG_BIT(6),
GPU_USE_TEXTURE_NPOT = FLAG_BIT(7),
GPU_USE_ANISOTROPY = FLAG_BIT(8),
GPU_USE_CLEAR_RAM_HACK = FLAG_BIT(9),
GPU_USE_INSTANCE_RENDERING = FLAG_BIT(10),
GPU_USE_VERTEX_TEXTURE_FETCH = FLAG_BIT(11),
GPU_USE_TEXTURE_FLOAT = FLAG_BIT(12),
GPU_USE_16BIT_FORMATS = FLAG_BIT(13),
GPU_USE_DEPTH_CLAMP = FLAG_BIT(14),
GPU_USE_TEXTURE_LOD_CONTROL = FLAG_BIT(15),
GPU_USE_DEPTH_TEXTURE = FLAG_BIT(16),
GPU_USE_ACCURATE_DEPTH = FLAG_BIT(17),
GPU_USE_GS_CULLING = FLAG_BIT(18),
GPU_USE_FRAMEBUFFER_ARRAYS = FLAG_BIT(19),
GPU_USE_FRAMEBUFFER_FETCH = FLAG_BIT(20),
GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT = FLAG_BIT(21),
GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22),
GPU_ROUND_DEPTH_TO_16BIT = FLAG_BIT(23),
GPU_USE_CLIP_DISTANCE = FLAG_BIT(24),
GPU_USE_CULL_DISTANCE = FLAG_BIT(25),
GPU_USE_SHADER_BLENDING = FLAG_BIT(26),
GPU_USE_VIRTUAL_REALITY = FLAG_BIT(29),
GPU_USE_SINGLE_PASS_STEREO = FLAG_BIT(30),
GPU_USE_SIMPLE_STEREO_PERSPECTIVE = FLAG_BIT(31),
};
const char *GpuUseFlagToString(int useFlag);
struct KnownVertexBounds {
u16 minU;
u16 minV;
u16 maxU;
u16 maxV;
};
enum class SubmitType {
DRAW,
BEZIER,
SPLINE,
HW_BEZIER,
HW_SPLINE,
};
extern GPUgstate gstate;
struct GPUStateCache {
bool Use(u32 flags) const { return (useFlags_ & flags) != 0; }
bool UseAll(u32 flags) const { return (useFlags_ & flags) == flags; }
u32 UseFlags() const { return useFlags_; }
uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; }
void Dirty(u64 what) {
dirty |= what;
}
void CleanUniforms() {
dirty &= ~DIRTY_ALL_UNIFORMS;
}
void Clean(u64 what) {
dirty &= ~what;
}
bool IsDirty(u64 what) const {
return (dirty & what) != 0ULL;
}
void SetUseShaderDepal(ShaderDepalMode mode) {
if (mode != shaderDepalMode) {
shaderDepalMode = mode;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
void SetTextureFullAlpha(bool fullAlpha) {
if (fullAlpha != textureFullAlpha) {
textureFullAlpha = fullAlpha;
Dirty(DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEX_ALPHA_MUL);
}
}
void SetNeedShaderTexclamp(bool need) {
if (need != needShaderTexClamp) {
needShaderTexClamp = need;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
if (need)
Dirty(DIRTY_TEXCLAMP);
}
}
void SetTextureIs3D(bool is3D) {
if (is3D != curTextureIs3D) {
curTextureIs3D = is3D;
Dirty(DIRTY_FRAGMENTSHADER_STATE | (is3D ? DIRTY_MIPBIAS : 0));
}
}
void SetTextureIsArray(bool isArrayTexture) {
if (textureIsArray != isArrayTexture) {
textureIsArray = isArrayTexture;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
void SetTextureIsVideo(bool isVideo) {
textureIsVideo = isVideo;
}
void SetTextureIsBGRA(bool isBGRA) {
if (bgraTexture != isBGRA) {
bgraTexture = isBGRA;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
void SetTextureIsFramebuffer(bool isFramebuffer) {
if (textureIsFramebuffer != isFramebuffer) {
textureIsFramebuffer = isFramebuffer;
Dirty(DIRTY_UVSCALEOFFSET);
} else if (isFramebuffer) {
Dirty(DIRTY_UVSCALEOFFSET);
}
}
bool SetUseFlags(u32 newFlags);
u32 GetUseFlags() const {
return useFlags_;
}
void UpdateUVScaleOffset() {
#if defined(_M_SSE)
__m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *)&gstate.texscaleu), 8);
_mm_storeu_si128((__m128i *)&uv, values);
#elif PPSSPP_ARCH(ARM_NEON)
const uint32x4_t values = vshlq_n_u32(vld1q_u32((const u32 *)&gstate.texscaleu), 8);
vst1q_u32((u32 *)&uv, values);
#else
uv.uScale = getFloat24(gstate.texscaleu);
uv.vScale = getFloat24(gstate.texscalev);
uv.uOff = getFloat24(gstate.texoffsetu);
uv.vOff = getFloat24(gstate.texoffsetv);
#endif
}
private:
u32 useFlags_;
public:
u32 vertexAddr;
u32 indexAddr;
u32 offsetAddr;
uint64_t dirty;
bool usingDepth;
bool clearingDepth;
bool textureFullAlpha;
bool vertexFullAlpha;
int skipDrawReason;
UVScale uv;
bool bgraTexture;
bool needShaderTexClamp;
bool textureIsArray;
bool textureIsFramebuffer;
bool textureIsVideo;
bool useFlagsChanged;
float morphWeights[8];
u32 deferredVertTypeDirty;
u32 curTextureWidth;
u32 curTextureHeight;
u32 actualTextureHeight;
int curTextureXOffset;
int curTextureYOffset;
bool curTextureIs3D;
float vpWidth;
float vpHeight;
float vpXOffset;
float vpYOffset;
float vpZOffset;
float vpWidthScale;
float vpHeightScale;
float vpDepthScale;
KnownVertexBounds vertBounds;
GEBufferFormat framebufFormat;
bool blueToAlpha;
bool pixelMapped;
u32 curRTWidth;
u32 curRTHeight;
u32 curRTRenderWidth;
u32 curRTRenderHeight;
void SetCurRTOffset(int xoff, int yoff) {
if (xoff != curRTOffsetX || yoff != curRTOffsetY) {
curRTOffsetX = xoff;
curRTOffsetY = yoff;
Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_PROJTHROUGHMATRIX);
}
}
int curRTOffsetX;
int curRTOffsetY;
SubmitType submitType;
int spline_num_points_u;
ShaderDepalMode shaderDepalMode;
GEBufferFormat depalFramebufferFormat;
u32 getRelativeAddress(u32 data) const;
static void Reset();
void DoState(PointerWrap &p);
};
class GPUInterface;
class GPUDebugInterface;
extern GPUStateCache gstate_c;
inline u32 GPUStateCache::getRelativeAddress(u32 data) const {
u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;
return (gstate_c.offsetAddr + baseExtended) & 0x0FFFFFFF;
}