/opengles/src/Rasterizer.cpp

http://ftk.googlecode.com/ · C++ · 1616 lines · 1189 code · 340 blank · 87 comment · 145 complexity · 8a504c41d557be294f9b30db1e35cb9c MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // Rasterizer.cpp Rasterizer Class for 3D Rendering Library
  4. //
  5. // The rasterizer converts transformed and lit
  6. // primitives and creates a raster image in the
  7. // current rendering surface.
  8. //
  9. // --------------------------------------------------------------------------
  10. //
  11. // 10-06-2003 Hans-Martin Will initial version
  12. //
  13. // --------------------------------------------------------------------------
  14. //
  15. // Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  16. //
  17. // Redistribution and use in source and binary forms, with or without
  18. // modification, are permitted provided that the following conditions are
  19. // met:
  20. //
  21. // * Redistributions of source code must retain the above copyright
  22. // notice, this list of conditions and the following disclaimer.
  23. // * Redistributions in binary form must reproduce the above copyright
  24. // notice, this list of conditions and the following disclaimer in the
  25. // documentation and/or other materials provided with the distribution.
  26. //
  27. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  32. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  37. // THE POSSIBILITY OF SUCH DAMAGE.
  38. //
  39. // ==========================================================================
  40. #include "stdafx.h"
  41. #include "Rasterizer.h"
  42. #include "Surface.h"
  43. #include "Texture.h"
  44. #include "arm/FunctionCache.h"
  45. using namespace EGL;
  46. // --------------------------------------------------------------------------
  47. // Local helper functions
  48. // --------------------------------------------------------------------------
  49. namespace {
  50. inline U8 MulU8(U8 a, U8 b) {
  51. U16 prod = a * b;
  52. return (((prod + (prod >> 6)) >> 7) + 1) >> 1;
  53. }
  54. inline U8 ClampU8(U16 value) {
  55. return (value > 0xff) ? (U8) 0xff : (U8) value;
  56. }
  57. inline U8 AddU8(U8 arg0, U8 arg1) {
  58. return ClampU8(arg0 + arg1);
  59. }
  60. inline U8 SubU8(U8 arg0, U8 arg1) {
  61. return arg0 > arg1 ? arg0 - arg1 : 0;
  62. }
  63. inline U8 AddSignedU8(U8 arg0, U8 arg1) {
  64. U16 value = (U16) arg0 + arg1;
  65. if (value >= 0x80)
  66. return ClampU8(value - 0x80);
  67. else
  68. return 0;
  69. }
  70. inline U8 InterpolateU8(U8 arg0, U8 arg1, U8 arg2) {
  71. return MulU8(arg0, arg2) + MulU8(arg1, 0xff - arg2);
  72. }
  73. // bring 0 .. 255 -> -128 .. 128
  74. inline I16 SignedVal(U8 in) {
  75. if (in <= 0x80)
  76. return (I16) in - 0x80;
  77. else {
  78. I16 inter = (I16) in - 0x80;
  79. return inter + (inter >> 6);
  80. }
  81. }
  82. inline U8 Dot3U8(const Color& arg0, const Color& arg1) {
  83. // each product is in the range of -2^14 .. +2^14
  84. I32 prodR = SignedVal(arg0.r) * SignedVal(arg1.r);
  85. I32 prodG = SignedVal(arg0.g) * SignedVal(arg1.g);
  86. I32 prodB = SignedVal(arg0.b) * SignedVal(arg1.b);
  87. I32 sum = (prodR + prodG + prodB) * 4;
  88. if (sum <= 0)
  89. return 0;
  90. else if (sum >= 0x10000)
  91. return 0xff;
  92. else
  93. return (sum >> 8) - (sum >> 15);
  94. }
  95. inline U8 MulU8(U8 a, U8 b, EGL_Fixed scale) {
  96. U16 prod = a * b;
  97. return ClampU8((U16) EGL_Mul((prod + (prod >> 7)) >> 8, scale));
  98. }
  99. inline U8 AddU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
  100. return ClampU8((U16) EGL_Mul((U16) arg0 + (U16) arg1, scale));
  101. }
  102. inline U8 SubU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
  103. return arg0 > arg1 ? ClampU8((U16) EGL_Mul(arg0 - arg1, scale)) : 0;
  104. }
  105. inline U8 AddSignedU8(U8 arg0, U8 arg1, EGL_Fixed scale) {
  106. U16 value = (U16) arg0 + arg1;
  107. if (value >= 0x80)
  108. return ClampU8((U16) EGL_Mul(value - 0x80, scale));
  109. else
  110. return 0;
  111. }
  112. inline U8 InterpolateU8(U8 arg0, U8 arg1, U8 arg2, EGL_Fixed scale) {
  113. return ClampU8((U16) MulU8(arg0, arg2, scale) + MulU8(arg1, 0xff - arg2, scale));
  114. }
  115. inline U8 Dot3U8(const Color& arg0, const Color& arg1, EGL_Fixed scale) {
  116. // each product is in the range of -2^14 .. +2^14
  117. I32 prodR = SignedVal(arg0.r) * SignedVal(arg1.r);
  118. I32 prodG = SignedVal(arg0.g) * SignedVal(arg1.g);
  119. I32 prodB = SignedVal(arg0.b) * SignedVal(arg1.b);
  120. I32 sum = (prodR + prodG + prodB) * 4;
  121. I32 scaledSum = ((sum >> 7) - (sum >> 14) + 1) >> 1;
  122. if (sum <= 0xff)
  123. return 0;
  124. else
  125. return ClampU8(EGL_Mul(scaledSum, scale));
  126. }
  127. const I32 InversionTable[32] = {
  128. 0,
  129. EGL_FixedFromFloat(1.0f / 1.0f),
  130. EGL_FixedFromFloat(1.0f / 2.0f),
  131. EGL_FixedFromFloat(1.0f / 3.0f),
  132. EGL_FixedFromFloat(1.0f / 4.0f),
  133. EGL_FixedFromFloat(1.0f / 5.0f),
  134. EGL_FixedFromFloat(1.0f / 6.0f),
  135. EGL_FixedFromFloat(1.0f / 7.0f),
  136. EGL_FixedFromFloat(1.0f / 8.0f),
  137. EGL_FixedFromFloat(1.0f / 9.0f),
  138. EGL_FixedFromFloat(1.0f / 10.0f),
  139. EGL_FixedFromFloat(1.0f / 11.0f),
  140. EGL_FixedFromFloat(1.0f / 12.0f),
  141. EGL_FixedFromFloat(1.0f / 13.0f),
  142. EGL_FixedFromFloat(1.0f / 14.0f),
  143. EGL_FixedFromFloat(1.0f / 15.0f),
  144. };
  145. }
  146. void RasterInfo::Init(Surface * surface, I32 y) {
  147. size_t offset = y * surface->GetWidth();
  148. SurfaceWidth = surface->GetWidth();
  149. SurfaceHeight = surface->GetHeight();
  150. DepthBuffer = surface->GetDepthBuffer() + offset;
  151. ColorBuffer = surface->GetColorBuffer() + offset;
  152. StencilBuffer = surface->GetStencilBuffer() + offset;
  153. AlphaBuffer = surface->GetAlphaBuffer() + offset;
  154. InversionTablePtr = InversionTable;
  155. }
  156. // --------------------------------------------------------------------------
  157. // Class Rasterizer
  158. // --------------------------------------------------------------------------
  159. Rasterizer :: Rasterizer(RasterizerState * state):
  160. m_State(state)
  161. {
  162. m_FunctionCache = new FunctionCache();
  163. memset(m_RasterTriangleFunctions, 0, sizeof m_RasterTriangleFunctions);
  164. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) ] = &Rasterizer::RasterTriangle_cTdfs;
  165. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  166. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_cTdFs;
  167. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  168. (1 << RasterTriangleDepth) ] = &Rasterizer::RasterTriangle_cTDfs;
  169. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  170. (1 << RasterTriangleDepth) |
  171. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_cTDFs;
  172. m_RasterTriangleFunctions[(1 << RasterTriangleColor) ] = &Rasterizer::RasterTriangle_Ctdfs;
  173. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  174. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_CtdFs;
  175. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  176. (1 << RasterTriangleDepth) ] = &Rasterizer::RasterTriangle_CtDfs;
  177. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  178. (1 << RasterTriangleDepth) |
  179. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_CtDFs;
  180. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  181. (1 << RasterTriangleTexture) ] = &Rasterizer::RasterTriangle_CTdfs;
  182. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  183. (1 << RasterTriangleTexture) |
  184. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_CTdFs;
  185. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  186. (1 << RasterTriangleTexture) |
  187. (1 << RasterTriangleDepth) ] = &Rasterizer::RasterTriangle_CTDfs;
  188. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  189. (1 << RasterTriangleTexture) |
  190. (1 << RasterTriangleDepth) |
  191. (1 << RasterTriangleFog) ] = &Rasterizer::RasterTriangle_CTDFs;
  192. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  193. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_cTdfS;
  194. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  195. (1 << RasterTriangleFog) |
  196. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_cTdFS;
  197. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  198. (1 << RasterTriangleDepth) |
  199. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_cTDfS;
  200. m_RasterTriangleFunctions[(1 << RasterTriangleTexture) |
  201. (1 << RasterTriangleDepth) |
  202. (1 << RasterTriangleFog) |
  203. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_cTDFS;
  204. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  205. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CtdfS;
  206. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  207. (1 << RasterTriangleFog) |
  208. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CtdFS;
  209. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  210. (1 << RasterTriangleDepth) |
  211. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CtDfS;
  212. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  213. (1 << RasterTriangleDepth) |
  214. (1 << RasterTriangleFog) |
  215. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CtDFS;
  216. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  217. (1 << RasterTriangleTexture) |
  218. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CTdfS;
  219. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  220. (1 << RasterTriangleTexture) |
  221. (1 << RasterTriangleFog) |
  222. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CTdFS;
  223. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  224. (1 << RasterTriangleTexture) |
  225. (1 << RasterTriangleDepth) |
  226. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CTDfS;
  227. m_RasterTriangleFunctions[(1 << RasterTriangleColor) |
  228. (1 << RasterTriangleTexture) |
  229. (1 << RasterTriangleDepth) |
  230. (1 << RasterTriangleFog) |
  231. (1 << RasterTriangleScissor) ] = &Rasterizer::RasterTriangle_CTDFS;
  232. }
  233. Rasterizer :: ~Rasterizer() {
  234. if (m_FunctionCache) {
  235. delete m_FunctionCache;
  236. }
  237. }
  238. void Rasterizer :: SetState(RasterizerState * state) {
  239. m_State = state;
  240. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  241. m_Texture[unit] = 0;
  242. }
  243. }
  244. RasterizerState * Rasterizer :: GetState() const {
  245. return m_State;
  246. }
  247. void Rasterizer :: SetTexture(size_t unit, MultiTexture * texture) {
  248. m_Texture[unit] = texture;
  249. }
  250. void Rasterizer :: PrepareTexture() {
  251. if (m_State) {
  252. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  253. if (m_State->m_Texture[unit].Enabled && m_Texture[unit]) {
  254. m_State->SetWrappingModeS(unit, m_Texture[unit]->GetWrappingModeS());
  255. m_State->SetWrappingModeT(unit, m_Texture[unit]->GetWrappingModeT());
  256. m_State->SetMinFilterMode(unit, m_Texture[unit]->GetMinFilterMode());
  257. m_State->SetMagFilterMode(unit, m_Texture[unit]->GetMagFilterMode());
  258. m_State->SetMipmapFilterMode(unit, m_Texture[unit]->GetMipmapFilterMode());
  259. m_State->SetInternalFormat(unit, m_Texture[unit]->GetInternalFormat());
  260. m_RasterInfo.Textures[unit] = m_Texture[unit]->m_TextureLevels;
  261. m_UseMipmap[unit] = m_Texture[unit]->IsMipMap() && m_Texture[unit]->IsComplete();
  262. m_RasterInfo.MaxMipmapLevel[unit] = EGL_Max(m_Texture[unit]->GetTexture(0)->GetLogWidth(), m_Texture[unit]->GetTexture(0)->GetLogHeight());
  263. } else {
  264. m_RasterInfo.Textures[unit] = 0;
  265. m_UseMipmap[unit] = false;
  266. }
  267. }
  268. }
  269. }
  270. #if !EGL_USE_JIT
  271. inline void Rasterizer :: Fragment(I32 x, I32 y, EGL_Fixed depth, EGL_Fixed tu[], EGL_Fixed tv[],
  272. EGL_Fixed fogDensity, const Color& baseColor) {
  273. // pixel ownership test
  274. if (x < 0 || x >= m_Surface->GetWidth() ||
  275. y < 0 || y >= m_Surface->GetHeight()) {
  276. return;
  277. }
  278. // fragment level clipping (for now)
  279. if (m_State->m_ScissorTest.Enabled) {
  280. if (x < m_State->m_ScissorTest.X || x - m_State->m_ScissorTest.X >= m_State->m_ScissorTest.Width ||
  281. y < m_State->m_ScissorTest.Y || y - m_State->m_ScissorTest.Y >= m_State->m_ScissorTest.Height) {
  282. return;
  283. }
  284. }
  285. m_RasterInfo.Init(m_Surface, y);
  286. Fragment(&m_RasterInfo, x, depth, tu, tv, baseColor, fogDensity);
  287. }
  288. Color Rasterizer :: GetRawTexColor(const RasterizerState::TextureState * state, const Texture * texture, EGL_Fixed tu, EGL_Fixed tv) {
  289. // retrieve the texture color from a texture plane
  290. EGL_Fixed tu0;
  291. EGL_Fixed tv0;
  292. // for nearest texel
  293. switch (state->WrappingModeS) {
  294. case RasterizerState::WrappingModeClampToEdge:
  295. if (tu < 0)
  296. tu0 = 0;
  297. else if (tu >= EGL_ONE)
  298. tu0 = EGL_ONE - 1;
  299. else
  300. tu0 = tu;
  301. break;
  302. default:
  303. case RasterizerState::WrappingModeRepeat:
  304. tu0 = tu & 0xffff;
  305. break;
  306. }
  307. switch (state->WrappingModeT) {
  308. case RasterizerState::WrappingModeClampToEdge:
  309. if (tv < 0)
  310. tv0 = 0;
  311. else if (tv >= EGL_ONE)
  312. tv0 = EGL_ONE - 1;
  313. else tv0 = tv;
  314. break;
  315. default:
  316. case RasterizerState::WrappingModeRepeat:
  317. tv0 = tv & 0xffff;
  318. break;
  319. }
  320. // get the pixel color
  321. I32 texX = EGL_IntFromFixed(texture->GetWidth() * tu0); // can become a shift
  322. I32 texY = EGL_IntFromFixed(texture->GetHeight() * tv0); // can become a shift
  323. // do wrapping mode here
  324. I32 texOffset = texX + (texY << texture->GetLogWidth());
  325. void * data = texture->GetData();
  326. switch (state->InternalFormat) {
  327. default:
  328. case RasterizerState::TextureFormatAlpha:
  329. //return Color(0xff, 0xff, 0xff, reinterpret_cast<const U8 *>(data)[texOffset]);
  330. return Color(0, 0, 0, reinterpret_cast<const U8 *>(data)[texOffset]);
  331. case RasterizerState::TextureFormatLuminance:
  332. {
  333. U8 luminance = reinterpret_cast<const U8 *>(data)[texOffset];
  334. return Color (luminance, luminance, luminance, 0xff);
  335. }
  336. case RasterizerState::TextureFormatRGB565:
  337. return Color::From565(reinterpret_cast<const U16 *>(data)[texOffset]);
  338. case RasterizerState::TextureFormatRGB8:
  339. {
  340. texOffset = (texOffset << 1) + texOffset;
  341. const U8 * ptr = reinterpret_cast<const U8 *>(data) + texOffset;
  342. return Color(ptr[0], ptr[1], ptr[2], 0xff);
  343. }
  344. case RasterizerState::TextureFormatLuminanceAlpha:
  345. {
  346. U8 luminance = reinterpret_cast<const U8 *>(data)[texOffset * 2];
  347. U8 alpha = reinterpret_cast<const U8 *>(data)[texOffset * 2 + 1];
  348. return Color (luminance, luminance, luminance, alpha);
  349. }
  350. case RasterizerState::TextureFormatRGBA8:
  351. //texColor = Color::FromRGBA(reinterpret_cast<const U32 *>(data)[texOffset]);
  352. {
  353. texOffset = texOffset << 2;
  354. const U8 * ptr = reinterpret_cast<const U8 *>(data) + texOffset;
  355. return Color(ptr[0], ptr[1], ptr[2], ptr[3]);
  356. }
  357. case RasterizerState::TextureFormatRGBA4444:
  358. return Color::From4444(reinterpret_cast<const U16 *>(data)[texOffset]);
  359. case RasterizerState::TextureFormatRGBA5551:
  360. return Color::From5551(reinterpret_cast<const U16 *>(data)[texOffset]);
  361. }
  362. }
  363. inline Color Rasterizer :: GetTexColor(const RasterizerState::TextureState * state, const Texture * texture, EGL_Fixed tu, EGL_Fixed tv,
  364. RasterizerState::FilterMode filterMode) {
  365. // retrieve the texture color from a texture plane
  366. if (filterMode == RasterizerState::FilterModeNearest) {
  367. return GetRawTexColor(state, texture, tu, tv);
  368. } else if (filterMode == RasterizerState::FilterModeLinear) {
  369. I32 logWidth = texture->GetLogWidth();
  370. I32 logHeight = texture->GetLogHeight();
  371. EGL_Fixed tu0 = tu - (0x8000 >> logWidth);
  372. EGL_Fixed tu1 = tu + (0x7fff >> logWidth);
  373. EGL_Fixed tv0 = tv - (0x8000 >> logHeight);
  374. EGL_Fixed tv1 = tv + (0x7fff >> logHeight);
  375. U32 alpha = EGL_FractionFromFixed(tu0 << logWidth) >> 8;
  376. U32 beta = EGL_FractionFromFixed(tv0 << logHeight) >> 8;
  377. return Color::BlendAlpha(Color::BlendAlpha(GetRawTexColor(state, texture, tu1, tv1),
  378. GetRawTexColor(state, texture, tu0, tv1), alpha),
  379. Color::BlendAlpha(GetRawTexColor(state, texture, tu1, tv0),
  380. GetRawTexColor(state, texture, tu0, tv0), alpha),
  381. beta);
  382. } else {
  383. return Color(0, 0, 0, 0xff);
  384. }
  385. }
  386. void Rasterizer :: Fragment(const RasterInfo * rasterInfo, I32 x, EGL_Fixed depth, EGL_Fixed tu[], EGL_Fixed tv[],
  387. const Color& baseColor, EGL_Fixed fogDensity) {
  388. // fragment rendering with signature corresponding to function fragment
  389. // generated by code generator
  390. bool depthTest;
  391. // fragment level clipping (for now)
  392. if (m_State->m_ScissorTest.Enabled) {
  393. if (x < m_State->m_ScissorTest.X || x - m_State->m_ScissorTest.X >= m_State->m_ScissorTest.Width) {
  394. return;
  395. }
  396. }
  397. I32 offset = x;
  398. depth = EGL_CLAMP(depth, 0, 0xffff);
  399. assert(depth >= 0 && depth <= 0xffff);
  400. I32 zBufferValue = rasterInfo->DepthBuffer[offset];
  401. switch (m_State->m_DepthTest.Func) {
  402. default:
  403. case RasterizerState::CompFuncNever: depthTest = false; break;
  404. case RasterizerState::CompFuncLess: depthTest = depth < zBufferValue; break;
  405. case RasterizerState::CompFuncEqual: depthTest = depth == zBufferValue; break;
  406. case RasterizerState::CompFuncLEqual: depthTest = depth <= zBufferValue; break;
  407. case RasterizerState::CompFuncGreater: depthTest = depth > zBufferValue; break;
  408. case RasterizerState::CompFuncNotEqual: depthTest = depth != zBufferValue; break;
  409. case RasterizerState::CompFuncGEqual: depthTest = depth >= zBufferValue; break;
  410. case RasterizerState::CompFuncAlways: depthTest = true; break;
  411. }
  412. if (!m_State->m_Stencil.Enabled && m_State->m_DepthTest.Enabled && !depthTest) {
  413. return;
  414. }
  415. Color color(baseColor);
  416. // have offset, color, texOffset, texture
  417. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  418. if (m_State->m_Texture[unit].Enabled) {
  419. Texture * texture = rasterInfo->Textures[unit] + rasterInfo->MipmapLevel[unit];
  420. Color texColor = GetTexColor(&m_State->m_Texture[unit], texture, tu[unit], tv[unit], m_State->GetMinFilterMode(unit));
  421. if (m_State->m_Texture[unit].Mode == RasterizerState::TextureModeCombine) {
  422. Color arg[3];
  423. for (size_t idx = 0; idx < 3; ++idx) {
  424. Color rgbIn;
  425. U8 alphaIn;
  426. switch (m_State->m_Texture[unit].CombineSrcRGB[idx]) {
  427. case RasterizerState::TextureCombineSrcTexture:
  428. rgbIn = texColor;
  429. break;
  430. case RasterizerState::TextureCombineSrcConstant:
  431. rgbIn = m_State->m_Texture[unit].EnvColor;
  432. break;
  433. case RasterizerState::TextureCombineSrcPrimaryColor:
  434. rgbIn = baseColor;
  435. break;
  436. case RasterizerState::TextureCombineSrcPrevious:
  437. rgbIn = color;
  438. break;
  439. }
  440. switch (m_State->m_Texture[unit].CombineSrcAlpha[idx]) {
  441. case RasterizerState::TextureCombineSrcTexture:
  442. alphaIn = texColor.a;
  443. break;
  444. case RasterizerState::TextureCombineSrcConstant:
  445. alphaIn = m_State->m_Texture[unit].EnvColor.a;
  446. break;
  447. case RasterizerState::TextureCombineSrcPrimaryColor:
  448. alphaIn = baseColor.a;
  449. break;
  450. case RasterizerState::TextureCombineSrcPrevious:
  451. alphaIn = color.a;
  452. break;
  453. }
  454. U8 alphaOut;
  455. if (m_State->m_Texture[unit].CombineOpAlpha[idx] == RasterizerState::TextureCombineOpSrcAlpha) {
  456. alphaOut = alphaIn;
  457. } else {
  458. alphaOut = 0xFF - alphaIn;
  459. }
  460. switch (m_State->m_Texture[unit].CombineOpRGB[idx]) {
  461. case RasterizerState::TextureCombineOpSrcColor:
  462. arg[idx] = Color(rgbIn.r, rgbIn.g, rgbIn.b, alphaOut);
  463. break;
  464. case RasterizerState::TextureCombineOpOneMinusSrcColor:
  465. arg[idx] = Color(0xFF - rgbIn.r, 0xFF - rgbIn.g, 0xFF - rgbIn.b, alphaOut);
  466. break;
  467. case RasterizerState::TextureCombineOpSrcAlpha:
  468. arg[idx] = Color(rgbIn.a, rgbIn.a, rgbIn.a, alphaOut);
  469. break;
  470. case RasterizerState::TextureCombineOpOneMinusSrcAlpha:
  471. arg[idx] = Color(0xFF - rgbIn.a, 0xFF - rgbIn.a, 0xFF - rgbIn.a, alphaOut);
  472. break;
  473. }
  474. }
  475. U8 combineAlpha;
  476. EGL_Fixed scaleAlpha = m_State->m_Texture[unit].ScaleAlpha;
  477. switch (m_State->m_Texture[unit].CombineFuncAlpha) {
  478. case RasterizerState::TextureModeCombineReplace:
  479. combineAlpha = MulU8(arg[0].a, 0xFF, scaleAlpha);
  480. break;
  481. case RasterizerState::TextureModeCombineModulate:
  482. combineAlpha = MulU8(arg[0].a, arg[1].a, scaleAlpha);
  483. break;
  484. case RasterizerState::TextureModeCombineAdd:
  485. combineAlpha = AddU8(arg[0].a, arg[1].a, scaleAlpha);
  486. break;
  487. case RasterizerState::TextureModeCombineAddSigned:
  488. combineAlpha = AddSignedU8(arg[0].a, arg[1].a, scaleAlpha);
  489. break;
  490. case RasterizerState::TextureModeCombineInterpolate:
  491. combineAlpha = InterpolateU8(arg[0].a, arg[1].a, arg[2].a, scaleAlpha);
  492. break;
  493. case RasterizerState::TextureModeCombineSubtract:
  494. combineAlpha = SubU8(arg[0].a, arg[1].a, scaleAlpha);
  495. break;
  496. }
  497. EGL_Fixed scaleRGB = m_State->m_Texture[unit].ScaleRGB;
  498. switch (m_State->m_Texture[unit].CombineFuncRGB) {
  499. case RasterizerState::TextureModeCombineReplace:
  500. color = Color(
  501. MulU8(arg[0].r, 0xFF, scaleRGB),
  502. MulU8(arg[0].g, 0xFF, scaleRGB),
  503. MulU8(arg[0].b, 0xFF, scaleRGB),
  504. combineAlpha);
  505. break;
  506. case RasterizerState::TextureModeCombineModulate:
  507. color =
  508. Color(
  509. MulU8(arg[0].r, arg[1].r, scaleRGB),
  510. MulU8(arg[0].g, arg[1].g, scaleRGB),
  511. MulU8(arg[0].b, arg[1].b, scaleRGB),
  512. combineAlpha);
  513. break;
  514. case RasterizerState::TextureModeCombineAdd:
  515. color =
  516. Color(
  517. AddU8(arg[0].r, arg[1].r, scaleRGB),
  518. AddU8(arg[0].g, arg[1].g, scaleRGB),
  519. AddU8(arg[0].b, arg[1].b, scaleRGB),
  520. combineAlpha);
  521. break;
  522. case RasterizerState::TextureModeCombineAddSigned:
  523. color =
  524. Color(
  525. AddSignedU8(arg[0].r, arg[1].r, scaleRGB),
  526. AddSignedU8(arg[0].g, arg[1].g, scaleRGB),
  527. AddSignedU8(arg[0].b, arg[1].b, scaleRGB),
  528. combineAlpha);
  529. break;
  530. case RasterizerState::TextureModeCombineInterpolate:
  531. color =
  532. Color(
  533. InterpolateU8(arg[0].r, arg[1].r, arg[2].r, scaleRGB),
  534. InterpolateU8(arg[0].g, arg[1].g, arg[2].g, scaleRGB),
  535. InterpolateU8(arg[0].b, arg[1].b, arg[2].b, scaleRGB),
  536. combineAlpha);
  537. break;
  538. case RasterizerState::TextureModeCombineSubtract:
  539. color =
  540. Color(
  541. SubU8(arg[0].r, arg[1].r, scaleRGB),
  542. SubU8(arg[0].g, arg[1].g, scaleRGB),
  543. SubU8(arg[0].b, arg[1].b, scaleRGB),
  544. combineAlpha);
  545. break;
  546. case RasterizerState::TextureModeCombineDot3RGB:
  547. {
  548. U8 dotRGB = Dot3U8(arg[0], arg[1], scaleRGB);
  549. color = Color(dotRGB, dotRGB, dotRGB, combineAlpha);
  550. }
  551. break;
  552. case RasterizerState::TextureModeCombineDot3RGBA:
  553. {
  554. U8 dotRGB = Dot3U8(arg[0], arg[1], scaleRGB);
  555. U8 dotAlpha = Dot3U8(arg[0], arg[1], scaleAlpha);
  556. color = Color(dotRGB, dotRGB, dotRGB, dotAlpha);
  557. }
  558. break;
  559. }
  560. } else {
  561. switch (m_Texture[unit]->GetInternalFormat()) {
  562. default:
  563. case RasterizerState::TextureFormatAlpha:
  564. switch (m_State->m_Texture[unit].Mode) {
  565. case RasterizerState::TextureModeReplace:
  566. color = Color(color.r, color.g, color.b, texColor.a);
  567. break;
  568. case RasterizerState::TextureModeModulate:
  569. case RasterizerState::TextureModeBlend:
  570. case RasterizerState::TextureModeAdd:
  571. color = Color(color.r, color.g, color.b, MulU8(color.a, texColor.a));
  572. break;
  573. }
  574. break;
  575. case RasterizerState::TextureFormatLuminance:
  576. switch (m_State->m_Texture[unit].Mode) {
  577. case RasterizerState::TextureModeDecal:
  578. case RasterizerState::TextureModeReplace:
  579. color = Color(texColor.r, texColor.g, texColor.b, color.a);
  580. break;
  581. case RasterizerState::TextureModeModulate:
  582. color = Color(MulU8(color.r, texColor.r),
  583. MulU8(color.g, texColor.g), MulU8(color.b, texColor.b), color.a);
  584. break;
  585. case RasterizerState::TextureModeBlend:
  586. color =
  587. Color(
  588. MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
  589. MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
  590. MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
  591. color.a);
  592. break;
  593. case RasterizerState::TextureModeAdd:
  594. color =
  595. Color(
  596. ClampU8(color.r + texColor.r),
  597. ClampU8(color.g + texColor.g),
  598. ClampU8(color.b + texColor.b),
  599. color.a);
  600. break;
  601. }
  602. break;
  603. case RasterizerState::TextureFormatRGB565:
  604. case RasterizerState::TextureFormatRGB8:
  605. switch (m_State->m_Texture[unit].Mode) {
  606. case RasterizerState::TextureModeDecal:
  607. case RasterizerState::TextureModeReplace:
  608. color = Color(texColor.r, texColor.g, texColor.b, color.a);
  609. break;
  610. case RasterizerState::TextureModeModulate:
  611. color = Color(MulU8(color.r, texColor.r),
  612. MulU8(color.g, texColor.g), MulU8(color.b, texColor.b), color.a);
  613. break;
  614. case RasterizerState::TextureModeBlend:
  615. color =
  616. Color(
  617. MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
  618. MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
  619. MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
  620. color.a);
  621. break;
  622. case RasterizerState::TextureModeAdd:
  623. color =
  624. Color(
  625. ClampU8(color.r + texColor.r),
  626. ClampU8(color.g + texColor.g),
  627. ClampU8(color.b + texColor.b),
  628. color.a);
  629. break;
  630. }
  631. break;
  632. case RasterizerState::TextureFormatLuminanceAlpha:
  633. switch (m_State->m_Texture[unit].Mode) {
  634. case RasterizerState::TextureModeReplace:
  635. color = texColor;
  636. break;
  637. case RasterizerState::TextureModeModulate:
  638. color = color * texColor;
  639. break;
  640. case RasterizerState::TextureModeDecal:
  641. color =
  642. Color(
  643. MulU8(color.r, 0xff - texColor.a) + MulU8(texColor.r, texColor.a),
  644. MulU8(color.g, 0xff - texColor.a) + MulU8(texColor.g, texColor.a),
  645. MulU8(color.b, 0xff - texColor.a) + MulU8(texColor.b, texColor.a),
  646. color.a);
  647. break;
  648. case RasterizerState::TextureModeBlend:
  649. color =
  650. Color(
  651. MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
  652. MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
  653. MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
  654. MulU8(color.a, texColor.a));
  655. break;
  656. case RasterizerState::TextureModeAdd:
  657. color =
  658. Color(
  659. ClampU8(color.r + texColor.r),
  660. ClampU8(color.g + texColor.g),
  661. ClampU8(color.b + texColor.b),
  662. MulU8(color.a, texColor.a));
  663. break;
  664. }
  665. break;
  666. case RasterizerState::TextureFormatRGBA5551:
  667. case RasterizerState::TextureFormatRGBA4444:
  668. case RasterizerState::TextureFormatRGBA8:
  669. switch (m_State->m_Texture[unit].Mode) {
  670. case RasterizerState::TextureModeReplace:
  671. color = texColor;
  672. break;
  673. case RasterizerState::TextureModeModulate:
  674. color = color * texColor;
  675. break;
  676. case RasterizerState::TextureModeDecal:
  677. color =
  678. Color(
  679. MulU8(color.r, 0xff - texColor.a) + MulU8(texColor.r, texColor.a),
  680. MulU8(color.g, 0xff - texColor.a) + MulU8(texColor.g, texColor.a),
  681. MulU8(color.b, 0xff - texColor.a) + MulU8(texColor.b, texColor.a),
  682. color.a);
  683. break;
  684. case RasterizerState::TextureModeBlend:
  685. color =
  686. Color(
  687. MulU8(color.r, 0xff - texColor.r) + MulU8(m_State->m_Texture[unit].EnvColor.r, texColor.r),
  688. MulU8(color.g, 0xff - texColor.g) + MulU8(m_State->m_Texture[unit].EnvColor.g, texColor.g),
  689. MulU8(color.b, 0xff - texColor.b) + MulU8(m_State->m_Texture[unit].EnvColor.b, texColor.b),
  690. MulU8(color.a, texColor.a));
  691. break;
  692. case RasterizerState::TextureModeAdd:
  693. color =
  694. Color(
  695. ClampU8(color.r + texColor.r),
  696. ClampU8(color.g + texColor.g),
  697. ClampU8(color.b + texColor.b),
  698. MulU8(color.a, texColor.a));
  699. break;
  700. }
  701. break;
  702. }
  703. }
  704. }
  705. }
  706. // fog
  707. if (m_State->m_Fog.Enabled) {
  708. color = Color::Blend(color, m_State->m_Fog.Color, fogDensity >> 8);
  709. }
  710. // have color
  711. if (m_State->m_Alpha.Enabled) {
  712. bool alphaTest;
  713. U8 alpha = color.A();
  714. U8 alphaRef = EGL_IntFromFixed(m_State->m_Alpha.Reference * 255);
  715. switch (m_State->m_Alpha.Func) {
  716. default:
  717. case RasterizerState::CompFuncNever: alphaTest = false; break;
  718. case RasterizerState::CompFuncLess: alphaTest = alpha < alphaRef; break;
  719. case RasterizerState::CompFuncEqual: alphaTest = alpha == alphaRef; break;
  720. case RasterizerState::CompFuncLEqual: alphaTest = alpha <= alphaRef; break;
  721. case RasterizerState::CompFuncGreater: alphaTest = alpha > alphaRef; break;
  722. case RasterizerState::CompFuncNotEqual: alphaTest = alpha != alphaRef; break;
  723. case RasterizerState::CompFuncGEqual: alphaTest = alpha >= alphaRef; break;
  724. case RasterizerState::CompFuncAlways: alphaTest = true; break;
  725. }
  726. if (!alphaTest) {
  727. return;
  728. }
  729. }
  730. // have offset, depth
  731. if (m_State->m_Stencil.Enabled) {
  732. bool stencilTest;
  733. U32 stencilRef = m_State->m_Stencil.Reference & m_State->m_Stencil.ComparisonMask;
  734. U32 stencilValue = rasterInfo->StencilBuffer[offset];
  735. U32 stencil = stencilValue & m_State->m_Stencil.ComparisonMask;
  736. switch (m_State->m_Stencil.Func) {
  737. default:
  738. case RasterizerState::CompFuncNever: stencilTest = false; break;
  739. case RasterizerState::CompFuncLess: stencilTest = stencilRef < stencil; break;
  740. case RasterizerState::CompFuncEqual: stencilTest = stencilRef == stencil;break;
  741. case RasterizerState::CompFuncLEqual: stencilTest = stencilRef <= stencil;break;
  742. case RasterizerState::CompFuncGreater: stencilTest = stencilRef > stencil; break;
  743. case RasterizerState::CompFuncNotEqual: stencilTest = stencilRef != stencil;break;
  744. case RasterizerState::CompFuncGEqual: stencilTest = stencilRef >= stencil;break;
  745. case RasterizerState::CompFuncAlways: stencilTest = true; break;
  746. }
  747. if (!stencilTest) {
  748. switch (m_State->m_Stencil.Fail) {
  749. default:
  750. case RasterizerState::StencilOpKeep:
  751. break;
  752. case RasterizerState::StencilOpZero:
  753. stencilValue = 0;
  754. break;
  755. case RasterizerState::StencilOpReplace:
  756. stencilValue = m_State->m_Stencil.Reference;
  757. break;
  758. case RasterizerState::StencilOpIncr:
  759. if (stencilValue != 0xffffffff) {
  760. stencilValue++;
  761. }
  762. break;
  763. case RasterizerState::StencilOpDecr:
  764. if (stencilValue != 0) {
  765. stencilValue--;
  766. }
  767. break;
  768. case RasterizerState::StencilOpInvert:
  769. stencilValue = ~stencilValue;
  770. break;
  771. }
  772. rasterInfo->StencilBuffer[offset] =
  773. rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
  774. stencilValue & m_State->m_Stencil.Mask;
  775. return;
  776. }
  777. if (depthTest) {
  778. switch (m_State->m_Stencil.ZPass) {
  779. default:
  780. case RasterizerState::StencilOpKeep:
  781. break;
  782. case RasterizerState::StencilOpZero:
  783. stencilValue = 0;
  784. break;
  785. case RasterizerState::StencilOpReplace:
  786. stencilValue = m_State->m_Stencil.Reference;
  787. break;
  788. case RasterizerState::StencilOpIncr:
  789. if (stencilValue != 0xffffffff) {
  790. stencilValue++;
  791. }
  792. break;
  793. case RasterizerState::StencilOpDecr:
  794. if (stencilValue != 0) {
  795. stencilValue--;
  796. }
  797. break;
  798. case RasterizerState::StencilOpInvert:
  799. stencilValue = ~stencilValue;
  800. break;
  801. }
  802. rasterInfo->StencilBuffer[offset] =
  803. rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
  804. stencilValue & m_State->m_Stencil.Mask;
  805. } else {
  806. switch (m_State->m_Stencil.ZFail) {
  807. default:
  808. case RasterizerState::StencilOpKeep:
  809. break;
  810. case RasterizerState::StencilOpZero:
  811. stencilValue = 0;
  812. break;
  813. case RasterizerState::StencilOpReplace:
  814. stencilValue = m_State->m_Stencil.Reference;
  815. break;
  816. case RasterizerState::StencilOpIncr:
  817. if (stencilValue != 0xffffffff) {
  818. stencilValue++;
  819. }
  820. break;
  821. case RasterizerState::StencilOpDecr:
  822. if (stencilValue != 0) {
  823. stencilValue--;
  824. }
  825. break;
  826. case RasterizerState::StencilOpInvert:
  827. stencilValue = ~stencilValue;
  828. break;
  829. }
  830. rasterInfo->StencilBuffer[offset] =
  831. rasterInfo->StencilBuffer[offset] & ~m_State->m_Stencil.Mask |
  832. stencilValue & m_State->m_Stencil.Mask;
  833. }
  834. }
  835. if (m_State->m_Stencil.Enabled && !depthTest && m_State->m_DepthTest.Enabled) {
  836. // otherwise we returned at the top
  837. return;
  838. }
  839. // have color, offset
  840. // Blending
  841. if (m_State->m_Blend.Enabled) {
  842. U16 dstValue = rasterInfo->ColorBuffer[offset];
  843. U8 dstAlpha = rasterInfo->AlphaBuffer[offset];
  844. Color dstColor = Color::From565A(dstValue, dstAlpha);
  845. Color srcCoeff, dstCoeff;
  846. switch (m_State->m_Blend.FuncSrc) {
  847. default:
  848. case RasterizerState::BlendFuncSrcZero:
  849. srcCoeff = Color(0, 0, 0, 0);
  850. break;
  851. case RasterizerState::BlendFuncSrcOne:
  852. srcCoeff = Color(Color::MAX, Color::MAX, Color::MAX, Color::MAX);
  853. break;
  854. case RasterizerState::BlendFuncSrcDstColor:
  855. srcCoeff = dstColor;
  856. break;
  857. case RasterizerState::BlendFuncSrcOneMinusDstColor:
  858. srcCoeff = Color(Color::MAX - dstColor.R(), Color::MAX - dstColor.G(), Color::MAX - dstColor.B(), Color::MAX - dstColor.A());
  859. break;
  860. case RasterizerState::BlendFuncSrcSrcAlpha:
  861. srcCoeff = Color(color.A(), color.A(), color.A(), color.A());
  862. break;
  863. case RasterizerState::BlendFuncSrcOneMinusSrcAlpha:
  864. srcCoeff = Color(Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A());
  865. break;
  866. case RasterizerState::BlendFuncSrcDstAlpha:
  867. srcCoeff = Color(dstAlpha, dstAlpha, dstAlpha, dstAlpha);
  868. break;
  869. case RasterizerState::BlendFuncSrcOneMinusDstAlpha:
  870. srcCoeff = Color(Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha);
  871. break;
  872. case RasterizerState::BlendFuncSrcSrcAlphaSaturate:
  873. {
  874. U8 rev = Color::MAX - dstAlpha;
  875. U8 f = (rev < color.A() ? rev : color.A());
  876. srcCoeff = Color(f, f, f, Color::MAX);
  877. }
  878. break;
  879. }
  880. switch (m_State->m_Blend.FuncDst) {
  881. default:
  882. case RasterizerState::BlendFuncDstZero:
  883. dstCoeff = Color(0, 0, 0, 0);
  884. break;
  885. case RasterizerState::BlendFuncDstOne:
  886. dstCoeff = Color(Color::MAX, Color::MAX, Color::MAX, Color::MAX);
  887. break;
  888. case RasterizerState::BlendFuncDstSrcColor:
  889. dstCoeff = color;
  890. break;
  891. case RasterizerState::BlendFuncDstOneMinusSrcColor:
  892. dstCoeff = Color(Color::MAX - color.R(), Color::MAX - color.G(), Color::MAX - color.B(), Color::MAX - color.A());
  893. break;
  894. case RasterizerState::BlendFuncDstSrcAlpha:
  895. dstCoeff = Color(color.A(), color.A(), color.A(), color.A());
  896. break;
  897. case RasterizerState::BlendFuncDstOneMinusSrcAlpha:
  898. dstCoeff = Color(Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A(), Color::MAX - color.A());
  899. break;
  900. case RasterizerState::BlendFuncDstDstAlpha:
  901. dstCoeff = Color(dstAlpha, dstAlpha, dstAlpha, dstAlpha);
  902. break;
  903. case RasterizerState::BlendFuncDstOneMinusDstAlpha:
  904. dstCoeff = Color(Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha, Color::MAX - dstAlpha);
  905. break;
  906. }
  907. color = srcCoeff * color + dstCoeff * dstColor;
  908. }
  909. // have offset, depth, color
  910. // Masking and write to framebuffer
  911. if (m_State->m_Mask.Depth) {
  912. rasterInfo->DepthBuffer[offset] = depth;
  913. }
  914. Color maskedColor =
  915. color.Mask(m_State->m_Mask.Red, m_State->m_Mask.Green, m_State->m_Mask.Blue, m_State->m_Mask.Alpha);
  916. if (m_State->m_LogicOp.Enabled) {
  917. U16 oldValue = rasterInfo->ColorBuffer[offset];
  918. U8 oldAlpha = rasterInfo->AlphaBuffer[offset];
  919. U16 newValue = maskedColor.ConvertTo565();
  920. U8 newAlpha = maskedColor.A();
  921. U16 value;
  922. U8 alpha;
  923. switch (m_State->m_LogicOp.Opcode) {
  924. default:
  925. case RasterizerState:: LogicOpClear:
  926. value = 0;
  927. alpha = 0;
  928. break;
  929. case RasterizerState:: LogicOpAnd:
  930. value = newValue & oldValue;
  931. alpha = newAlpha & oldAlpha;
  932. break;
  933. case RasterizerState:: LogicOpAndReverse:
  934. value = newValue & ~oldValue;
  935. alpha = newAlpha & ~oldAlpha;
  936. break;
  937. case RasterizerState:: LogicOpCopy:
  938. value = newValue;
  939. alpha = newAlpha;
  940. break;
  941. case RasterizerState:: LogicOpAndInverted:
  942. value = ~newValue & oldValue;
  943. alpha = ~newAlpha & oldAlpha;
  944. break;
  945. case RasterizerState:: LogicOpNoop:
  946. value = oldValue;
  947. alpha = oldAlpha;
  948. break;
  949. case RasterizerState:: LogicOpXor:
  950. value = newValue ^ oldValue;
  951. alpha = newAlpha ^ oldAlpha;
  952. break;
  953. case RasterizerState:: LogicOpOr:
  954. value = newValue | oldValue;
  955. alpha = newAlpha | oldAlpha;
  956. break;
  957. case RasterizerState:: LogicOpNor:
  958. value = ~(newValue | oldValue);
  959. alpha = ~(newAlpha | oldAlpha);
  960. break;
  961. case RasterizerState:: LogicOpEquiv:
  962. value = ~(newValue ^ oldValue);
  963. alpha = ~(newAlpha ^ oldAlpha);
  964. break;
  965. case RasterizerState:: LogicOpInvert:
  966. value = ~oldValue;
  967. alpha = ~oldAlpha;
  968. break;
  969. case RasterizerState:: LogicOpOrReverse:
  970. value = newValue | ~oldValue;
  971. alpha = newAlpha | ~oldAlpha;
  972. break;
  973. case RasterizerState:: LogicOpCopyInverted:
  974. value = ~newValue;
  975. alpha = ~newAlpha;
  976. break;
  977. case RasterizerState:: LogicOpOrInverted:
  978. value = ~newValue | oldValue;
  979. alpha = ~newAlpha | oldAlpha;
  980. break;
  981. case RasterizerState:: LogicOpNand:
  982. value = ~(newValue & oldValue);
  983. alpha = ~(newAlpha & oldAlpha);
  984. break;
  985. case RasterizerState:: LogicOpSet:
  986. value = 0xFFFF;
  987. alpha = 0xFF;
  988. break;
  989. }
  990. rasterInfo->ColorBuffer[offset] = value;
  991. rasterInfo->AlphaBuffer[offset] = alpha;
  992. } else {
  993. rasterInfo->ColorBuffer[offset] = maskedColor.ConvertTo565();
  994. if (m_State->m_Mask.Alpha) {
  995. rasterInfo->AlphaBuffer[offset] = maskedColor.A();
  996. }
  997. }
  998. }
  999. #endif // !EGL_USE_JIT
  1000. // --------------------------------------------------------------------------
  1001. // Prepare rasterizer with according to current state settings
  1002. // --------------------------------------------------------------------------
  1003. void Rasterizer :: PreparePoint() {
  1004. PrepareTexture();
  1005. m_PointFunction = (PointFunction *)
  1006. m_FunctionCache->GetFunction(FunctionCache::FunctionTypePoint,
  1007. *m_State);
  1008. m_RasterInfo.Init(m_Surface, 0);
  1009. memset(m_RasterInfo.MipmapLevel, 0, sizeof(m_RasterInfo.MipmapLevel));
  1010. }
  1011. void Rasterizer :: PrepareLine() {
  1012. PrepareTexture();
  1013. m_LineFunction = (LineFunction *)
  1014. m_FunctionCache->GetFunction(FunctionCache::FunctionTypeLine,
  1015. *m_State);
  1016. m_RasterInfo.Init(m_Surface, 0);
  1017. memset(m_RasterInfo.MipmapLevel, 0, sizeof(m_RasterInfo.MipmapLevel));
  1018. }
  1019. void Rasterizer :: Finish() {
  1020. }
  1021. #if !EGL_USE_JIT
  1022. void Rasterizer :: RasterLine(RasterPos& p_from, RasterPos& p_to) {
  1023. if (EGL_Round(p_from.m_WindowCoords.x) == EGL_Round(p_to.m_WindowCoords.x) &&
  1024. EGL_Round(p_from.m_WindowCoords.y) == EGL_Round(p_to.m_WindowCoords.y)) {
  1025. // both ends of line on same pixel
  1026. RasterPoint(p_from, EGL_ONE);
  1027. return;
  1028. }
  1029. EGL_Fixed deltaX = p_to.m_WindowCoords.x - p_from.m_WindowCoords.x;
  1030. EGL_Fixed deltaY = p_to.m_WindowCoords.y - p_from.m_WindowCoords.y;
  1031. if (EGL_Abs(deltaX) > EGL_Abs(deltaY)) {
  1032. // Bresenham along x-axis
  1033. const RasterPos *start, *end;
  1034. I32 x;
  1035. I32 endX;
  1036. EGL_Fixed roundedX; //, preStepX;
  1037. if (deltaX < 0) {
  1038. deltaY = -deltaY;
  1039. deltaX = -deltaX;
  1040. start = &p_to;
  1041. end = &p_from;
  1042. roundedX = EGL_NearestInt(p_to.m_WindowCoords.x + 1);
  1043. x = EGL_IntFromFixed(roundedX);
  1044. //preStepX = roundedX + (EGL_ONE/2) - p_to.m_WindowCoords.x;
  1045. endX = EGL_IntFromFixed(p_from.m_WindowCoords.x + ((EGL_ONE)/2));
  1046. } else {
  1047. start = &p_from;
  1048. end = &p_to;
  1049. roundedX = EGL_NearestInt(p_from.m_WindowCoords.x);
  1050. x = EGL_IntFromFixed(roundedX);
  1051. //preStepX = roundedX + (EGL_ONE/2) - p_from.m_WindowCoords.x;
  1052. endX = EGL_IntFromFixed(p_to.m_WindowCoords.x + ((EGL_ONE)/2-1));
  1053. }
  1054. const RasterPos& from = *start;
  1055. const RasterPos& to = *end;
  1056. FractionalColor baseColor = from.m_Color;
  1057. EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
  1058. EGL_Fixed tuOverZ[EGL_NUM_TEXTURE_UNITS];
  1059. EGL_Fixed tvOverZ[EGL_NUM_TEXTURE_UNITS];
  1060. size_t unit;
  1061. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1062. tuOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ);
  1063. tvOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ);
  1064. }
  1065. EGL_Fixed fogDensity = from.m_FogDensity;
  1066. EGL_Fixed depth = from.m_WindowCoords.depth;
  1067. EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
  1068. EGL_Fixed invSpan = EGL_Inverse(deltaX);
  1069. EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaY), invSpan);
  1070. // -- increments(to, from, invSpan)
  1071. FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
  1072. EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
  1073. EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
  1074. EGL_Fixed deltaU[EGL_NUM_TEXTURE_UNITS], deltaV[EGL_NUM_TEXTURE_UNITS];
  1075. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1076. deltaU[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tu, OneOverZTo) -
  1077. EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ), invSpan);
  1078. deltaV[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tv, OneOverZTo) -
  1079. EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ), invSpan);
  1080. }
  1081. EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
  1082. // -- end increments
  1083. #if 0
  1084. baseColor.r += EGL_Mul(colorIncrement.r, preStepX);
  1085. baseColor.g += EGL_Mul(colorIncrement.g, preStepX);
  1086. baseColor.b += EGL_Mul(colorIncrement.b, preStepX);
  1087. baseColor.a += EGL_Mul(colorIncrement.a, preStepX);
  1088. fogDensity += EGL_Mul(deltaFog, preStepX);
  1089. depth += EGL_Mul(deltaDepth, preStepX);
  1090. OneOverZ += EGL_Mul(deltaZ, preStepX);
  1091. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1092. tuOverZ[unit] += EGL_Mul(deltaU[unit], preStepX);
  1093. tvOverZ[unit] += EGL_Mul(deltaV[unit], preStepX);
  1094. }
  1095. #endif
  1096. I32 y = EGL_IntFromFixed(from.m_WindowCoords.y + ((EGL_ONE)/2-1));
  1097. I32 yIncrement = (deltaY > 0) ? 1 : -1;
  1098. EGL_Fixed error = 0;//EGL_ONE/2;
  1099. for (; x < endX; ++x) {
  1100. EGL_Fixed z = EGL_Inverse(OneOverZ);
  1101. EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
  1102. size_t unit;
  1103. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1104. tu[unit] = EGL_Mul(tuOverZ[unit], z);
  1105. tv[unit] = EGL_Mul(tvOverZ[unit], z);
  1106. }
  1107. Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
  1108. error += slope;
  1109. if (error > EGL_ONE) {
  1110. y += yIncrement;
  1111. error -= EGL_ONE;
  1112. }
  1113. baseColor += colorIncrement;
  1114. depth += deltaDepth;
  1115. OneOverZ += deltaZ;
  1116. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1117. tuOverZ[unit] += deltaU[unit];
  1118. tvOverZ[unit] += deltaV[unit];
  1119. }
  1120. fogDensity += deltaFog;
  1121. }
  1122. } else {
  1123. // Bresenham along y-axis
  1124. const RasterPos *start, *end;
  1125. I32 y;
  1126. I32 endY;
  1127. EGL_Fixed roundedY; //, preStepY;
  1128. if (deltaY < 0) {
  1129. deltaY = -deltaY;
  1130. deltaX = -deltaX;
  1131. start = &p_to;
  1132. end = &p_from;
  1133. roundedY = EGL_NearestInt(p_to.m_WindowCoords.y + 1);
  1134. y = EGL_IntFromFixed(roundedY);
  1135. //preStepY = roundedY + (EGL_ONE/2) - p_to.m_WindowCoords.y;
  1136. endY = EGL_IntFromFixed(p_from.m_WindowCoords.y + ((EGL_ONE)/2));
  1137. } else {
  1138. start = &p_from;
  1139. end = &p_to;
  1140. roundedY = EGL_NearestInt(p_from.m_WindowCoords.y);
  1141. y = EGL_IntFromFixed(roundedY);
  1142. //preStepY = roundedY + (EGL_ONE/2) - p_from.m_WindowCoords.y;
  1143. endY = EGL_IntFromFixed(p_to.m_WindowCoords.y + ((EGL_ONE)/2-1));
  1144. }
  1145. const RasterPos& from = *start;
  1146. const RasterPos& to = *end;
  1147. FractionalColor baseColor = from.m_Color;
  1148. EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
  1149. EGL_Fixed tuOverZ[EGL_NUM_TEXTURE_UNITS];
  1150. EGL_Fixed tvOverZ[EGL_NUM_TEXTURE_UNITS];
  1151. size_t unit;
  1152. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1153. tuOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ);
  1154. tvOverZ[unit] = EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ);
  1155. }
  1156. EGL_Fixed fogDensity = from.m_FogDensity;
  1157. EGL_Fixed depth = from.m_WindowCoords.depth;
  1158. EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
  1159. EGL_Fixed invSpan = EGL_Inverse(deltaY);
  1160. EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaX), invSpan);
  1161. // -- increments(to, from, invSpan)
  1162. FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
  1163. EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
  1164. EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
  1165. EGL_Fixed deltaU[EGL_NUM_TEXTURE_UNITS], deltaV[EGL_NUM_TEXTURE_UNITS];
  1166. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1167. deltaU[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tu, OneOverZTo) -
  1168. EGL_Mul(from.m_TextureCoords[unit].tu, OneOverZ), invSpan);
  1169. deltaV[unit] = EGL_Mul(EGL_Mul(to.m_TextureCoords[unit].tv, OneOverZTo) -
  1170. EGL_Mul(from.m_TextureCoords[unit].tv, OneOverZ), invSpan);
  1171. }
  1172. EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
  1173. // -- end increments
  1174. #if 0
  1175. baseColor.r += EGL_Mul(colorIncrement.r, preStepY);
  1176. baseColor.g += EGL_Mul(colorIncrement.g, preStepY);
  1177. baseColor.b += EGL_Mul(colorIncrement.b, preStepY);
  1178. baseColor.a += EGL_Mul(colorIncrement.a, preStepY);
  1179. fogDensity += EGL_Mul(deltaFog, preStepY);
  1180. depth += EGL_Mul(deltaDepth, preStepY);
  1181. OneOverZ += EGL_Mul(deltaZ, preStepY);
  1182. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1183. tuOverZ[unit] += EGL_Mul(deltaU[unit], preStepX);
  1184. tvOverZ[unit] += EGL_Mul(deltaV[unit], preStepX);
  1185. }
  1186. #endif
  1187. I32 x = EGL_IntFromFixed(from.m_WindowCoords.x + ((EGL_ONE)/2-1));
  1188. I32 xIncrement = (deltaX > 0) ? 1 : -1;
  1189. EGL_Fixed error = 0;//EGL_ONE/2;
  1190. // can have xIncrement; yIncrement; xBaseIncrement, yBaseIncrement
  1191. // then both x/y loops become the same
  1192. // question: how to add correct mipmap selection?
  1193. for (; y < endY; ++y) {
  1194. EGL_Fixed z = EGL_Inverse(OneOverZ);
  1195. EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
  1196. size_t unit;
  1197. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1198. tu[unit] = EGL_Mul(tuOverZ[unit], z);
  1199. tv[unit] = EGL_Mul(tvOverZ[unit], z);
  1200. }
  1201. Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
  1202. error += slope;
  1203. if (error > EGL_ONE) {
  1204. x += xIncrement;
  1205. error -= EGL_ONE;
  1206. }
  1207. baseColor += colorIncrement;
  1208. depth += deltaDepth;
  1209. OneOverZ += deltaZ;
  1210. for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1211. tuOverZ[unit] += deltaU[unit];
  1212. tvOverZ[unit] += deltaV[unit];
  1213. }
  1214. fogDensity += deltaFog;
  1215. }
  1216. }
  1217. }
  1218. namespace {
  1219. inline int Log2(int value) {
  1220. if (value <= 1) {
  1221. return 0;
  1222. }
  1223. int result = 0;
  1224. while (value > 1) {
  1225. result++;
  1226. value >>= 1;
  1227. }
  1228. return result;
  1229. }
  1230. }
  1231. void Rasterizer :: RasterPoint(const RasterPos& point, EGL_Fixed size) {
  1232. EGL_Fixed halfSize = size / 2;
  1233. I32 xmin = EGL_IntFromFixed(point.m_WindowCoords.x - halfSize + EGL_HALF);
  1234. I32 xmax = xmin + ((size - EGL_HALF) >> EGL_PRECISION);
  1235. I32 ymin = EGL_IntFromFixed(point.m_WindowCoords.y - halfSize + EGL_HALF);
  1236. I32 ymax = ymin + ((size - EGL_HALF) >> EGL_PRECISION);
  1237. EGL_Fixed depth = point.m_WindowCoords.depth;
  1238. FractionalColor baseColor = point.m_Color;
  1239. EGL_Fixed fogDensity = point.m_FogDensity;
  1240. if (!m_State->m_Point.SpriteEnabled && !m_State->m_Point.CoordReplaceEnabled) {
  1241. EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
  1242. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1243. tu[unit] = point.m_TextureCoords[unit].tu;
  1244. tv[unit] = point.m_TextureCoords[unit].tv;
  1245. }
  1246. for (I32 y = ymin; y <= ymax; y++) {
  1247. for (I32 x = xmin; x <= xmax; x++) {
  1248. Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
  1249. }
  1250. }
  1251. } else {
  1252. EGL_Fixed delta = EGL_Inverse(size);
  1253. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1254. if (m_UseMipmap[unit]) {
  1255. EGL_Fixed maxDu = delta >> (16 - m_Texture[unit]->GetTexture(0)->GetLogWidth());
  1256. EGL_Fixed maxDv = delta >> (16 - m_Texture[unit]->GetTexture(0)->GetLogHeight());
  1257. EGL_Fixed rho = maxDu + maxDv;
  1258. // we start with nearest/minification only selection; will add LINEAR later
  1259. m_RasterInfo.MipmapLevel[unit] = EGL_Min(Log2(rho), m_RasterInfo.MaxMipmapLevel[unit]);
  1260. }
  1261. }
  1262. EGL_Fixed tu[EGL_NUM_TEXTURE_UNITS], tv[EGL_NUM_TEXTURE_UNITS];
  1263. for (I32 y = ymin, tv0 = delta / 2; y <= ymax; y++, tv0 += delta) {
  1264. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1265. tv[unit] = tv0;
  1266. }
  1267. for (I32 x = xmin, tu0 = delta / 2; x <= xmax; x++, tu0 += delta) {
  1268. for (size_t unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
  1269. tu[unit] = tu0;
  1270. }
  1271. Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
  1272. }
  1273. }
  1274. }
  1275. }
  1276. #endif // !EGL_USE_JIT