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