1 // Copyright (c) 2012- PPSSPP Project.
2
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
11
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18 #pragma once
19
20 #include "Common/Common.h"
21 #include "Common/Swap.h"
22 #include "GPU/GPU.h"
23 #include "GPU/ge_constants.h"
24 #include "GPU/Common/ShaderCommon.h"
25
26 class PointerWrap;
27
28 struct GPUgstate {
29 // Getting rid of this ugly union in favor of the accessor functions
30 // might be a good idea....
31 union {
32 u32 cmdmem[256];
33 struct {
34 u32 nop,
35 vaddr,
36 iaddr,
37 pad00,
38 prim,
39 bezier,
40 spline,
41 boundBox,
42 jump,
43 bjump,
44 call,
45 ret,
46 end,
47 pad01,
48 signal,
49 finish,
50 base,
51 pad02,
52 vertType,
53 offsetAddr,
54 origin,
55 region1,
56 region2,
57 lightingEnable,
58 lightEnable[4],
59 depthClampEnable,
60 cullfaceEnable,
61 textureMapEnable, // 0x1E GE_CMD_TEXTUREMAPENABLE
62 fogEnable,
63 ditherEnable,
64 alphaBlendEnable,
65 alphaTestEnable,
66 zTestEnable,
67 stencilTestEnable,
68 antiAliasEnable,
69 patchCullEnable,
70 colorTestEnable,
71 logicOpEnable,
72 pad03,
73 boneMatrixNumber,
74 boneMatrixData,
75 morphwgt[8], //dont use
76 pad04[2],
77 patchdivision,
78 patchprimitive,
79 patchfacing,
80 pad04_a,
81
82 worldmtxnum, // 0x3A
83 worldmtxdata, // 0x3B
84 viewmtxnum, // 0x3C
85 viewmtxdata, // 0x3D
86 projmtxnum, // 0x3E
87 projmtxdata, // 0x3F
88 texmtxnum, // 0x40
89 texmtxdata, // 0x41
90
91 viewportxscale, // 0x42
92 viewportyscale, // 0x43
93 viewportzscale, // 0x44
94 viewportxcenter, // 0x45
95 viewportycenter, // 0x46
96 viewportzcenter, // 0x47
97 texscaleu, // 0x48
98 texscalev, // 0x49
99 texoffsetu, // 0x4A
100 texoffsetv, // 0x4B
101 offsetx, // 0x4C
102 offsety, // 0x4D
103 pad111[2],
104 shademodel, // 0x50
105 reversenormals, // 0x51
106 pad222,
107 materialupdate, // 0x53
108 materialemissive, // 0x54
109 materialambient, // 0x55
110 materialdiffuse, // 0x56
111 materialspecular, // 0x57
112 materialalpha, // 0x58
113 pad333[2],
114 materialspecularcoef, // 0x5B
115 ambientcolor, // 0x5C
116 ambientalpha, // 0x5D
117 lmode, // 0x5E GE_CMD_LIGHTMODE
118 ltype[4], // 0x5F-0x62 GE_CMD_LIGHTTYPEx
119 lpos[12], // 0x63-0x6E
120 ldir[12], // 0x6F-0x7A
121 latt[12], // 0x7B-0x86
122 lconv[4], // 0x87-0x8A
123 lcutoff[4], // 0x8B-0x8E
124 lcolor[12], // 0x8F-0x9A
125 cullmode, // 0x9B
126 fbptr, // 0x9C
127 fbwidth, // 0x9D
128 zbptr, // 0x9E
129 zbwidth, // 0x9F
130 texaddr[8], // 0xA0-0xA7
131 texbufwidth[8], // 0xA8-0xAF
132 clutaddr, // 0xB0
133 clutaddrupper, // 0xB1
134 transfersrc, // 0xB2
135 transfersrcw, // 0xB3
136 transferdst, // 0xB4
137 transferdstw, // 0xB5
138 padxxx[2],
139 texsize[8], // 0xB8-BF
140 texmapmode, // 0xC0
141 texshade, // 0xC1
142 texmode, // 0xC2 GE_CMD_TEXMODE
143 texformat, // 0xC3
144 loadclut, // 0xC4
145 clutformat, // 0xC5
146 texfilter, // 0xC6
147 texwrap, // 0xC7
148 texlevel, // 0xC8
149 texfunc, // 0xC9
150 texenvcolor, // 0xCA
151 texflush, // 0xCB
152 texsync, // 0xCC
153 fog1, // 0xCD
154 fog2, // 0xCE
155 fogcolor, // 0xCF
156 texlodslope, // 0xD0
157 padxxxxxx, // 0xD1
158 framebufpixformat, // 0xD2
159 clearmode, // 0xD3 GE_CMD_CLEARMODE
160 scissor1,
161 scissor2,
162 minz,
163 maxz,
164 colortest,
165 colorref,
166 colortestmask,
167 alphatest,
168 stenciltest,
169 stencilop,
170 ztestfunc,
171 blend,
172 blendfixa,
173 blendfixb,
174 dithmtx[4],
175 lop, // 0xE6
176 zmsk,
177 pmskc,
178 pmska,
179 transferstart,
180 transfersrcpos,
181 transferdstpos,
182 pad99,
183 transfersize, // 0xEE
184 pad100, // 0xEF
185 imm_vscx, // 0xF0
186 imm_vscy,
187 imm_vscz,
188 imm_vtcs,
189 imm_vtct,
190 imm_vtcq,
191 imm_cv,
192 imm_ap,
193 imm_fc,
194 imm_scv; // 0xF9
195 // In the unlikely case we ever add anything else here, don't forget to update the padding on the next line!
196 u32 pad05[0xFF- 0xF9];
197 };
198 };
199
200 // These are not directly mapped, instead these are loaded one-by-one through special commands.
201 // However, these are actual state, and can be read back.
202 float worldMatrix[12]; // 4x3
203 float viewMatrix[12]; // 4x3
204 float projMatrix[16]; // 4x4
205 float tgenMatrix[12]; // 4x3
206 float boneMatrix[12 * 8]; // Eight 4x3 bone matrices.
207
208 // We ignore the high bits of the framebuffer in fbwidth - even 0x08000000 renders to vRAM.
getFrameBufRawAddressGPUgstate209 u32 getFrameBufRawAddress() const { return (fbptr & 0xFFFFFF); }
210 // 0x44000000 is uncached VRAM.
getFrameBufAddressGPUgstate211 u32 getFrameBufAddress() const { return 0x44000000 | getFrameBufRawAddress(); }
FrameBufFormatGPUgstate212 GEBufferFormat FrameBufFormat() const { return static_cast<GEBufferFormat>(framebufpixformat & 3); }
FrameBufStrideGPUgstate213 int FrameBufStride() const { return fbwidth&0x7FC; }
getDepthBufRawAddressGPUgstate214 u32 getDepthBufRawAddress() const { return (zbptr & 0xFFFFFF); }
getDepthBufAddressGPUgstate215 u32 getDepthBufAddress() const { return 0x44000000 | getDepthBufRawAddress(); }
DepthBufStrideGPUgstate216 int DepthBufStride() const { return zbwidth&0x7FC; }
217
218 // Pixel Pipeline
isModeClearGPUgstate219 bool isModeClear() const { return clearmode & 1; }
isFogEnabledGPUgstate220 bool isFogEnabled() const { return fogEnable & 1; }
getFogCoef1GPUgstate221 float getFogCoef1() const { return getFloat24(fog1); }
getFogCoef2GPUgstate222 float getFogCoef2() const { return getFloat24(fog2); }
223
224 // Cull
isCullEnabledGPUgstate225 bool isCullEnabled() const { return cullfaceEnable & 1; }
getCullModeGPUgstate226 int getCullMode() const { return cullmode & 1; }
227
228 // Color Mask
isClearModeColorMaskGPUgstate229 bool isClearModeColorMask() const { return (clearmode&0x100) != 0; }
isClearModeAlphaMaskGPUgstate230 bool isClearModeAlphaMask() const { return (clearmode&0x200) != 0; }
isClearModeDepthMaskGPUgstate231 bool isClearModeDepthMask() const { return (clearmode&0x400) != 0; }
getClearModeColorMaskGPUgstate232 u32 getClearModeColorMask() const { return ((clearmode&0x100) ? 0 : 0xFFFFFF) | ((clearmode&0x200) ? 0 : 0xFF000000); }
233
234 // Blend
getBlendFuncAGPUgstate235 GEBlendSrcFactor getBlendFuncA() const { return (GEBlendSrcFactor)(blend & 0xF); }
getBlendFuncBGPUgstate236 GEBlendDstFactor getBlendFuncB() const { return (GEBlendDstFactor)((blend >> 4) & 0xF); }
getFixAGPUgstate237 u32 getFixA() const { return blendfixa & 0xFFFFFF; }
getFixBGPUgstate238 u32 getFixB() const { return blendfixb & 0xFFFFFF; }
getBlendEqGPUgstate239 GEBlendMode getBlendEq() const { return static_cast<GEBlendMode>((blend >> 8) & 0x7); }
isAlphaBlendEnabledGPUgstate240 bool isAlphaBlendEnabled() const { return alphaBlendEnable & 1; }
241
242 // AntiAlias
isAntiAliasEnabledGPUgstate243 bool isAntiAliasEnabled() const { return antiAliasEnable & 1; }
244
245 // Dither
isDitherEnabledGPUgstate246 bool isDitherEnabled() const { return ditherEnable & 1; }
getDitherValueGPUgstate247 int getDitherValue(int x, int y) const {
248 u8 raw = (dithmtx[y & 3] >> ((x & 3) * 4)) & 0xF;
249 // Apply sign extension to make 8-F negative, 0-7 positive.
250 return ((s8)(raw << 4)) >> 4;
251 }
252
253 // Color Mask
getColorMaskGPUgstate254 u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); }
getStencilWriteMaskGPUgstate255 u8 getStencilWriteMask() const { return pmska & 0xFF; }
isLogicOpEnabledGPUgstate256 bool isLogicOpEnabled() const { return logicOpEnable & 1; }
getLogicOpGPUgstate257 GELogicOp getLogicOp() const { return static_cast<GELogicOp>(lop & 0xF); }
258
259 // Depth Test
isDepthTestEnabledGPUgstate260 bool isDepthTestEnabled() const { return zTestEnable & 1; }
isDepthWriteEnabledGPUgstate261 bool isDepthWriteEnabled() const { return !(zmsk & 1); }
getDepthTestFunctionGPUgstate262 GEComparison getDepthTestFunction() const { return static_cast<GEComparison>(ztestfunc & 0x7); }
getDepthRangeMinGPUgstate263 u16 getDepthRangeMin() const { return minz & 0xFFFF; }
getDepthRangeMaxGPUgstate264 u16 getDepthRangeMax() const { return maxz & 0xFFFF; }
265
266 // Stencil Test
isStencilTestEnabledGPUgstate267 bool isStencilTestEnabled() const { return stencilTestEnable & 1; }
getStencilTestFunctionGPUgstate268 GEComparison getStencilTestFunction() const { return static_cast<GEComparison>(stenciltest & 0x7); }
getStencilTestRefGPUgstate269 int getStencilTestRef() const { return (stenciltest>>8) & 0xFF; }
getStencilTestMaskGPUgstate270 int getStencilTestMask() const { return (stenciltest>>16) & 0xFF; }
getStencilOpSFailGPUgstate271 GEStencilOp getStencilOpSFail() const { return static_cast<GEStencilOp>(stencilop & 0x7); }
getStencilOpZFailGPUgstate272 GEStencilOp getStencilOpZFail() const { return static_cast<GEStencilOp>((stencilop>>8) & 0x7); }
getStencilOpZPassGPUgstate273 GEStencilOp getStencilOpZPass() const { return static_cast<GEStencilOp>((stencilop>>16) & 0x7); }
274
275 // Alpha Test
isAlphaTestEnabledGPUgstate276 bool isAlphaTestEnabled() const { return alphaTestEnable & 1; }
getAlphaTestFunctionGPUgstate277 GEComparison getAlphaTestFunction() const { return static_cast<GEComparison>(alphatest & 0x7); }
getAlphaTestRefGPUgstate278 int getAlphaTestRef() const { return (alphatest >> 8) & 0xFF; }
getAlphaTestMaskGPUgstate279 int getAlphaTestMask() const { return (alphatest >> 16) & 0xFF; }
280
281 // Color Test
isColorTestEnabledGPUgstate282 bool isColorTestEnabled() const { return colorTestEnable & 1; }
getColorTestFunctionGPUgstate283 GEComparison getColorTestFunction() const { return static_cast<GEComparison>(colortest & 0x3); }
getColorTestRefGPUgstate284 u32 getColorTestRef() const { return colorref & 0xFFFFFF; }
getColorTestMaskGPUgstate285 u32 getColorTestMask() const { return colortestmask & 0xFFFFFF; }
286
287 // Texturing
288 // TODO: Verify getTextureAddress() alignment?
getTextureAddressGPUgstate289 u32 getTextureAddress(int level) const { return (texaddr[level] & 0xFFFFF0) | ((texbufwidth[level] << 8) & 0x0F000000); }
getTextureWidthGPUgstate290 int getTextureWidth(int level) const { return 1 << (texsize[level] & 0xf);}
getTextureHeightGPUgstate291 int getTextureHeight(int level) const { return 1 << ((texsize[level] >> 8) & 0xf);}
getTextureDimensionGPUgstate292 u16 getTextureDimension(int level) const { return texsize[level] & 0xf0f;}
getTexLevelModeGPUgstate293 GETexLevelMode getTexLevelMode() const { return static_cast<GETexLevelMode>(texlevel & 0x3); }
getTexLevelOffset16GPUgstate294 int getTexLevelOffset16() const { return (int)(s8)((texlevel >> 16) & 0xFF); }
isTextureMapEnabledGPUgstate295 bool isTextureMapEnabled() const { return textureMapEnable & 1; }
getTextureFunctionGPUgstate296 GETexFunc getTextureFunction() const { return static_cast<GETexFunc>(texfunc & 0x7); }
isColorDoublingEnabledGPUgstate297 bool isColorDoublingEnabled() const { return (texfunc & 0x10000) != 0; }
isTextureAlphaUsedGPUgstate298 bool isTextureAlphaUsed() const { return (texfunc & 0x100) != 0; }
getTextureFormatGPUgstate299 GETextureFormat getTextureFormat() const { return static_cast<GETextureFormat>(texformat & 0xF); }
isTextureFormatIndexedGPUgstate300 bool isTextureFormatIndexed() const { return (texformat & 4) != 0; } // GE_TFMT_CLUT4 - GE_TFMT_CLUT32 are 0b1xx.
getTextureEnvColRGPUgstate301 int getTextureEnvColR() const { return texenvcolor&0xFF; }
getTextureEnvColGGPUgstate302 int getTextureEnvColG() const { return (texenvcolor>>8)&0xFF; }
getTextureEnvColBGPUgstate303 int getTextureEnvColB() const { return (texenvcolor>>16)&0xFF; }
getClutAddressGPUgstate304 u32 getClutAddress() const { return (clutaddr & 0x00FFFFF0) | ((clutaddrupper << 8) & 0x0F000000); }
getClutLoadBytesGPUgstate305 int getClutLoadBytes() const { return (loadclut & 0x3F) * 32; }
getClutLoadBlocksGPUgstate306 int getClutLoadBlocks() const { return (loadclut & 0x3F); }
getClutPaletteFormatGPUgstate307 GEPaletteFormat getClutPaletteFormat() const { return static_cast<GEPaletteFormat>(clutformat & 3); }
getClutIndexShiftGPUgstate308 int getClutIndexShift() const { return (clutformat >> 2) & 0x1F; }
getClutIndexMaskGPUgstate309 int getClutIndexMask() const { return (clutformat >> 8) & 0xFF; }
getClutIndexStartPosGPUgstate310 int getClutIndexStartPos() const { return ((clutformat >> 16) & 0x1F) << 4; }
transformClutIndexGPUgstate311 u32 transformClutIndex(u32 index) const {
312 // We need to wrap any entries beyond the first 1024 bytes.
313 u32 mask = getClutPaletteFormat() == GE_CMODE_32BIT_ABGR8888 ? 0xFF : 0x1FF;
314 return ((index >> getClutIndexShift()) & getClutIndexMask()) | (getClutIndexStartPos() & mask);
315 }
isClutIndexSimpleGPUgstate316 bool isClutIndexSimple() const { return (clutformat & ~3) == 0xC500FF00; } // Meaning, no special mask, shift, or start pos.
isTextureSwizzledGPUgstate317 bool isTextureSwizzled() const { return texmode & 1; }
isClutSharedForMipmapsGPUgstate318 bool isClutSharedForMipmaps() const { return (texmode & 0x100) == 0; }
isMipmapEnabledGPUgstate319 bool isMipmapEnabled() const { return (texfilter & 4) != 0; }
isMipmapFilteringEnabledGPUgstate320 bool isMipmapFilteringEnabled() const { return (texfilter & 2) != 0; }
isMinifyFilteringEnabledGPUgstate321 bool isMinifyFilteringEnabled() const { return (texfilter & 1) != 0; }
isMagnifyFilteringEnabledGPUgstate322 bool isMagnifyFilteringEnabled() const { return (texfilter >> 8) & 1; }
getTextureMaxLevelGPUgstate323 int getTextureMaxLevel() const { return (texmode >> 16) & 0x7; }
getTextureLodSlopeGPUgstate324 float getTextureLodSlope() const { return getFloat24(texlodslope); }
325
326 // Lighting
isLightingEnabledGPUgstate327 bool isLightingEnabled() const { return lightingEnable & 1; }
isLightChanEnabledGPUgstate328 bool isLightChanEnabled(int chan) const { return lightEnable[chan] & 1; }
getLightComputationGPUgstate329 GELightComputation getLightComputation(int chan) const { return static_cast<GELightComputation>(ltype[chan] & 0x3); }
isUsingPoweredDiffuseLightGPUgstate330 bool isUsingPoweredDiffuseLight(int chan) const { return getLightComputation(chan) == GE_LIGHTCOMP_ONLYPOWDIFFUSE; }
isUsingSpecularLightGPUgstate331 bool isUsingSpecularLight(int chan) const { return getLightComputation(chan) == GE_LIGHTCOMP_BOTH; }
isUsingSecondaryColorGPUgstate332 bool isUsingSecondaryColor() const { return lmode & 1; }
getLightTypeGPUgstate333 GELightType getLightType(int chan) const { return static_cast<GELightType>((ltype[chan] >> 8) & 3); }
isDirectionalLightGPUgstate334 bool isDirectionalLight(int chan) const { return getLightType(chan) == GE_LIGHTTYPE_DIRECTIONAL; }
isPointLightGPUgstate335 bool isPointLight(int chan) const { return getLightType(chan) == GE_LIGHTTYPE_POINT; }
isSpotLightGPUgstate336 bool isSpotLight(int chan) const { return getLightType(chan) >= GE_LIGHTTYPE_SPOT; }
getShadeModeGPUgstate337 GEShadeMode getShadeMode() const { return static_cast<GEShadeMode>(shademodel & 1); }
getAmbientRGPUgstate338 unsigned int getAmbientR() const { return ambientcolor&0xFF; }
getAmbientGGPUgstate339 unsigned int getAmbientG() const { return (ambientcolor>>8)&0xFF; }
getAmbientBGPUgstate340 unsigned int getAmbientB() const { return (ambientcolor>>16)&0xFF; }
getAmbientAGPUgstate341 unsigned int getAmbientA() const { return ambientalpha&0xFF; }
getAmbientRGBAGPUgstate342 unsigned int getAmbientRGBA() const { return (ambientcolor&0xFFFFFF) | ((ambientalpha&0xFF)<<24); }
getMaterialUpdateGPUgstate343 unsigned int getMaterialUpdate() const { return materialupdate&0xFFFFFF; }
getMaterialAmbientRGPUgstate344 unsigned int getMaterialAmbientR() const { return materialambient&0xFF; }
getMaterialAmbientGGPUgstate345 unsigned int getMaterialAmbientG() const { return (materialambient>>8)&0xFF; }
getMaterialAmbientBGPUgstate346 unsigned int getMaterialAmbientB() const { return (materialambient>>16)&0xFF; }
getMaterialAmbientAGPUgstate347 unsigned int getMaterialAmbientA() const { return materialalpha&0xFF; }
getMaterialAmbientRGBAGPUgstate348 unsigned int getMaterialAmbientRGBA() const { return (materialambient & 0x00FFFFFF) | (materialalpha << 24); }
getMaterialDiffuseRGPUgstate349 unsigned int getMaterialDiffuseR() const { return materialdiffuse&0xFF; }
getMaterialDiffuseGGPUgstate350 unsigned int getMaterialDiffuseG() const { return (materialdiffuse>>8)&0xFF; }
getMaterialDiffuseBGPUgstate351 unsigned int getMaterialDiffuseB() const { return (materialdiffuse>>16)&0xFF; }
getMaterialDiffuseGPUgstate352 unsigned int getMaterialDiffuse() const { return materialdiffuse & 0xffffff; }
getMaterialEmissiveRGPUgstate353 unsigned int getMaterialEmissiveR() const { return materialemissive&0xFF; }
getMaterialEmissiveGGPUgstate354 unsigned int getMaterialEmissiveG() const { return (materialemissive>>8)&0xFF; }
getMaterialEmissiveBGPUgstate355 unsigned int getMaterialEmissiveB() const { return (materialemissive>>16)&0xFF; }
getMaterialEmissiveGPUgstate356 unsigned int getMaterialEmissive() const { return materialemissive & 0xffffff; }
getMaterialSpecularRGPUgstate357 unsigned int getMaterialSpecularR() const { return materialspecular&0xFF; }
getMaterialSpecularGGPUgstate358 unsigned int getMaterialSpecularG() const { return (materialspecular>>8)&0xFF; }
getMaterialSpecularBGPUgstate359 unsigned int getMaterialSpecularB() const { return (materialspecular>>16)&0xFF; }
getMaterialSpecularGPUgstate360 unsigned int getMaterialSpecular() const { return materialspecular & 0xffffff; }
getMaterialSpecularCoefGPUgstate361 float getMaterialSpecularCoef() const { return getFloat24(materialspecularcoef); }
getLightAmbientColorRGPUgstate362 unsigned int getLightAmbientColorR(int chan) const { return lcolor[chan*3]&0xFF; }
getLightAmbientColorGGPUgstate363 unsigned int getLightAmbientColorG(int chan) const { return (lcolor[chan*3]>>8)&0xFF; }
getLightAmbientColorBGPUgstate364 unsigned int getLightAmbientColorB(int chan) const { return (lcolor[chan*3]>>16)&0xFF; }
getLightAmbientColorGPUgstate365 unsigned int getLightAmbientColor(int chan) const { return lcolor[chan*3]&0xFFFFFF; }
getDiffuseColorRGPUgstate366 unsigned int getDiffuseColorR(int chan) const { return lcolor[1+chan*3]&0xFF; }
getDiffuseColorGGPUgstate367 unsigned int getDiffuseColorG(int chan) const { return (lcolor[1+chan*3]>>8)&0xFF; }
getDiffuseColorBGPUgstate368 unsigned int getDiffuseColorB(int chan) const { return (lcolor[1+chan*3]>>16)&0xFF; }
getDiffuseColorGPUgstate369 unsigned int getDiffuseColor(int chan) const { return lcolor[1+chan*3]&0xFFFFFF; }
getSpecularColorRGPUgstate370 unsigned int getSpecularColorR(int chan) const { return lcolor[2+chan*3]&0xFF; }
getSpecularColorGGPUgstate371 unsigned int getSpecularColorG(int chan) const { return (lcolor[2+chan*3]>>8)&0xFF; }
getSpecularColorBGPUgstate372 unsigned int getSpecularColorB(int chan) const { return (lcolor[2+chan*3]>>16)&0xFF; }
getSpecularColorGPUgstate373 unsigned int getSpecularColor(int chan) const { return lcolor[2+chan*3]&0xFFFFFF; }
374
getPatchDivisionUGPUgstate375 int getPatchDivisionU() const { return patchdivision & 0x7F; }
getPatchDivisionVGPUgstate376 int getPatchDivisionV() const { return (patchdivision >> 8) & 0x7F; }
377
378 // UV gen
getUVGenModeGPUgstate379 GETexMapMode getUVGenMode() const { return static_cast<GETexMapMode>(texmapmode & 3);} // 2 bits
getUVProjModeGPUgstate380 GETexProjMapMode getUVProjMode() const { return static_cast<GETexProjMapMode>((texmapmode >> 8) & 3);} // 2 bits
getUVLS0GPUgstate381 int getUVLS0() const { return texshade & 0x3; } // 2 bits
getUVLS1GPUgstate382 int getUVLS1() const { return (texshade >> 8) & 0x3; } // 2 bits
383
isTexCoordClampedSGPUgstate384 bool isTexCoordClampedS() const { return texwrap & 1; }
isTexCoordClampedTGPUgstate385 bool isTexCoordClampedT() const { return (texwrap >> 8) & 1; }
386
getScissorX1GPUgstate387 int getScissorX1() const { return scissor1 & 0x3FF; }
getScissorY1GPUgstate388 int getScissorY1() const { return (scissor1 >> 10) & 0x3FF; }
getScissorX2GPUgstate389 int getScissorX2() const { return scissor2 & 0x3FF; }
getScissorY2GPUgstate390 int getScissorY2() const { return (scissor2 >> 10) & 0x3FF; }
getRegionX1GPUgstate391 int getRegionX1() const { return region1 & 0x3FF; }
getRegionY1GPUgstate392 int getRegionY1() const { return (region1 >> 10) & 0x3FF; }
getRegionX2GPUgstate393 int getRegionX2() const { return (region2 & 0x3FF); }
getRegionY2GPUgstate394 int getRegionY2() const { return (region2 >> 10) & 0x3FF; }
395
isDepthClampEnabledGPUgstate396 bool isDepthClampEnabled() const { return depthClampEnable & 1; }
397
398 // Note that the X1/Y1/Z1 here does not mean the upper-left corner, but half the dimensions. X2/Y2/Z2 are the center.
getViewportXScaleGPUgstate399 float getViewportXScale() const { return getFloat24(viewportxscale); }
getViewportYScaleGPUgstate400 float getViewportYScale() const { return getFloat24(viewportyscale); }
getViewportZScaleGPUgstate401 float getViewportZScale() const { return getFloat24(viewportzscale); }
getViewportXCenterGPUgstate402 float getViewportXCenter() const { return getFloat24(viewportxcenter); }
getViewportYCenterGPUgstate403 float getViewportYCenter() const { return getFloat24(viewportycenter); }
getViewportZCenterGPUgstate404 float getViewportZCenter() const { return getFloat24(viewportzcenter); }
405
406 // Fixed 16 point.
getOffsetX16GPUgstate407 int getOffsetX16() const { return offsetx & 0xFFFF; }
getOffsetY16GPUgstate408 int getOffsetY16() const { return offsety & 0xFFFF; }
getOffsetXGPUgstate409 float getOffsetX() const { return (float)getOffsetX16() / 16.0f; }
getOffsetYGPUgstate410 float getOffsetY() const { return (float)getOffsetY16() / 16.0f; }
411
412 // Vertex type
isModeThroughGPUgstate413 bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; }
areNormalsReversedGPUgstate414 bool areNormalsReversed() const { return reversenormals & 1; }
isSkinningEnabledGPUgstate415 bool isSkinningEnabled() const { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); }
getNumMorphWeightsGPUgstate416 int getNumMorphWeights() const { return ((vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT) + 1; }
417
getPatchPrimitiveTypeGPUgstate418 GEPatchPrimType getPatchPrimitiveType() const { return static_cast<GEPatchPrimType>(patchprimitive & 3); }
isPatchNormalsReversedGPUgstate419 bool isPatchNormalsReversed() const { return patchfacing & 1; }
420
421 // Transfers
getTransferSrcAddressGPUgstate422 u32 getTransferSrcAddress() const { return (transfersrc & 0xFFFFF0) | ((transfersrcw & 0xFF0000) << 8); }
423 // Bits 0xf800 are ignored, > 0x400 is treated as 0.
getTransferSrcStrideGPUgstate424 u32 getTransferSrcStride() const { int stride = transfersrcw & 0x7F8; return stride > 0x400 ? 0 : stride; }
getTransferSrcXGPUgstate425 int getTransferSrcX() const { return (transfersrcpos >> 0) & 0x3FF; }
getTransferSrcYGPUgstate426 int getTransferSrcY() const { return (transfersrcpos >> 10) & 0x3FF; }
getTransferDstAddressGPUgstate427 u32 getTransferDstAddress() const { return (transferdst & 0xFFFFF0) | ((transferdstw & 0xFF0000) << 8); }
428 // Bits 0xf800 are ignored, > 0x400 is treated as 0.
getTransferDstStrideGPUgstate429 u32 getTransferDstStride() const { int stride = transferdstw & 0x7F8; return stride > 0x400 ? 0 : stride; }
getTransferDstXGPUgstate430 int getTransferDstX() const { return (transferdstpos >> 0) & 0x3FF; }
getTransferDstYGPUgstate431 int getTransferDstY() const { return (transferdstpos >> 10) & 0x3FF; }
getTransferWidthGPUgstate432 int getTransferWidth() const { return ((transfersize >> 0) & 0x3FF) + 1; }
getTransferHeightGPUgstate433 int getTransferHeight() const { return ((transfersize >> 10) & 0x3FF) + 1; }
getTransferBppGPUgstate434 int getTransferBpp() const { return (transferstart & 1) ? 4 : 2; }
435
436
437 void FastLoadBoneMatrix(u32 addr);
438
439 // Real data in the context ends here
440
441 void Reset();
442 void Save(u32_le *ptr);
443 void Restore(u32_le *ptr);
444 };
445
446 bool vertTypeIsSkinningEnabled(u32 vertType);
447
vertTypeGetNumBoneWeights(u32 vertType)448 inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); }
vertTypeGetWeightMask(u32 vertType)449 inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; }
450
451 // The rest is cached simplified/converted data for fast access.
452 // Does not need to be saved when saving/restoring context.
453 //
454 // Lots of this, however, is actual emulator state which must be saved when savestating.
455 // vertexAddr, indexAddr, offsetAddr for example.
456
457 struct UVScale {
458 float uScale, vScale;
459 float uOff, vOff;
460 };
461
462 #define FLAG_BIT(x) (1 << x)
463
464 // Some of these are OpenGL-specific even though this file is neutral, unfortunately.
465 // Might want to move this mechanism into the backend later.
466 enum {
467 GPU_SUPPORTS_DUALSOURCE_BLEND = FLAG_BIT(0),
468 GPU_SUPPORTS_GLSL_ES_300 = FLAG_BIT(1),
469 GPU_SUPPORTS_GLSL_330 = FLAG_BIT(2),
470 GPU_SUPPORTS_VS_RANGE_CULLING = FLAG_BIT(3),
471 GPU_SUPPORTS_BLEND_MINMAX = FLAG_BIT(4),
472 GPU_SUPPORTS_LOGIC_OP = FLAG_BIT(5),
473 GPU_USE_DEPTH_RANGE_HACK = FLAG_BIT(6),
474 GPU_SUPPORTS_WIDE_LINES = FLAG_BIT(7),
475 GPU_SUPPORTS_ANISOTROPY = FLAG_BIT(8),
476 GPU_USE_CLEAR_RAM_HACK = FLAG_BIT(9),
477 GPU_SUPPORTS_INSTANCE_RENDERING = FLAG_BIT(10),
478 GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(11),
479 GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(12),
480 GPU_SUPPORTS_16BIT_FORMATS = FLAG_BIT(13),
481 GPU_SUPPORTS_DEPTH_CLAMP = FLAG_BIT(14),
482 GPU_SUPPORTS_32BIT_INT_FSHADER = FLAG_BIT(15),
483 GPU_SUPPORTS_DEPTH_TEXTURE = FLAG_BIT(16),
484 GPU_SUPPORTS_ACCURATE_DEPTH = FLAG_BIT(17),
485 // Free bit: 18,
486 GPU_SUPPORTS_COPY_IMAGE = FLAG_BIT(19),
487 GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH = FLAG_BIT(20),
488 GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT = FLAG_BIT(21),
489 GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT = FLAG_BIT(22),
490 GPU_ROUND_DEPTH_TO_16BIT = FLAG_BIT(23), // Can be disabled either per game or if we use a real 16-bit depth buffer
491 GPU_SUPPORTS_TEXTURE_LOD_CONTROL = FLAG_BIT(24),
492 GPU_SUPPORTS_FRAMEBUFFER_BLIT = FLAG_BIT(26),
493 GPU_SUPPORTS_FRAMEBUFFER_BLIT_TO_DEPTH = FLAG_BIT(27),
494 GPU_SUPPORTS_TEXTURE_NPOT = FLAG_BIT(28),
495 GPU_NEEDS_Z_EQUAL_W_HACK = FLAG_BIT(29),
496 // Free bit: 30
497 GPU_PREFER_REVERSE_COLOR_ORDER = FLAG_BIT(31),
498 };
499
500 struct KnownVertexBounds {
501 u16 minU;
502 u16 minV;
503 u16 maxU;
504 u16 maxV;
505 };
506
507 enum class SubmitType {
508 DRAW,
509 BEZIER,
510 SPLINE,
511 HW_BEZIER,
512 HW_SPLINE,
513 };
514
515 struct GPUStateCache {
SupportsGPUStateCache516 bool Supports(u32 flags) { return (featureFlags & flags) != 0; } // Return true if ANY of flags are true.
SupportsAllGPUStateCache517 bool SupportsAll(u32 flags) { return (featureFlags & flags) == flags; } // Return true if ALL flags are true.
GetDirtyUniformsGPUStateCache518 uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; }
DirtyGPUStateCache519 void Dirty(u64 what) {
520 dirty |= what;
521 }
CleanUniformsGPUStateCache522 void CleanUniforms() {
523 dirty &= ~DIRTY_ALL_UNIFORMS;
524 }
CleanGPUStateCache525 void Clean(u64 what) {
526 dirty &= ~what;
527 }
IsDirtyGPUStateCache528 bool IsDirty(u64 what) const {
529 return (dirty & what) != 0ULL;
530 }
SetUseShaderDepalGPUStateCache531 void SetUseShaderDepal(bool depal) {
532 if (depal != useShaderDepal) {
533 useShaderDepal = depal;
534 Dirty(DIRTY_FRAGMENTSHADER_STATE);
535 }
536 }
SetTextureFullAlphaGPUStateCache537 void SetTextureFullAlpha(bool fullAlpha) {
538 if (fullAlpha != textureFullAlpha) {
539 textureFullAlpha = fullAlpha;
540 Dirty(DIRTY_FRAGMENTSHADER_STATE);
541 }
542 }
SetNeedShaderTexclampGPUStateCache543 void SetNeedShaderTexclamp(bool need) {
544 if (need != needShaderTexClamp) {
545 needShaderTexClamp = need;
546 Dirty(DIRTY_FRAGMENTSHADER_STATE);
547 if (need)
548 Dirty(DIRTY_TEXCLAMP);
549 }
550 }
SetAllowFramebufferReadGPUStateCache551 void SetAllowFramebufferRead(bool allow) {
552 if (allowFramebufferRead != allow) {
553 allowFramebufferRead = allow;
554 Dirty(DIRTY_FRAGMENTSHADER_STATE);
555 }
556 }
557
558 u32 featureFlags;
559
560 u32 vertexAddr;
561 u32 indexAddr;
562 u32 offsetAddr;
563
564 uint64_t dirty;
565
566 bool textureFullAlpha;
567 bool vertexFullAlpha;
568
569 int skipDrawReason;
570
571 UVScale uv;
572
573 bool bgraTexture;
574 bool needShaderTexClamp;
575 bool allowFramebufferRead;
576
577 float morphWeights[8];
578 u32 deferredVertTypeDirty;
579
580 u32 curTextureWidth;
581 u32 curTextureHeight;
582 u32 actualTextureHeight;
583 // Only applied when needShaderTexClamp = true.
584 u32 curTextureXOffset;
585 u32 curTextureYOffset;
586
587 float vpWidth;
588 float vpHeight;
589
590 float vpXOffset;
591 float vpYOffset;
592 float vpZOffset;
593 float vpWidthScale;
594 float vpHeightScale;
595 float vpDepthScale;
596
597 KnownVertexBounds vertBounds;
598
599 // TODO: These should be accessed from the current VFB object directly.
600 u32 curRTWidth;
601 u32 curRTHeight;
602 u32 curRTRenderWidth;
603 u32 curRTRenderHeight;
604
SetCurRTOffsetXGPUStateCache605 void SetCurRTOffsetX(int off) {
606 if (off != curRTOffsetX) {
607 curRTOffsetX = off;
608 Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
609 }
610 }
611 u32 curRTOffsetX;
612
613 // Set if we are doing hardware bezier/spline.
614 SubmitType submitType;
615 int spline_num_points_u;
616
617 bool useShaderDepal;
618 GEBufferFormat depalFramebufferFormat;
619
620 u32 getRelativeAddress(u32 data) const;
621 void Reset();
622 void DoState(PointerWrap &p);
623 };
624
625 class GPUInterface;
626 class GPUDebugInterface;
627
628 extern GPUgstate gstate;
629 extern GPUStateCache gstate_c;
630
getRelativeAddress(u32 data)631 inline u32 GPUStateCache::getRelativeAddress(u32 data) const {
632 u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;
633 return (gstate_c.offsetAddr + baseExtended) & 0x0FFFFFFF;
634 }
635