2012-11-01 15:19:01 +00:00
|
|
|
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
2012-11-04 22:01:49 +00:00
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
2012-11-01 15:19:01 +00:00
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official git repository and contact information can be found at
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2013-08-14 18:42:13 +00:00
|
|
|
#include <cmath>
|
2013-11-10 12:18:52 +00:00
|
|
|
|
2012-11-01 15:19:01 +00:00
|
|
|
#include "../Globals.h"
|
2012-11-24 14:19:29 +00:00
|
|
|
#include "ge_constants.h"
|
2013-09-20 16:51:26 +00:00
|
|
|
#include "Common/Common.h"
|
2012-11-01 15:19:01 +00:00
|
|
|
|
2014-04-13 21:02:00 +00:00
|
|
|
class PointerWrap;
|
|
|
|
|
2013-08-10 09:22:22 +00:00
|
|
|
// PSP uses a curious 24-bit float - it's basically the top 24 bits of a regular IEEE754 32-bit float.
|
|
|
|
// This is used for light positions, transform matrices, you name it.
|
|
|
|
inline float getFloat24(unsigned int data)
|
|
|
|
{
|
|
|
|
data <<= 8;
|
|
|
|
float f;
|
|
|
|
memcpy(&f, &data, 4);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// in case we ever want to generate PSP display lists...
|
|
|
|
inline unsigned int toFloat24(float f) {
|
|
|
|
unsigned int i;
|
|
|
|
memcpy(&i, &f, 4);
|
|
|
|
return i >> 8;
|
|
|
|
}
|
|
|
|
|
2012-11-01 15:19:01 +00:00
|
|
|
struct GPUgstate
|
|
|
|
{
|
2012-12-21 15:49:42 +00:00
|
|
|
// Getting rid of this ugly union in favor of the accessor functions
|
|
|
|
// might be a good idea....
|
2012-11-01 15:19:01 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
u32 cmdmem[256];
|
|
|
|
struct
|
|
|
|
{
|
2012-12-05 03:45:28 +00:00
|
|
|
u32 nop,
|
|
|
|
vaddr,
|
2012-11-01 15:19:01 +00:00
|
|
|
iaddr,
|
|
|
|
pad00,
|
|
|
|
prim,
|
|
|
|
bezier,
|
|
|
|
spline,
|
|
|
|
boundBox,
|
|
|
|
jump,
|
|
|
|
bjump,
|
|
|
|
call,
|
|
|
|
ret,
|
|
|
|
end,
|
|
|
|
pad01,
|
|
|
|
signal,
|
|
|
|
finish,
|
|
|
|
base,
|
|
|
|
pad02,
|
|
|
|
vertType,
|
|
|
|
offsetAddr,
|
|
|
|
origin,
|
|
|
|
region1,
|
|
|
|
region2,
|
|
|
|
lightingEnable,
|
|
|
|
lightEnable[4],
|
|
|
|
clipEnable,
|
|
|
|
cullfaceEnable,
|
|
|
|
textureMapEnable,
|
|
|
|
fogEnable,
|
|
|
|
ditherEnable,
|
|
|
|
alphaBlendEnable,
|
|
|
|
alphaTestEnable,
|
|
|
|
zTestEnable,
|
|
|
|
stencilTestEnable,
|
|
|
|
antiAliasEnable,
|
|
|
|
patchCullEnable,
|
|
|
|
colorTestEnable,
|
|
|
|
logicOpEnable,
|
|
|
|
pad03,
|
|
|
|
boneMatrixNumber,
|
|
|
|
boneMatrixData,
|
|
|
|
morphwgt[8], //dont use
|
2012-12-28 18:33:26 +00:00
|
|
|
pad04[2],
|
|
|
|
patchdivision,
|
|
|
|
patchprimitive,
|
|
|
|
patchfacing,
|
|
|
|
pad04_a,
|
2012-11-01 15:19:01 +00:00
|
|
|
|
2013-07-22 00:43:08 +00:00
|
|
|
worldmtxnum, // 0x3A
|
|
|
|
worldmtxdata, // 0x3B
|
|
|
|
viewmtxnum, // 0x3C
|
|
|
|
viewmtxdata, // 0x3D
|
|
|
|
projmtxnum, // 0x3E
|
|
|
|
projmtxdata, // 0x3F
|
|
|
|
texmtxnum, // 0x40
|
|
|
|
texmtxdata, // 0x41
|
|
|
|
|
|
|
|
viewportx1, // 0x42
|
|
|
|
viewporty1, // 0x43
|
|
|
|
viewportz1, // 0x44
|
|
|
|
viewportx2, // 0x45
|
|
|
|
viewporty2, // 0x46
|
|
|
|
viewportz2, // 0x47
|
|
|
|
texscaleu, // 0x48
|
|
|
|
texscalev, // 0x49
|
|
|
|
texoffsetu, // 0x4A
|
|
|
|
texoffsetv, // 0x4B
|
|
|
|
offsetx, // 0x4C
|
|
|
|
offsety, // 0x4D
|
2012-11-01 15:19:01 +00:00
|
|
|
pad111[2],
|
2013-07-22 00:43:08 +00:00
|
|
|
shademodel, // 0x50
|
|
|
|
reversenormals, // 0x51
|
2012-11-01 15:19:01 +00:00
|
|
|
pad222,
|
2013-07-22 00:43:08 +00:00
|
|
|
materialupdate, // 0x53
|
|
|
|
materialemissive, // 0x54
|
|
|
|
materialambient, // 0x55
|
|
|
|
materialdiffuse, // 0x56
|
|
|
|
materialspecular, // 0x57
|
|
|
|
materialalpha, // 0x58
|
2012-11-25 17:12:20 +00:00
|
|
|
pad333[2],
|
2013-07-22 00:43:08 +00:00
|
|
|
materialspecularcoef, // 0x5B
|
|
|
|
ambientcolor, // 0x5C
|
|
|
|
ambientalpha, // 0x5D
|
2013-07-22 00:56:58 +00:00
|
|
|
lmode, // 0x5E
|
|
|
|
ltype[4], // 0x5F-0x62
|
|
|
|
lpos[12], // 0x63-0x6E
|
|
|
|
ldir[12], // 0x6F-0x7A
|
|
|
|
latt[12], // 0x7B-0x86
|
|
|
|
lconv[4], // 0x87-0x8A
|
|
|
|
lcutoff[4], // 0x8B-0x8E
|
2013-07-22 01:40:19 +00:00
|
|
|
lcolor[12], // 0x8F-0x9A
|
|
|
|
cullmode, // 0x9B
|
|
|
|
fbptr, // 0x9C
|
|
|
|
fbwidth, // 0x9D
|
|
|
|
zbptr, // 0x9E
|
|
|
|
zbwidth, // 0x9F
|
|
|
|
texaddr[8], // 0xA0-0xA7
|
|
|
|
texbufwidth[8], // 0xA8-0xAF
|
|
|
|
clutaddr, // 0xB0
|
|
|
|
clutaddrupper, // 0xB1
|
|
|
|
transfersrc, // 0xB2
|
|
|
|
transfersrcw, // 0xB3
|
|
|
|
transferdst, // 0xB4
|
|
|
|
transferdstw, // 0xB5
|
2012-11-01 15:19:01 +00:00
|
|
|
padxxx[2],
|
2013-07-22 01:40:19 +00:00
|
|
|
texsize[8], // 0xB8-BF
|
|
|
|
texmapmode, // 0xC0
|
|
|
|
texshade, // 0xC1
|
|
|
|
texmode, // 0xC2
|
|
|
|
texformat, // 0xC3
|
|
|
|
loadclut, // 0xC4
|
2013-07-22 01:59:18 +00:00
|
|
|
clutformat, // 0xC5
|
|
|
|
texfilter, // 0xC6
|
|
|
|
texwrap, // 0xC7
|
|
|
|
texlevel, // 0xC8
|
|
|
|
texfunc, // 0xC9
|
|
|
|
texenvcolor, // 0xCA
|
|
|
|
texflush, // 0xCB
|
|
|
|
texsync, // 0xCC
|
|
|
|
fog1, // 0xCD
|
|
|
|
fog2, // 0xCE
|
|
|
|
fogcolor, // 0xCF
|
|
|
|
texlodslope, // 0xD0
|
|
|
|
padxxxxxx, // 0xD1
|
|
|
|
framebufpixformat, // 0xD2
|
|
|
|
clearmode, // 0xD3
|
2012-11-01 15:19:01 +00:00
|
|
|
scissor1,
|
|
|
|
scissor2,
|
|
|
|
minz,
|
|
|
|
maxz,
|
|
|
|
colortest,
|
|
|
|
colorref,
|
2014-06-16 07:33:48 +00:00
|
|
|
colortestmask,
|
2012-11-01 15:19:01 +00:00
|
|
|
alphatest,
|
|
|
|
stenciltest,
|
|
|
|
stencilop,
|
|
|
|
ztestfunc,
|
|
|
|
blend,
|
|
|
|
blendfixa,
|
|
|
|
blendfixb,
|
|
|
|
dith1,
|
|
|
|
dith2,
|
|
|
|
dith3,
|
|
|
|
dith4,
|
2013-07-22 01:59:18 +00:00
|
|
|
lop, // 0xE6
|
2012-11-01 15:19:01 +00:00
|
|
|
zmsk,
|
2013-01-12 11:51:09 +00:00
|
|
|
pmskc,
|
|
|
|
pmska,
|
2012-11-22 19:57:41 +00:00
|
|
|
transferstart,
|
|
|
|
transfersrcpos,
|
|
|
|
transferdstpos,
|
2012-12-17 18:04:19 +00:00
|
|
|
pad99,
|
|
|
|
transfersize; // 0xEE
|
2012-11-01 15:19:01 +00:00
|
|
|
|
2012-12-17 18:04:19 +00:00
|
|
|
u32 pad05[0xFF- 0xEE];
|
2012-11-01 15:19:01 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2012-11-18 12:04:49 +00:00
|
|
|
float worldMatrix[12];
|
|
|
|
float viewMatrix[12];
|
|
|
|
float projMatrix[16];
|
|
|
|
float tgenMatrix[12];
|
2012-11-25 11:25:07 +00:00
|
|
|
float boneMatrix[12 * 8]; // Eight bone matrices.
|
2012-11-24 14:19:29 +00:00
|
|
|
|
2014-06-21 15:29:38 +00:00
|
|
|
// We ignore the high bits of the framebuffer in fbwidth - even 0x08000000 renders to vRAM.
|
|
|
|
u32 getFrameBufRawAddress() const { return (fbptr & 0xFFFFFF); }
|
2013-10-06 22:51:31 +00:00
|
|
|
// 0x44000000 is uncached VRAM.
|
|
|
|
u32 getFrameBufAddress() const { return 0x44000000 | getFrameBufRawAddress(); }
|
2013-07-21 17:15:28 +00:00
|
|
|
GEBufferFormat FrameBufFormat() const { return static_cast<GEBufferFormat>(framebufpixformat & 3); }
|
2013-12-15 17:48:44 +00:00
|
|
|
int FrameBufStride() const { return fbwidth&0x7FC; }
|
2014-06-21 15:29:38 +00:00
|
|
|
u32 getDepthBufRawAddress() const { return (zbptr & 0xFFFFFF); }
|
2013-10-06 22:51:31 +00:00
|
|
|
u32 getDepthBufAddress() const { return 0x44000000 | getDepthBufRawAddress(); }
|
2013-12-15 17:48:44 +00:00
|
|
|
int DepthBufStride() const { return zbwidth&0x7FC; }
|
2013-06-29 21:41:21 +00:00
|
|
|
|
2012-12-21 15:49:42 +00:00
|
|
|
// Pixel Pipeline
|
2012-11-28 12:45:22 +00:00
|
|
|
bool isModeClear() const { return clearmode & 1; }
|
2013-07-29 09:25:07 +00:00
|
|
|
bool isFogEnabled() const { return fogEnable & 1; }
|
|
|
|
|
|
|
|
// Cull
|
2012-11-28 12:45:22 +00:00
|
|
|
bool isCullEnabled() const { return cullfaceEnable & 1; }
|
2012-12-21 15:49:42 +00:00
|
|
|
int getCullMode() const { return cullmode & 1; }
|
2013-12-10 12:48:20 +00:00
|
|
|
|
|
|
|
// Color Mask
|
2013-08-03 06:56:37 +00:00
|
|
|
bool isClearModeColorMask() const { return (clearmode&0x100) != 0; }
|
|
|
|
bool isClearModeAlphaMask() const { return (clearmode&0x200) != 0; }
|
2013-08-24 17:20:07 +00:00
|
|
|
bool isClearModeDepthMask() const { return (clearmode&0x400) != 0; }
|
2013-11-10 08:54:19 +00:00
|
|
|
u32 getClearModeColorMask() const { return ((clearmode&0x100) ? 0 : 0xFFFFFF) | ((clearmode&0x200) ? 0 : 0xFF000000); }
|
2013-07-29 09:25:07 +00:00
|
|
|
|
|
|
|
// Blend
|
2013-08-27 19:48:03 +00:00
|
|
|
GEBlendSrcFactor getBlendFuncA() const { return (GEBlendSrcFactor)(blend & 0xF); }
|
2013-12-10 12:48:20 +00:00
|
|
|
GEBlendDstFactor getBlendFuncB() const { return (GEBlendDstFactor)((blend >> 4) & 0xF); }
|
2012-11-28 12:45:22 +00:00
|
|
|
u32 getFixA() const { return blendfixa & 0xFFFFFF; }
|
|
|
|
u32 getFixB() const { return blendfixb & 0xFFFFFF; }
|
2013-09-14 14:34:36 +00:00
|
|
|
GEBlendMode getBlendEq() const { return static_cast<GEBlendMode>((blend >> 8) & 0x7); }
|
2013-02-27 14:37:17 +00:00
|
|
|
bool isAlphaBlendEnabled() const { return alphaBlendEnable & 1; }
|
2013-08-30 12:46:36 +00:00
|
|
|
|
|
|
|
// AntiAlias
|
|
|
|
bool isAntiAliasEnabled() const { return antiAliasEnable & 1; }
|
2013-07-29 09:25:07 +00:00
|
|
|
|
|
|
|
// Dither
|
2013-02-27 14:37:17 +00:00
|
|
|
bool isDitherEnabled() const { return ditherEnable & 1; }
|
2013-07-22 01:35:31 +00:00
|
|
|
|
2013-07-29 09:25:07 +00:00
|
|
|
// Color Mask
|
2013-07-22 01:59:18 +00:00
|
|
|
u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); }
|
|
|
|
bool isLogicOpEnabled() const { return logicOpEnable & 1; }
|
|
|
|
GELogicOp getLogicOp() const { return static_cast<GELogicOp>(lop & 0xF); }
|
2013-07-29 09:25:07 +00:00
|
|
|
|
|
|
|
// Depth Test
|
|
|
|
bool isDepthTestEnabled() const { return zTestEnable & 1; }
|
|
|
|
bool isDepthWriteEnabled() const { return !(zmsk & 1); }
|
2013-09-05 05:59:09 +00:00
|
|
|
GEComparison getDepthTestFunction() const { return static_cast<GEComparison>(ztestfunc & 0x7); }
|
2013-07-29 09:25:07 +00:00
|
|
|
u16 getDepthRangeMin() const { return minz & 0xFFFF; }
|
|
|
|
u16 getDepthRangeMax() const { return maxz & 0xFFFF; }
|
|
|
|
|
|
|
|
// Stencil Test
|
2013-07-22 01:48:14 +00:00
|
|
|
bool isStencilTestEnabled() const { return stencilTestEnable & 1; }
|
2013-07-22 01:54:17 +00:00
|
|
|
GEComparison getStencilTestFunction() const { return static_cast<GEComparison>(stenciltest & 0x7); }
|
2013-07-22 01:48:14 +00:00
|
|
|
int getStencilTestRef() const { return (stenciltest>>8) & 0xFF; }
|
|
|
|
int getStencilTestMask() const { return (stenciltest>>16) & 0xFF; }
|
2013-07-22 01:54:17 +00:00
|
|
|
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); }
|
2013-07-22 01:48:14 +00:00
|
|
|
|
2013-07-29 09:25:07 +00:00
|
|
|
// Alpha Test
|
2013-07-22 02:06:44 +00:00
|
|
|
bool isAlphaTestEnabled() const { return alphaTestEnable & 1; }
|
|
|
|
GEComparison getAlphaTestFunction() { return static_cast<GEComparison>(alphatest & 0x7); }
|
|
|
|
int getAlphaTestRef() const { return (alphatest >> 8) & 0xFF; }
|
|
|
|
int getAlphaTestMask() const { return (alphatest >> 16) & 0xFF; }
|
2013-07-29 09:25:07 +00:00
|
|
|
|
|
|
|
// Color Test
|
2013-07-22 02:06:44 +00:00
|
|
|
bool isColorTestEnabled() const { return colorTestEnable & 1; }
|
|
|
|
GEComparison getColorTestFunction() { return static_cast<GEComparison>(colortest & 0x3); }
|
|
|
|
u32 getColorTestRef() const { return colorref & 0xFFFFFF; }
|
2014-06-16 07:33:48 +00:00
|
|
|
u32 getColorTestMask() const { return colortestmask & 0xFFFFFF; }
|
2013-07-22 02:06:44 +00:00
|
|
|
|
2013-07-22 01:35:31 +00:00
|
|
|
// Texturing
|
2013-09-16 04:39:28 +00:00
|
|
|
// TODO: Verify getTextureAddress() alignment?
|
|
|
|
u32 getTextureAddress(int level) const { return (texaddr[level] & 0xFFFFF0) | ((texbufwidth[level] << 8) & 0x0F000000); }
|
2013-07-30 15:23:02 +00:00
|
|
|
int getTextureWidth(int level) const { return 1 << (texsize[level] & 0xf);}
|
|
|
|
int getTextureHeight(int level) const { return 1 << ((texsize[level] >> 8) & 0xf);}
|
2013-09-08 08:09:40 +00:00
|
|
|
u16 getTextureDimension(int level) const { return texsize[level] & 0xf0f;}
|
2014-04-18 14:00:53 +00:00
|
|
|
GETexLevelMode getTexLevelMode() const { return static_cast<GETexLevelMode>(texlevel & 0x3); }
|
2013-07-22 00:56:58 +00:00
|
|
|
bool isTextureMapEnabled() const { return textureMapEnable & 1; }
|
2013-07-22 01:35:52 +00:00
|
|
|
GETexFunc getTextureFunction() const { return static_cast<GETexFunc>(texfunc & 0x7); }
|
2013-07-22 01:35:31 +00:00
|
|
|
bool isColorDoublingEnabled() const { return (texfunc & 0x10000) != 0; }
|
2013-08-20 13:28:16 +00:00
|
|
|
bool isTextureAlphaUsed() const { return (texfunc & 0x100) != 0; }
|
2013-07-22 01:44:04 +00:00
|
|
|
GETextureFormat getTextureFormat() const { return static_cast<GETextureFormat>(texformat & 0xF); }
|
2013-07-29 09:25:07 +00:00
|
|
|
bool isTextureFormatIndexed() const { return (texformat & 4) != 0; } // GE_TFMT_CLUT4 - GE_TFMT_CLUT32 are 0b1xx.
|
2013-07-22 01:35:31 +00:00
|
|
|
int getTextureEnvColR() const { return texenvcolor&0xFF; }
|
|
|
|
int getTextureEnvColG() const { return (texenvcolor>>8)&0xFF; }
|
|
|
|
int getTextureEnvColB() const { return (texenvcolor>>16)&0xFF; }
|
2013-08-24 18:10:56 +00:00
|
|
|
u32 getClutAddress() const { return (clutaddr & 0x00FFFFFF) | ((clutaddrupper << 8) & 0x0F000000); }
|
|
|
|
int getClutLoadBytes() const { return (loadclut & 0x3F) * 32; }
|
2013-11-12 14:29:57 +00:00
|
|
|
int getClutLoadBlocks() const { return (loadclut & 0x3F); }
|
2013-07-22 01:44:04 +00:00
|
|
|
GEPaletteFormat getClutPaletteFormat() { return static_cast<GEPaletteFormat>(clutformat & 3); }
|
2013-07-22 01:40:19 +00:00
|
|
|
int getClutIndexShift() const { return (clutformat >> 2) & 0x1F; }
|
|
|
|
int getClutIndexMask() const { return (clutformat >> 8) & 0xFF; }
|
|
|
|
int getClutIndexStartPos() const { return ((clutformat >> 16) & 0x1F) << 4; }
|
2013-08-24 18:10:56 +00:00
|
|
|
int transformClutIndex(int index) const { return ((index >> getClutIndexShift()) & getClutIndexMask()) | getClutIndexStartPos(); }
|
2013-07-29 09:25:07 +00:00
|
|
|
bool isClutIndexSimple() const { return (clutformat & ~3) == 0xC500FF00; } // Meaning, no special mask, shift, or start pos.
|
2013-08-24 17:51:17 +00:00
|
|
|
bool isTextureSwizzled() const { return texmode & 1; }
|
2013-12-09 11:46:13 +00:00
|
|
|
bool isClutSharedForMipmaps() const { return (texmode & 0x100) == 0; }
|
2014-06-15 17:31:16 +00:00
|
|
|
int getTextureMaxLevel() const { return (texmode >> 16) & 0x7; }
|
2013-07-22 01:40:19 +00:00
|
|
|
|
2013-07-22 01:35:31 +00:00
|
|
|
// Lighting
|
2013-03-27 10:21:02 +00:00
|
|
|
bool isLightingEnabled() const { return lightingEnable & 1; }
|
2013-07-22 01:13:55 +00:00
|
|
|
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_BOTHWITHPOWDIFFUSE; }
|
|
|
|
bool isUsingSpecularLight(int chan) const { return getLightComputation(chan) != GE_LIGHTCOMP_ONLYDIFFUSE; }
|
2013-07-22 00:43:08 +00:00
|
|
|
bool isUsingSecondaryColor() const { return lmode & 1; }
|
2013-07-22 01:13:55 +00:00
|
|
|
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; }
|
2013-09-14 14:34:36 +00:00
|
|
|
GEShadeMode getShadeMode() const { return static_cast<GEShadeMode>(shademodel & 1); }
|
2013-07-22 00:43:08 +00:00
|
|
|
unsigned int getAmbientR() const { return ambientcolor&0xFF; }
|
|
|
|
unsigned int getAmbientG() const { return (ambientcolor>>8)&0xFF; }
|
|
|
|
unsigned int getAmbientB() const { return (ambientcolor>>16)&0xFF; }
|
|
|
|
unsigned int getAmbientA() const { return ambientalpha&0xFF; }
|
|
|
|
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; }
|
2014-03-18 06:05:48 +00:00
|
|
|
unsigned int getMaterialAmbientRGBA() const { return (materialambient & 0x00FFFFFF) | (materialalpha << 24); }
|
2013-07-22 00:56:58 +00:00
|
|
|
unsigned int getMaterialDiffuseR() const { return materialdiffuse&0xFF; }
|
|
|
|
unsigned int getMaterialDiffuseG() const { return (materialdiffuse>>8)&0xFF; }
|
|
|
|
unsigned int getMaterialDiffuseB() const { return (materialdiffuse>>16)&0xFF; }
|
2013-07-22 00:43:08 +00:00
|
|
|
unsigned int getMaterialEmissiveR() const { return materialemissive&0xFF; }
|
|
|
|
unsigned int getMaterialEmissiveG() const { return (materialemissive>>8)&0xFF; }
|
|
|
|
unsigned int getMaterialEmissiveB() const { return (materialemissive>>16)&0xFF; }
|
2013-07-22 01:29:27 +00:00
|
|
|
unsigned int getMaterialSpecularR() const { return materialspecular&0xFF; }
|
|
|
|
unsigned int getMaterialSpecularG() const { return (materialspecular>>8)&0xFF; }
|
|
|
|
unsigned int getMaterialSpecularB() const { return (materialspecular>>16)&0xFF; }
|
|
|
|
unsigned int getLightAmbientColorR(int chan) const { return lcolor[chan*3]&0xFF; }
|
|
|
|
unsigned int getLightAmbientColorG(int chan) const { return (lcolor[chan*3]>>8)&0xFF; }
|
|
|
|
unsigned int getLightAmbientColorB(int chan) const { return (lcolor[chan*3]>>16)&0xFF; }
|
2013-07-22 00:56:58 +00:00
|
|
|
unsigned int getDiffuseColorR(int chan) const { return lcolor[1+chan*3]&0xFF; }
|
|
|
|
unsigned int getDiffuseColorG(int chan) const { return (lcolor[1+chan*3]>>8)&0xFF; }
|
|
|
|
unsigned int getDiffuseColorB(int chan) const { return (lcolor[1+chan*3]>>16)&0xFF; }
|
2013-07-22 01:29:27 +00:00
|
|
|
unsigned int getSpecularColorR(int chan) const { return lcolor[2+chan*3]&0xFF; }
|
|
|
|
unsigned int getSpecularColorG(int chan) const { return (lcolor[2+chan*3]>>8)&0xFF; }
|
|
|
|
unsigned int getSpecularColorB(int chan) const { return (lcolor[2+chan*3]>>16)&0xFF; }
|
|
|
|
|
2013-09-22 07:51:32 +00:00
|
|
|
int getPatchDivisionU() const { return patchdivision & 0x7F; }
|
|
|
|
int getPatchDivisionV() const { return (patchdivision >> 8) & 0x7F; }
|
|
|
|
|
2012-12-21 15:49:42 +00:00
|
|
|
// UV gen
|
2013-07-24 11:55:10 +00:00
|
|
|
GETexMapMode getUVGenMode() const { return static_cast<GETexMapMode>(texmapmode & 3);} // 2 bits
|
|
|
|
GETexProjMapMode getUVProjMode() const { return static_cast<GETexProjMapMode>((texmapmode >> 8) & 3);} // 2 bits
|
2012-12-20 13:10:42 +00:00
|
|
|
int getUVLS0() const { return texshade & 0x3; } // 2 bits
|
|
|
|
int getUVLS1() const { return (texshade >> 8) & 0x3; } // 2 bits
|
2013-07-23 18:47:18 +00:00
|
|
|
|
|
|
|
bool isTexCoordClampedS() const { return texwrap & 1; }
|
|
|
|
bool isTexCoordClampedT() const { return (texwrap >> 8) & 1; }
|
|
|
|
|
2013-03-15 23:40:37 +00:00
|
|
|
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; }
|
2013-07-10 19:57:25 +00:00
|
|
|
int getRegionX1() const { return region1 & 0x3FF; }
|
|
|
|
int getRegionY1() const { return (region1 >> 10) & 0x3FF; }
|
|
|
|
int getRegionX2() const { return (region2 & 0x3FF); }
|
2013-09-14 14:34:36 +00:00
|
|
|
int getRegionY2() const { return (region2 >> 10) & 0x3FF; }
|
2013-09-14 18:06:48 +00:00
|
|
|
float getViewportX1() const { return fabsf(getFloat24(viewportx1) * 2.0f); }
|
|
|
|
float getViewportY1() const { return fabsf(getFloat24(viewporty1) * 2.0f); }
|
|
|
|
// Fixed 16 point.
|
|
|
|
int getOffsetX16() const { return offsetx & 0xFFFF; }
|
|
|
|
// Fixed 16 point.
|
|
|
|
int getOffsetY16() const { return offsety & 0xFFFF; }
|
|
|
|
float getOffsetX() const { return (float)getOffsetX16() / 16.0f; }
|
|
|
|
float getOffsetY() const { return (float)getOffsetY16() / 16.0f; }
|
2013-07-10 19:57:25 +00:00
|
|
|
|
2012-12-21 15:49:42 +00:00
|
|
|
// Vertex type
|
|
|
|
bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; }
|
2013-08-24 18:11:34 +00:00
|
|
|
bool areNormalsReversed() const { return reversenormals & 1; }
|
2013-12-16 12:42:45 +00:00
|
|
|
bool isSkinningEnabled() const { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); }
|
|
|
|
|
2013-07-24 15:59:21 +00:00
|
|
|
GEPatchPrimType getPatchPrimitiveType() const { return static_cast<GEPatchPrimType>(patchprimitive & 3); }
|
|
|
|
|
2013-08-24 17:41:45 +00:00
|
|
|
// Transfers
|
|
|
|
u32 getTransferSrcAddress() const { return (transfersrc & 0xFFFFF0) | ((transfersrcw & 0xFF0000) << 8); }
|
2013-11-25 09:03:22 +00:00
|
|
|
// Bits 0xf800 are ignored, > 0x400 is treated as 0.
|
|
|
|
u32 getTransferSrcStride() const { int stride = transfersrcw & 0x7F8; return stride > 0x400 ? 0 : stride; }
|
2013-08-24 17:41:45 +00:00
|
|
|
int getTransferSrcX() const { return (transfersrcpos >> 0) & 0x3FF; }
|
|
|
|
int getTransferSrcY() const { return (transfersrcpos >> 10) & 0x3FF; }
|
|
|
|
u32 getTransferDstAddress() const { return (transferdst & 0xFFFFF0) | ((transferdstw & 0xFF0000) << 8); }
|
2013-11-25 09:03:22 +00:00
|
|
|
// Bits 0xf800 are ignored, > 0x400 is treated as 0.
|
|
|
|
u32 getTransferDstStride() const { int stride = transferdstw & 0x7F8; return stride > 0x400 ? 0 : stride; }
|
2013-08-24 17:41:45 +00:00
|
|
|
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; }
|
|
|
|
|
2013-11-14 13:02:31 +00:00
|
|
|
|
|
|
|
void FastLoadBoneMatrix(u32 addr);
|
|
|
|
|
|
|
|
// Real data in the context ends here
|
2013-09-20 07:33:32 +00:00
|
|
|
|
|
|
|
void Save(u32_le *ptr);
|
|
|
|
void Restore(u32_le *ptr);
|
2012-12-20 13:10:42 +00:00
|
|
|
};
|
2013-02-18 22:44:32 +00:00
|
|
|
|
|
|
|
enum SkipDrawReasonFlags {
|
|
|
|
SKIPDRAW_SKIPFRAME = 1,
|
2013-03-03 12:00:21 +00:00
|
|
|
SKIPDRAW_NON_DISPLAYED_FB = 2, // Skip drawing to FBO:s that have not been displayed.
|
|
|
|
SKIPDRAW_BAD_FB_TEXTURE = 4,
|
2014-06-29 22:06:47 +00:00
|
|
|
SKIPDRAW_WINDOW_MINIMIZED = 8, // Don't draw when the host window is minimized.
|
2013-02-18 22:44:32 +00:00
|
|
|
};
|
|
|
|
|
2013-11-10 12:18:52 +00:00
|
|
|
bool vertTypeIsSkinningEnabled(u32 vertType);
|
|
|
|
|
2013-09-21 21:37:14 +00:00
|
|
|
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; }
|
2013-09-21 21:44:11 +00:00
|
|
|
inline int vertTypeGetTexCoordMask(u32 vertType) { return vertType & GE_VTYPE_TC_MASK; }
|
2013-09-21 21:37:14 +00:00
|
|
|
|
|
|
|
|
2012-11-18 22:14:50 +00:00
|
|
|
// The rest is cached simplified/converted data for fast access.
|
|
|
|
// Does not need to be saved when saving/restoring context.
|
2013-07-27 22:18:41 +00:00
|
|
|
|
|
|
|
struct UVScale {
|
|
|
|
float uScale, vScale;
|
|
|
|
float uOff, vOff;
|
|
|
|
};
|
|
|
|
|
2014-04-13 21:02:00 +00:00
|
|
|
enum TextureChangeReason {
|
2014-04-13 21:45:55 +00:00
|
|
|
TEXCHANGE_UNCHANGED = 0x00,
|
|
|
|
TEXCHANGE_UPDATED = 0x01,
|
|
|
|
TEXCHANGE_PARAMSONLY = 0x02,
|
2014-04-13 21:02:00 +00:00
|
|
|
};
|
|
|
|
|
2012-11-18 12:04:49 +00:00
|
|
|
struct GPUStateCache
|
|
|
|
{
|
2012-11-01 15:19:01 +00:00
|
|
|
u32 vertexAddr;
|
|
|
|
u32 indexAddr;
|
|
|
|
|
2013-02-02 12:38:34 +00:00
|
|
|
u32 offsetAddr;
|
|
|
|
|
2014-04-13 21:45:55 +00:00
|
|
|
u8 textureChanged;
|
2013-05-08 14:52:54 +00:00
|
|
|
bool textureFullAlpha;
|
2014-05-11 21:11:36 +00:00
|
|
|
bool textureSimpleAlpha;
|
2014-03-23 15:29:11 +00:00
|
|
|
bool vertexFullAlpha;
|
2013-04-21 22:08:47 +00:00
|
|
|
bool framebufChanged;
|
2012-11-01 15:19:01 +00:00
|
|
|
|
2013-02-18 22:44:32 +00:00
|
|
|
int skipDrawReason;
|
|
|
|
|
2013-07-27 22:18:41 +00:00
|
|
|
UVScale uv;
|
2013-02-14 23:30:02 +00:00
|
|
|
bool flipTexture;
|
2014-06-07 19:21:52 +00:00
|
|
|
bool needShaderTexClamp;
|
2014-08-04 02:56:53 +00:00
|
|
|
bool allowShaderBlend;
|
2013-02-14 23:30:02 +00:00
|
|
|
|
2012-11-01 15:19:01 +00:00
|
|
|
float morphWeights[8];
|
|
|
|
|
|
|
|
u32 curTextureWidth;
|
|
|
|
u32 curTextureHeight;
|
2013-02-21 20:37:19 +00:00
|
|
|
u32 actualTextureHeight;
|
2014-06-08 20:52:05 +00:00
|
|
|
// Only applied when needShaderTexClamp = true.
|
|
|
|
u32 curTextureXOffset;
|
|
|
|
u32 curTextureYOffset;
|
2012-11-26 19:38:26 +00:00
|
|
|
|
|
|
|
float vpWidth;
|
|
|
|
float vpHeight;
|
2013-02-02 12:38:34 +00:00
|
|
|
|
2013-03-15 23:40:37 +00:00
|
|
|
u32 curRTWidth;
|
|
|
|
u32 curRTHeight;
|
2014-06-14 05:49:28 +00:00
|
|
|
u32 curRTRenderWidth;
|
|
|
|
u32 curRTRenderHeight;
|
2014-06-15 00:08:41 +00:00
|
|
|
u32 cutRTOffsetX;
|
2014-06-14 05:49:28 +00:00
|
|
|
|
2013-02-02 22:47:35 +00:00
|
|
|
u32 getRelativeAddress(u32 data) const;
|
2014-04-13 21:02:00 +00:00
|
|
|
void DoState(PointerWrap &p);
|
2012-11-18 12:04:49 +00:00
|
|
|
};
|
2012-11-01 15:19:01 +00:00
|
|
|
|
2012-11-18 12:04:49 +00:00
|
|
|
// TODO: Implement support for these.
|
2013-08-07 21:32:28 +00:00
|
|
|
struct GPUStatistics {
|
2013-08-07 20:32:04 +00:00
|
|
|
void Reset() {
|
|
|
|
// Never add a vtable :)
|
2012-11-25 11:25:07 +00:00
|
|
|
memset(this, 0, sizeof(*this));
|
2012-11-22 22:07:15 +00:00
|
|
|
}
|
2013-08-07 20:32:04 +00:00
|
|
|
void ResetFrame() {
|
2012-11-22 22:07:15 +00:00
|
|
|
numDrawCalls = 0;
|
2013-01-19 16:05:08 +00:00
|
|
|
numCachedDrawCalls = 0;
|
2013-01-24 23:36:59 +00:00
|
|
|
numVertsSubmitted = 0;
|
2013-01-19 16:05:08 +00:00
|
|
|
numCachedVertsDrawn = 0;
|
2013-01-24 23:36:59 +00:00
|
|
|
numUncachedVertsDrawn = 0;
|
2013-01-19 16:05:08 +00:00
|
|
|
numTrackedVertexArrays = 0;
|
2013-01-06 11:27:01 +00:00
|
|
|
numTextureInvalidations = 0;
|
2012-11-22 22:07:15 +00:00
|
|
|
numTextureSwitches = 0;
|
|
|
|
numShaderSwitches = 0;
|
2012-12-21 20:49:09 +00:00
|
|
|
numFlushes = 0;
|
|
|
|
numTexturesDecoded = 0;
|
2013-08-27 18:58:27 +00:00
|
|
|
numAlphaTestedDraws = 0;
|
|
|
|
numNonAlphaTestedDraws = 0;
|
2013-01-10 22:49:33 +00:00
|
|
|
msProcessingDisplayLists = 0;
|
2013-05-31 17:40:16 +00:00
|
|
|
vertexGPUCycles = 0;
|
|
|
|
otherGPUCycles = 0;
|
2013-08-23 09:26:13 +00:00
|
|
|
memset(gpuCommandsAtCallLevel, 0, sizeof(gpuCommandsAtCallLevel));
|
2012-11-22 22:07:15 +00:00
|
|
|
}
|
|
|
|
|
2012-11-18 12:04:49 +00:00
|
|
|
// Per frame statistics
|
|
|
|
int numDrawCalls;
|
2013-01-19 16:05:08 +00:00
|
|
|
int numCachedDrawCalls;
|
2012-12-21 18:16:17 +00:00
|
|
|
int numFlushes;
|
2013-01-24 23:36:59 +00:00
|
|
|
int numVertsSubmitted;
|
2013-01-19 16:05:08 +00:00
|
|
|
int numCachedVertsDrawn;
|
2013-01-24 23:36:59 +00:00
|
|
|
int numUncachedVertsDrawn;
|
2013-01-19 16:05:08 +00:00
|
|
|
int numTrackedVertexArrays;
|
2013-01-06 11:27:01 +00:00
|
|
|
int numTextureInvalidations;
|
2012-11-18 12:04:49 +00:00
|
|
|
int numTextureSwitches;
|
|
|
|
int numShaderSwitches;
|
2012-12-21 20:49:09 +00:00
|
|
|
int numTexturesDecoded;
|
2013-01-10 22:49:33 +00:00
|
|
|
double msProcessingDisplayLists;
|
2013-05-31 17:40:16 +00:00
|
|
|
int vertexGPUCycles;
|
|
|
|
int otherGPUCycles;
|
2013-08-23 09:26:13 +00:00
|
|
|
int gpuCommandsAtCallLevel[4];
|
2012-11-18 12:04:49 +00:00
|
|
|
|
2013-08-27 18:58:27 +00:00
|
|
|
int numAlphaTestedDraws;
|
|
|
|
int numNonAlphaTestedDraws;
|
|
|
|
|
2012-11-26 16:35:08 +00:00
|
|
|
// Total statistics, updated by the GPU core in UpdateStats
|
2013-08-07 20:32:04 +00:00
|
|
|
int numVBlanks;
|
|
|
|
int numFlips;
|
2012-11-26 16:35:08 +00:00
|
|
|
int numTextures;
|
|
|
|
int numVertexShaders;
|
|
|
|
int numFragmentShaders;
|
|
|
|
int numShaders;
|
2013-01-11 01:00:51 +00:00
|
|
|
int numFBOs;
|
2012-11-01 15:19:01 +00:00
|
|
|
};
|
|
|
|
|
2013-09-08 05:30:30 +00:00
|
|
|
bool GPU_Init();
|
2013-08-07 15:07:13 +00:00
|
|
|
void GPU_Shutdown();
|
2013-11-28 23:34:41 +00:00
|
|
|
void GPU_Reinitialize();
|
2013-08-07 15:07:13 +00:00
|
|
|
|
2012-11-01 15:19:01 +00:00
|
|
|
void InitGfxState();
|
2012-11-06 16:05:27 +00:00
|
|
|
void ShutdownGfxState();
|
2012-11-01 15:19:01 +00:00
|
|
|
void ReapplyGfxState();
|
|
|
|
|
2012-11-06 16:05:27 +00:00
|
|
|
class GPUInterface;
|
2013-09-22 17:22:33 +00:00
|
|
|
class GPUDebugInterface;
|
2012-11-06 16:05:27 +00:00
|
|
|
|
2012-11-01 15:19:01 +00:00
|
|
|
extern GPUgstate gstate;
|
2012-11-18 12:04:49 +00:00
|
|
|
extern GPUStateCache gstate_c;
|
|
|
|
extern GPUInterface *gpu;
|
2013-09-22 17:22:33 +00:00
|
|
|
extern GPUDebugInterface *gpuDebug;
|
2012-11-24 14:19:29 +00:00
|
|
|
extern GPUStatistics gpuStats;
|
2013-02-02 12:38:34 +00:00
|
|
|
|
2013-02-02 22:47:35 +00:00
|
|
|
inline u32 GPUStateCache::getRelativeAddress(u32 data) const {
|
2013-09-14 21:33:55 +00:00
|
|
|
u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;
|
2013-02-02 12:38:34 +00:00
|
|
|
return (gstate_c.offsetAddr + baseExtended) & 0x0FFFFFFF;
|
|
|
|
}
|