primitives.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. /* libs/opengles/primitives.cpp
  2. **
  3. ** Copyright 2006, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include "context.h"
  21. #include "primitives.h"
  22. #include "light.h"
  23. #include "matrix.h"
  24. #include "vertex.h"
  25. #include "fp.h"
  26. #include "TextureObjectManager.h"
  27. extern "C" void iterators0032(const void* that,
  28. int32_t* it, int32_t c0, int32_t c1, int32_t c2);
  29. namespace android {
  30. // ----------------------------------------------------------------------------
  31. static void primitive_point(ogles_context_t* c, vertex_t* v);
  32. static void primitive_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1);
  33. static void primitive_clip_triangle(ogles_context_t* c,
  34. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  35. static void primitive_nop_point(ogles_context_t* c, vertex_t* v);
  36. static void primitive_nop_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1);
  37. static void primitive_nop_triangle(ogles_context_t* c,
  38. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  39. static inline bool cull_triangle(ogles_context_t* c,
  40. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  41. static void lerp_triangle(ogles_context_t* c,
  42. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  43. static void lerp_texcoords(ogles_context_t* c,
  44. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  45. static void lerp_texcoords_w(ogles_context_t* c,
  46. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  47. static void triangle(ogles_context_t* c,
  48. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  49. static void clip_triangle(ogles_context_t* c,
  50. vertex_t* v0, vertex_t* v1, vertex_t* v2);
  51. static unsigned int clip_line(ogles_context_t* c,
  52. vertex_t* s, vertex_t* p);
  53. // ----------------------------------------------------------------------------
  54. #if 0
  55. #pragma mark -
  56. #endif
  57. static void lightTriangleDarkSmooth(ogles_context_t* c,
  58. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  59. {
  60. if (!(v0->flags & vertex_t::LIT)) {
  61. v0->flags |= vertex_t::LIT;
  62. const GLvoid* cp = c->arrays.color.element(
  63. v0->index & vertex_cache_t::INDEX_MASK);
  64. c->arrays.color.fetch(c, v0->color.v, cp);
  65. }
  66. if (!(v1->flags & vertex_t::LIT)) {
  67. v1->flags |= vertex_t::LIT;
  68. const GLvoid* cp = c->arrays.color.element(
  69. v1->index & vertex_cache_t::INDEX_MASK);
  70. c->arrays.color.fetch(c, v1->color.v, cp);
  71. }
  72. if(!(v2->flags & vertex_t::LIT)) {
  73. v2->flags |= vertex_t::LIT;
  74. const GLvoid* cp = c->arrays.color.element(
  75. v2->index & vertex_cache_t::INDEX_MASK);
  76. c->arrays.color.fetch(c, v2->color.v, cp);
  77. }
  78. }
  79. static void lightTriangleDarkFlat(ogles_context_t* c,
  80. vertex_t* /*v0*/, vertex_t* /*v1*/, vertex_t* v2)
  81. {
  82. if (!(v2->flags & vertex_t::LIT)) {
  83. v2->flags |= vertex_t::LIT;
  84. const GLvoid* cp = c->arrays.color.element(
  85. v2->index & vertex_cache_t::INDEX_MASK);
  86. c->arrays.color.fetch(c, v2->color.v, cp);
  87. }
  88. // configure the rasterizer here, before we clip
  89. c->rasterizer.procs.color4xv(c, v2->color.v);
  90. }
  91. static void lightTriangleSmooth(ogles_context_t* c,
  92. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  93. {
  94. if (!(v0->flags & vertex_t::LIT))
  95. c->lighting.lightVertex(c, v0);
  96. if (!(v1->flags & vertex_t::LIT))
  97. c->lighting.lightVertex(c, v1);
  98. if(!(v2->flags & vertex_t::LIT))
  99. c->lighting.lightVertex(c, v2);
  100. }
  101. static void lightTriangleFlat(ogles_context_t* c,
  102. vertex_t* /*v0*/, vertex_t* /*v1*/, vertex_t* v2)
  103. {
  104. if (!(v2->flags & vertex_t::LIT))
  105. c->lighting.lightVertex(c, v2);
  106. // configure the rasterizer here, before we clip
  107. c->rasterizer.procs.color4xv(c, v2->color.v);
  108. }
  109. // The fog versions...
  110. static inline
  111. void lightVertexDarkSmoothFog(ogles_context_t* c, vertex_t* v)
  112. {
  113. if (!(v->flags & vertex_t::LIT)) {
  114. v->flags |= vertex_t::LIT;
  115. v->fog = c->fog.fog(c, v->eye.z);
  116. const GLvoid* cp = c->arrays.color.element(
  117. v->index & vertex_cache_t::INDEX_MASK);
  118. c->arrays.color.fetch(c, v->color.v, cp);
  119. }
  120. }
  121. static inline
  122. void lightVertexDarkFlatFog(ogles_context_t* c, vertex_t* v)
  123. {
  124. if (!(v->flags & vertex_t::LIT)) {
  125. v->flags |= vertex_t::LIT;
  126. v->fog = c->fog.fog(c, v->eye.z);
  127. }
  128. }
  129. static inline
  130. void lightVertexSmoothFog(ogles_context_t* c, vertex_t* v)
  131. {
  132. if (!(v->flags & vertex_t::LIT)) {
  133. v->fog = c->fog.fog(c, v->eye.z);
  134. c->lighting.lightVertex(c, v);
  135. }
  136. }
  137. static void lightTriangleDarkSmoothFog(ogles_context_t* c,
  138. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  139. {
  140. lightVertexDarkSmoothFog(c, v0);
  141. lightVertexDarkSmoothFog(c, v1);
  142. lightVertexDarkSmoothFog(c, v2);
  143. }
  144. static void lightTriangleDarkFlatFog(ogles_context_t* c,
  145. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  146. {
  147. lightVertexDarkFlatFog(c, v0);
  148. lightVertexDarkFlatFog(c, v1);
  149. lightVertexDarkSmoothFog(c, v2);
  150. // configure the rasterizer here, before we clip
  151. c->rasterizer.procs.color4xv(c, v2->color.v);
  152. }
  153. static void lightTriangleSmoothFog(ogles_context_t* c,
  154. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  155. {
  156. lightVertexSmoothFog(c, v0);
  157. lightVertexSmoothFog(c, v1);
  158. lightVertexSmoothFog(c, v2);
  159. }
  160. static void lightTriangleFlatFog(ogles_context_t* c,
  161. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  162. {
  163. lightVertexDarkFlatFog(c, v0);
  164. lightVertexDarkFlatFog(c, v1);
  165. lightVertexSmoothFog(c, v2);
  166. // configure the rasterizer here, before we clip
  167. c->rasterizer.procs.color4xv(c, v2->color.v);
  168. }
  169. typedef void (*light_primitive_t)(ogles_context_t*,
  170. vertex_t*, vertex_t*, vertex_t*);
  171. // fog 0x4, light 0x2, smooth 0x1
  172. static const light_primitive_t lightPrimitive[8] = {
  173. lightTriangleDarkFlat, // no fog | dark | flat
  174. lightTriangleDarkSmooth, // no fog | dark | smooth
  175. lightTriangleFlat, // no fog | light | flat
  176. lightTriangleSmooth, // no fog | light | smooth
  177. lightTriangleDarkFlatFog, // fog | dark | flat
  178. lightTriangleDarkSmoothFog, // fog | dark | smooth
  179. lightTriangleFlatFog, // fog | light | flat
  180. lightTriangleSmoothFog // fog | light | smooth
  181. };
  182. void ogles_validate_primitives(ogles_context_t* c)
  183. {
  184. const uint32_t enables = c->rasterizer.state.enables;
  185. // set up the lighting/shading/smoothing/fogging function
  186. int index = enables & GGL_ENABLE_SMOOTH ? 0x1 : 0;
  187. index |= c->lighting.enable ? 0x2 : 0;
  188. index |= enables & GGL_ENABLE_FOG ? 0x4 : 0;
  189. c->lighting.lightTriangle = lightPrimitive[index];
  190. // set up the primitive renderers
  191. if (ggl_likely(c->arrays.vertex.enable)) {
  192. c->prims.renderPoint = primitive_point;
  193. c->prims.renderLine = primitive_line;
  194. c->prims.renderTriangle = primitive_clip_triangle;
  195. } else {
  196. c->prims.renderPoint = primitive_nop_point;
  197. c->prims.renderLine = primitive_nop_line;
  198. c->prims.renderTriangle = primitive_nop_triangle;
  199. }
  200. }
  201. // ----------------------------------------------------------------------------
  202. void compute_iterators_t::initTriangle(
  203. vertex_t const* v0, vertex_t const* v1, vertex_t const* v2)
  204. {
  205. m_dx01 = v1->window.x - v0->window.x;
  206. m_dy10 = v0->window.y - v1->window.y;
  207. m_dx20 = v0->window.x - v2->window.x;
  208. m_dy02 = v2->window.y - v0->window.y;
  209. m_area = m_dx01*m_dy02 + (-m_dy10)*m_dx20;
  210. }
  211. void compute_iterators_t::initLine(
  212. vertex_t const* v0, vertex_t const* v1)
  213. {
  214. m_dx01 = m_dy02 = v1->window.x - v0->window.x;
  215. m_dy10 = m_dx20 = v0->window.y - v1->window.y;
  216. m_area = m_dx01*m_dy02 + (-m_dy10)*m_dx20;
  217. }
  218. void compute_iterators_t::initLerp(vertex_t const* v0, uint32_t enables)
  219. {
  220. m_x0 = v0->window.x;
  221. m_y0 = v0->window.y;
  222. const GGLcoord area = (m_area + TRI_HALF) >> TRI_FRACTION_BITS;
  223. const GGLcoord minArea = 2; // cannot be inverted
  224. // triangles with an area smaller than 1.0 are not smooth-shaded
  225. int q=0, s=0, d=0;
  226. if (abs(area) >= minArea) {
  227. // Here we do some voodoo magic, to compute a suitable scale
  228. // factor for deltas/area:
  229. // First compute the 1/area with full 32-bits precision,
  230. // gglRecipQNormalized returns a number [-0.5, 0.5[ and an exponent.
  231. d = gglRecipQNormalized(area, &q);
  232. // Then compute the minimum left-shift to not overflow the muls
  233. // below.
  234. s = 32 - gglClz(abs(m_dy02)|abs(m_dy10)|abs(m_dx01)|abs(m_dx20));
  235. // We'll keep 16-bits of precision for deltas/area. So we need
  236. // to shift everything left an extra 15 bits.
  237. s += 15;
  238. // make sure all final shifts are not > 32, because gglMulx
  239. // can't handle it.
  240. if (s < q) s = q;
  241. if (s > 32) {
  242. d >>= 32-s;
  243. s = 32;
  244. }
  245. }
  246. m_dx01 = gglMulx(m_dx01, d, s);
  247. m_dy10 = gglMulx(m_dy10, d, s);
  248. m_dx20 = gglMulx(m_dx20, d, s);
  249. m_dy02 = gglMulx(m_dy02, d, s);
  250. m_area_scale = 32 + q - s;
  251. m_scale = 0;
  252. if (enables & GGL_ENABLE_TMUS) {
  253. const int A = gglClz(abs(m_dy02)|abs(m_dy10)|abs(m_dx01)|abs(m_dx20));
  254. const int B = gglClz(abs(m_x0)|abs(m_y0));
  255. m_scale = max(0, 32 - (A + 16)) +
  256. max(0, 32 - (B + TRI_FRACTION_BITS)) + 1;
  257. }
  258. }
  259. int compute_iterators_t::iteratorsScale(GGLfixed* it,
  260. int32_t c0, int32_t c1, int32_t c2) const
  261. {
  262. int32_t dc01 = c1 - c0;
  263. int32_t dc02 = c2 - c0;
  264. const int A = gglClz(abs(c0));
  265. const int B = gglClz(abs(dc01)|abs(dc02));
  266. const int scale = min(A, B - m_scale) - 2;
  267. if (scale >= 0) {
  268. c0 <<= scale;
  269. dc01 <<= scale;
  270. dc02 <<= scale;
  271. } else {
  272. c0 >>= -scale;
  273. dc01 >>= -scale;
  274. dc02 >>= -scale;
  275. }
  276. const int s = m_area_scale;
  277. int32_t dcdx = gglMulAddx(dc01, m_dy02, gglMulx(dc02, m_dy10, s), s);
  278. int32_t dcdy = gglMulAddx(dc02, m_dx01, gglMulx(dc01, m_dx20, s), s);
  279. int32_t c = c0 - (gglMulAddx(dcdx, m_x0,
  280. gglMulx(dcdy, m_y0, TRI_FRACTION_BITS), TRI_FRACTION_BITS));
  281. it[0] = c;
  282. it[1] = dcdx;
  283. it[2] = dcdy;
  284. return scale;
  285. }
  286. void compute_iterators_t::iterators1616(GGLfixed* it,
  287. GGLfixed c0, GGLfixed c1, GGLfixed c2) const
  288. {
  289. const GGLfixed dc01 = c1 - c0;
  290. const GGLfixed dc02 = c2 - c0;
  291. // 16.16 x 16.16 == 32.32 --> 16.16
  292. const int s = m_area_scale;
  293. int32_t dcdx = gglMulAddx(dc01, m_dy02, gglMulx(dc02, m_dy10, s), s);
  294. int32_t dcdy = gglMulAddx(dc02, m_dx01, gglMulx(dc01, m_dx20, s), s);
  295. int32_t c = c0 - (gglMulAddx(dcdx, m_x0,
  296. gglMulx(dcdy, m_y0, TRI_FRACTION_BITS), TRI_FRACTION_BITS));
  297. it[0] = c;
  298. it[1] = dcdx;
  299. it[2] = dcdy;
  300. }
  301. void compute_iterators_t::iterators0032(int64_t* it,
  302. int32_t c0, int32_t c1, int32_t c2) const
  303. {
  304. const int s = m_area_scale - 16;
  305. int32_t dc01 = (c1 - c0)>>s;
  306. int32_t dc02 = (c2 - c0)>>s;
  307. // 16.16 x 16.16 == 32.32
  308. int64_t dcdx = gglMulii(dc01, m_dy02) + gglMulii(dc02, m_dy10);
  309. int64_t dcdy = gglMulii(dc02, m_dx01) + gglMulii(dc01, m_dx20);
  310. it[ 0] = (c0<<16) - ((dcdx*m_x0 + dcdy*m_y0)>>4);
  311. it[ 1] = dcdx;
  312. it[ 2] = dcdy;
  313. }
  314. #if defined(__arm__) && !defined(__thumb__)
  315. inline void compute_iterators_t::iterators0032(int32_t* it,
  316. int32_t c0, int32_t c1, int32_t c2) const
  317. {
  318. ::iterators0032(this, it, c0, c1, c2);
  319. }
  320. #else
  321. void compute_iterators_t::iterators0032(int32_t* it,
  322. int32_t c0, int32_t c1, int32_t c2) const
  323. {
  324. int64_t it64[3];
  325. iterators0032(it64, c0, c1, c2);
  326. it[0] = it64[0];
  327. it[1] = it64[1];
  328. it[2] = it64[2];
  329. }
  330. #endif
  331. // ----------------------------------------------------------------------------
  332. static inline int32_t clampZ(GLfixed z) CONST;
  333. int32_t clampZ(GLfixed z) {
  334. z = (z & ~(z>>31));
  335. if (z >= 0x10000)
  336. z = 0xFFFF;
  337. return z;
  338. }
  339. static __attribute__((noinline))
  340. void fetch_texcoord_impl(ogles_context_t* c,
  341. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  342. {
  343. vertex_t* const vtx[3] = { v0, v1, v2 };
  344. array_t const * const texcoordArray = c->arrays.texture;
  345. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  346. if (!(c->rasterizer.state.texture[i].enable))
  347. continue;
  348. for (int j=0 ; j<3 ; j++) {
  349. vertex_t* const v = vtx[j];
  350. if (v->flags & vertex_t::TT)
  351. continue;
  352. // NOTE: here we could compute automatic texgen
  353. // such as sphere/cube maps, instead of fetching them
  354. // from the textcoord array.
  355. vec4_t& coords = v->texture[i];
  356. const GLubyte* tp = texcoordArray[i].element(
  357. v->index & vertex_cache_t::INDEX_MASK);
  358. texcoordArray[i].fetch(c, coords.v, tp);
  359. // transform texture coordinates...
  360. coords.Q = 0x10000;
  361. const transform_t& tr = c->transforms.texture[i].transform;
  362. if (ggl_unlikely(tr.ops)) {
  363. c->arrays.tex_transform[i](&tr, &coords, &coords);
  364. }
  365. // divide by Q
  366. const GGLfixed q = coords.Q;
  367. if (ggl_unlikely(q != 0x10000)) {
  368. const int32_t qinv = gglRecip28(q);
  369. coords.S = gglMulx(coords.S, qinv, 28);
  370. coords.T = gglMulx(coords.T, qinv, 28);
  371. }
  372. }
  373. }
  374. v0->flags |= vertex_t::TT;
  375. v1->flags |= vertex_t::TT;
  376. v2->flags |= vertex_t::TT;
  377. }
  378. inline void fetch_texcoord(ogles_context_t* c,
  379. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  380. {
  381. const uint32_t enables = c->rasterizer.state.enables;
  382. if (!(enables & GGL_ENABLE_TMUS))
  383. return;
  384. // Fetch & transform texture coordinates...
  385. if (ggl_likely(v0->flags & v1->flags & v2->flags & vertex_t::TT)) {
  386. // already done for all three vertices, bail...
  387. return;
  388. }
  389. fetch_texcoord_impl(c, v0, v1, v2);
  390. }
  391. // ----------------------------------------------------------------------------
  392. #if 0
  393. #pragma mark -
  394. #pragma mark Point
  395. #endif
  396. void primitive_nop_point(ogles_context_t*, vertex_t*) {
  397. }
  398. void primitive_point(ogles_context_t* c, vertex_t* v)
  399. {
  400. // lighting & clamping...
  401. const uint32_t enables = c->rasterizer.state.enables;
  402. if (ggl_unlikely(!(v->flags & vertex_t::LIT))) {
  403. if (c->lighting.enable) {
  404. c->lighting.lightVertex(c, v);
  405. } else {
  406. v->flags |= vertex_t::LIT;
  407. const GLvoid* cp = c->arrays.color.element(
  408. v->index & vertex_cache_t::INDEX_MASK);
  409. c->arrays.color.fetch(c, v->color.v, cp);
  410. }
  411. if (enables & GGL_ENABLE_FOG) {
  412. v->fog = c->fog.fog(c, v->eye.z);
  413. }
  414. }
  415. // XXX: we don't need to do that each-time
  416. // if color array and lighting not enabled
  417. c->rasterizer.procs.color4xv(c, v->color.v);
  418. // XXX: look into ES point-sprite extension
  419. if (enables & GGL_ENABLE_TMUS) {
  420. fetch_texcoord(c, v,v,v);
  421. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  422. if (!c->rasterizer.state.texture[i].enable)
  423. continue;
  424. int32_t itt[8];
  425. itt[1] = itt[2] = itt[4] = itt[5] = 0;
  426. itt[6] = itt[7] = 16; // XXX: check that
  427. if (c->rasterizer.state.texture[i].s_wrap == GGL_CLAMP) {
  428. int width = c->textures.tmu[i].texture->surface.width;
  429. itt[0] = v->texture[i].S * width;
  430. itt[6] = 0;
  431. }
  432. if (c->rasterizer.state.texture[i].t_wrap == GGL_CLAMP) {
  433. int height = c->textures.tmu[i].texture->surface.height;
  434. itt[3] = v->texture[i].T * height;
  435. itt[7] = 0;
  436. }
  437. c->rasterizer.procs.texCoordGradScale8xv(c, i, itt);
  438. }
  439. }
  440. if (enables & GGL_ENABLE_DEPTH_TEST) {
  441. int32_t itz[3];
  442. itz[0] = clampZ(v->window.z) * 0x00010001;
  443. itz[1] = itz[2] = 0;
  444. c->rasterizer.procs.zGrad3xv(c, itz);
  445. }
  446. if (enables & GGL_ENABLE_FOG) {
  447. GLfixed itf[3];
  448. itf[0] = v->fog;
  449. itf[1] = itf[2] = 0;
  450. c->rasterizer.procs.fogGrad3xv(c, itf);
  451. }
  452. // Render our point...
  453. c->rasterizer.procs.pointx(c, v->window.v, c->point.size);
  454. }
  455. // ----------------------------------------------------------------------------
  456. #if 0
  457. #pragma mark -
  458. #pragma mark Line
  459. #endif
  460. void primitive_nop_line(ogles_context_t*, vertex_t*, vertex_t*) {
  461. }
  462. void primitive_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1)
  463. {
  464. // get texture coordinates
  465. fetch_texcoord(c, v0, v1, v1);
  466. // light/shade the vertices first (they're copied below)
  467. c->lighting.lightTriangle(c, v0, v1, v1);
  468. // clip the line if needed
  469. if (ggl_unlikely((v0->flags | v1->flags) & vertex_t::CLIP_ALL)) {
  470. unsigned int count = clip_line(c, v0, v1);
  471. if (ggl_unlikely(count == 0))
  472. return;
  473. }
  474. // compute iterators...
  475. const uint32_t enables = c->rasterizer.state.enables;
  476. const uint32_t mask = GGL_ENABLE_TMUS |
  477. GGL_ENABLE_SMOOTH |
  478. GGL_ENABLE_W |
  479. GGL_ENABLE_FOG |
  480. GGL_ENABLE_DEPTH_TEST;
  481. if (ggl_unlikely(enables & mask)) {
  482. c->lerp.initLine(v0, v1);
  483. lerp_triangle(c, v0, v1, v0);
  484. }
  485. // render our line
  486. c->rasterizer.procs.linex(c, v0->window.v, v1->window.v, c->line.width);
  487. }
  488. // ----------------------------------------------------------------------------
  489. #if 0
  490. #pragma mark -
  491. #pragma mark Triangle
  492. #endif
  493. void primitive_nop_triangle(ogles_context_t* /*c*/,
  494. vertex_t* /*v0*/, vertex_t* /*v1*/, vertex_t* /*v2*/) {
  495. }
  496. void primitive_clip_triangle(ogles_context_t* c,
  497. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  498. {
  499. uint32_t cc = (v0->flags | v1->flags | v2->flags) & vertex_t::CLIP_ALL;
  500. if (ggl_likely(!cc)) {
  501. // code below must be as optimized as possible, this is the
  502. // common code path.
  503. // This triangle is not clipped, test if it's culled
  504. // unclipped triangle...
  505. c->lerp.initTriangle(v0, v1, v2);
  506. if (cull_triangle(c, v0, v1, v2))
  507. return; // culled!
  508. // Fetch all texture coordinates if needed
  509. fetch_texcoord(c, v0, v1, v2);
  510. // light (or shade) our triangle!
  511. c->lighting.lightTriangle(c, v0, v1, v2);
  512. triangle(c, v0, v1, v2);
  513. return;
  514. }
  515. // The assumption here is that we're not going to clip very often,
  516. // and even more rarely will we clip a triangle that ends up
  517. // being culled out. So it's okay to light the vertices here, even though
  518. // in a few cases we won't render the triangle (if culled).
  519. // Fetch texture coordinates...
  520. fetch_texcoord(c, v0, v1, v2);
  521. // light (or shade) our triangle!
  522. c->lighting.lightTriangle(c, v0, v1, v2);
  523. clip_triangle(c, v0, v1, v2);
  524. }
  525. // -----------------------------------------------------------------------
  526. void triangle(ogles_context_t* c,
  527. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  528. {
  529. // compute iterators...
  530. const uint32_t enables = c->rasterizer.state.enables;
  531. const uint32_t mask = GGL_ENABLE_TMUS |
  532. GGL_ENABLE_SMOOTH |
  533. GGL_ENABLE_W |
  534. GGL_ENABLE_FOG |
  535. GGL_ENABLE_DEPTH_TEST;
  536. if (ggl_likely(enables & mask))
  537. lerp_triangle(c, v0, v1, v2);
  538. c->rasterizer.procs.trianglex(c, v0->window.v, v1->window.v, v2->window.v);
  539. }
  540. void lerp_triangle(ogles_context_t* c,
  541. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  542. {
  543. const uint32_t enables = c->rasterizer.state.enables;
  544. c->lerp.initLerp(v0, enables);
  545. // set up texture iterators
  546. if (enables & GGL_ENABLE_TMUS) {
  547. if (enables & GGL_ENABLE_W) {
  548. lerp_texcoords_w(c, v0, v1, v2);
  549. } else {
  550. lerp_texcoords(c, v0, v1, v2);
  551. }
  552. }
  553. // set up the color iterators
  554. const compute_iterators_t& lerp = c->lerp;
  555. if (enables & GGL_ENABLE_SMOOTH) {
  556. GLfixed itc[12];
  557. for (int i=0 ; i<4 ; i++) {
  558. const GGLcolor c0 = v0->color.v[i] * 255;
  559. const GGLcolor c1 = v1->color.v[i] * 255;
  560. const GGLcolor c2 = v2->color.v[i] * 255;
  561. lerp.iterators1616(&itc[i*3], c0, c1, c2);
  562. }
  563. c->rasterizer.procs.colorGrad12xv(c, itc);
  564. }
  565. if (enables & GGL_ENABLE_DEPTH_TEST) {
  566. int32_t itz[3];
  567. const int32_t v0z = clampZ(v0->window.z);
  568. const int32_t v1z = clampZ(v1->window.z);
  569. const int32_t v2z = clampZ(v2->window.z);
  570. if (ggl_unlikely(c->polygonOffset.enable)) {
  571. const int32_t units = (c->polygonOffset.units << 16);
  572. const GLfixed factor = c->polygonOffset.factor;
  573. if (factor) {
  574. int64_t itz64[3];
  575. lerp.iterators0032(itz64, v0z, v1z, v2z);
  576. int64_t maxDepthSlope = max(itz64[1], itz64[2]);
  577. itz[0] = uint32_t(itz64[0])
  578. + uint32_t((maxDepthSlope*factor)>>16) + units;
  579. itz[1] = uint32_t(itz64[1]);
  580. itz[2] = uint32_t(itz64[2]);
  581. } else {
  582. lerp.iterators0032(itz, v0z, v1z, v2z);
  583. itz[0] += units;
  584. }
  585. } else {
  586. lerp.iterators0032(itz, v0z, v1z, v2z);
  587. }
  588. c->rasterizer.procs.zGrad3xv(c, itz);
  589. }
  590. if (ggl_unlikely(enables & GGL_ENABLE_FOG)) {
  591. GLfixed itf[3];
  592. lerp.iterators1616(itf, v0->fog, v1->fog, v2->fog);
  593. c->rasterizer.procs.fogGrad3xv(c, itf);
  594. }
  595. }
  596. static inline
  597. int compute_lod(ogles_context_t* c, int i,
  598. int32_t s0, int32_t t0, int32_t s1, int32_t t1, int32_t s2, int32_t t2)
  599. {
  600. // Compute mipmap level / primitive
  601. // rho = sqrt( texelArea / area )
  602. // lod = log2( rho )
  603. // lod = log2( texelArea / area ) / 2
  604. // lod = (log2( texelArea ) - log2( area )) / 2
  605. const compute_iterators_t& lerp = c->lerp;
  606. const GGLcoord area = abs(lerp.area());
  607. const int w = c->textures.tmu[i].texture->surface.width;
  608. const int h = c->textures.tmu[i].texture->surface.height;
  609. const int shift = 16 + (16 - TRI_FRACTION_BITS);
  610. int32_t texelArea = abs( gglMulx(s1-s0, t2-t0, shift) -
  611. gglMulx(s2-s0, t1-t0, shift) )*w*h;
  612. int log2TArea = (32-TRI_FRACTION_BITS -1) - gglClz(texelArea);
  613. int log2Area = (32-TRI_FRACTION_BITS*2-1) - gglClz(area);
  614. int lod = (log2TArea - log2Area + 1) >> 1;
  615. return lod;
  616. }
  617. void lerp_texcoords(ogles_context_t* c,
  618. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  619. {
  620. const compute_iterators_t& lerp = c->lerp;
  621. int32_t itt[8] __attribute__((aligned(16)));
  622. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  623. const texture_t& tmu = c->rasterizer.state.texture[i];
  624. if (!tmu.enable)
  625. continue;
  626. // compute the jacobians using block floating-point
  627. int32_t s0 = v0->texture[i].S;
  628. int32_t t0 = v0->texture[i].T;
  629. int32_t s1 = v1->texture[i].S;
  630. int32_t t1 = v1->texture[i].T;
  631. int32_t s2 = v2->texture[i].S;
  632. int32_t t2 = v2->texture[i].T;
  633. const GLenum min_filter = c->textures.tmu[i].texture->min_filter;
  634. if (ggl_unlikely(min_filter >= GL_NEAREST_MIPMAP_NEAREST)) {
  635. int lod = compute_lod(c, i, s0, t0, s1, t1, s2, t2);
  636. c->rasterizer.procs.bindTextureLod(c, i,
  637. &c->textures.tmu[i].texture->mip(lod));
  638. }
  639. // premultiply (s,t) when clampling
  640. if (tmu.s_wrap == GGL_CLAMP) {
  641. const int width = tmu.surface.width;
  642. s0 *= width;
  643. s1 *= width;
  644. s2 *= width;
  645. }
  646. if (tmu.t_wrap == GGL_CLAMP) {
  647. const int height = tmu.surface.height;
  648. t0 *= height;
  649. t1 *= height;
  650. t2 *= height;
  651. }
  652. itt[6] = -lerp.iteratorsScale(itt+0, s0, s1, s2);
  653. itt[7] = -lerp.iteratorsScale(itt+3, t0, t1, t2);
  654. c->rasterizer.procs.texCoordGradScale8xv(c, i, itt);
  655. }
  656. }
  657. void lerp_texcoords_w(ogles_context_t* c,
  658. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  659. {
  660. const compute_iterators_t& lerp = c->lerp;
  661. int32_t itt[8] __attribute__((aligned(16)));
  662. int32_t itw[3];
  663. // compute W's scale to 2.30
  664. int32_t w0 = v0->window.w;
  665. int32_t w1 = v1->window.w;
  666. int32_t w2 = v2->window.w;
  667. int wscale = 32 - gglClz(w0|w1|w2);
  668. // compute the jacobian using block floating-point
  669. int sc = lerp.iteratorsScale(itw, w0, w1, w2);
  670. sc += wscale - 16;
  671. c->rasterizer.procs.wGrad3xv(c, itw);
  672. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  673. const texture_t& tmu = c->rasterizer.state.texture[i];
  674. if (!tmu.enable)
  675. continue;
  676. // compute the jacobians using block floating-point
  677. int32_t s0 = v0->texture[i].S;
  678. int32_t t0 = v0->texture[i].T;
  679. int32_t s1 = v1->texture[i].S;
  680. int32_t t1 = v1->texture[i].T;
  681. int32_t s2 = v2->texture[i].S;
  682. int32_t t2 = v2->texture[i].T;
  683. const GLenum min_filter = c->textures.tmu[i].texture->min_filter;
  684. if (ggl_unlikely(min_filter >= GL_NEAREST_MIPMAP_NEAREST)) {
  685. int lod = compute_lod(c, i, s0, t0, s1, t1, s2, t2);
  686. c->rasterizer.procs.bindTextureLod(c, i,
  687. &c->textures.tmu[i].texture->mip(lod));
  688. }
  689. // premultiply (s,t) when clampling
  690. if (tmu.s_wrap == GGL_CLAMP) {
  691. const int width = tmu.surface.width;
  692. s0 *= width;
  693. s1 *= width;
  694. s2 *= width;
  695. }
  696. if (tmu.t_wrap == GGL_CLAMP) {
  697. const int height = tmu.surface.height;
  698. t0 *= height;
  699. t1 *= height;
  700. t2 *= height;
  701. }
  702. s0 = gglMulx(s0, w0, wscale);
  703. t0 = gglMulx(t0, w0, wscale);
  704. s1 = gglMulx(s1, w1, wscale);
  705. t1 = gglMulx(t1, w1, wscale);
  706. s2 = gglMulx(s2, w2, wscale);
  707. t2 = gglMulx(t2, w2, wscale);
  708. itt[6] = sc - lerp.iteratorsScale(itt+0, s0, s1, s2);
  709. itt[7] = sc - lerp.iteratorsScale(itt+3, t0, t1, t2);
  710. c->rasterizer.procs.texCoordGradScale8xv(c, i, itt);
  711. }
  712. }
  713. static inline
  714. bool cull_triangle(ogles_context_t* c, vertex_t* /*v0*/, vertex_t* /*v1*/, vertex_t* /*v2*/)
  715. {
  716. if (ggl_likely(c->cull.enable)) {
  717. const GLenum winding = (c->lerp.area() > 0) ? GL_CW : GL_CCW;
  718. const GLenum face = (winding == c->cull.frontFace) ? GL_FRONT : GL_BACK;
  719. if (face == c->cull.cullFace)
  720. return true; // culled!
  721. }
  722. return false;
  723. }
  724. static inline
  725. GLfixed frustumPlaneDist(int plane, const vec4_t& s)
  726. {
  727. const GLfixed d = s.v[ plane >> 1 ];
  728. return ((plane & 1) ? (s.w - d) : (s.w + d));
  729. }
  730. static inline
  731. int32_t clipDivide(GLfixed a, GLfixed b) {
  732. // returns a 4.28 fixed-point
  733. return gglMulDivi(1LU<<28, a, b);
  734. }
  735. void clip_triangle(ogles_context_t* c,
  736. vertex_t* v0, vertex_t* v1, vertex_t* v2)
  737. {
  738. uint32_t all_cc = (v0->flags | v1->flags | v2->flags) & vertex_t::CLIP_ALL;
  739. vertex_t *p0, *p1, *p2;
  740. const int MAX_CLIPPING_PLANES = 6 + OGLES_MAX_CLIP_PLANES;
  741. const int MAX_VERTICES = 3;
  742. // Temporary buffer to hold the new vertices. Each plane can add up to
  743. // two new vertices (because the polygon is convex).
  744. // We need one extra element, to handle an overflow case when
  745. // the polygon degenerates into something non convex.
  746. vertex_t buffer[MAX_CLIPPING_PLANES * 2 + 1]; // ~3KB
  747. vertex_t* buf = buffer;
  748. // original list of vertices (polygon to clip, in fact this
  749. // function works with an arbitrary polygon).
  750. vertex_t* in[3] = { v0, v1, v2 };
  751. // output lists (we need 2, which we use back and forth)
  752. // (maximum outpout list's size is MAX_CLIPPING_PLANES + MAX_VERTICES)
  753. // 2 more elements for overflow when non convex polygons.
  754. vertex_t* out[2][MAX_CLIPPING_PLANES + MAX_VERTICES + 2];
  755. unsigned int outi = 0;
  756. // current input list
  757. vertex_t** ivl = in;
  758. // 3 input vertices, 0 in the output list, first plane
  759. unsigned int ic = 3;
  760. // User clip-planes first, the clipping is always done in eye-coordinate
  761. // this is basically the same algorithm than for the view-volume
  762. // clipping, except for the computation of the distance (vertex, plane)
  763. // and the fact that we need to compute the eye-coordinates of each
  764. // new vertex we create.
  765. if (ggl_unlikely(all_cc & vertex_t::USER_CLIP_ALL))
  766. {
  767. unsigned int plane = 0;
  768. uint32_t cc = (all_cc & vertex_t::USER_CLIP_ALL) >> 8;
  769. do {
  770. if (cc & 1) {
  771. // pointers to our output list (head and current)
  772. vertex_t** const ovl = &out[outi][0];
  773. vertex_t** output = ovl;
  774. unsigned int oc = 0;
  775. unsigned int sentinel = 0;
  776. // previous vertex, compute distance to the plane
  777. vertex_t* s = ivl[ic-1];
  778. const vec4_t& equation = c->clipPlanes.plane[plane].equation;
  779. GLfixed sd = dot4(equation.v, s->eye.v);
  780. // clip each vertex against this plane...
  781. for (unsigned int i=0 ; i<ic ; i++) {
  782. vertex_t* p = ivl[i];
  783. const GLfixed pd = dot4(equation.v, p->eye.v);
  784. if (sd >= 0) {
  785. if (pd >= 0) {
  786. // both inside
  787. *output++ = p;
  788. oc++;
  789. } else {
  790. // s inside, p outside (exiting)
  791. const GLfixed t = clipDivide(sd, sd-pd);
  792. c->arrays.clipEye(c, buf, t, p, s);
  793. *output++ = buf++;
  794. oc++;
  795. if (++sentinel >= 3)
  796. return; // non-convex polygon!
  797. }
  798. } else {
  799. if (pd >= 0) {
  800. // s outside (entering)
  801. if (pd) {
  802. const GLfixed t = clipDivide(pd, pd-sd);
  803. c->arrays.clipEye(c, buf, t, s, p);
  804. *output++ = buf++;
  805. oc++;
  806. if (++sentinel >= 3)
  807. return; // non-convex polygon!
  808. }
  809. *output++ = p;
  810. oc++;
  811. } else {
  812. // both outside
  813. }
  814. }
  815. s = p;
  816. sd = pd;
  817. }
  818. // output list become the new input list
  819. if (oc<3)
  820. return; // less than 3 vertices left? we're done!
  821. ivl = ovl;
  822. ic = oc;
  823. outi = 1-outi;
  824. }
  825. cc >>= 1;
  826. plane++;
  827. } while (cc);
  828. }
  829. // frustum clip-planes
  830. if (all_cc & vertex_t::FRUSTUM_CLIP_ALL)
  831. {
  832. unsigned int plane = 0;
  833. uint32_t cc = all_cc & vertex_t::FRUSTUM_CLIP_ALL;
  834. do {
  835. if (cc & 1) {
  836. // pointers to our output list (head and current)
  837. vertex_t** const ovl = &out[outi][0];
  838. vertex_t** output = ovl;
  839. unsigned int oc = 0;
  840. unsigned int sentinel = 0;
  841. // previous vertex, compute distance to the plane
  842. vertex_t* s = ivl[ic-1];
  843. GLfixed sd = frustumPlaneDist(plane, s->clip);
  844. // clip each vertex against this plane...
  845. for (unsigned int i=0 ; i<ic ; i++) {
  846. vertex_t* p = ivl[i];
  847. const GLfixed pd = frustumPlaneDist(plane, p->clip);
  848. if (sd >= 0) {
  849. if (pd >= 0) {
  850. // both inside
  851. *output++ = p;
  852. oc++;
  853. } else {
  854. // s inside, p outside (exiting)
  855. const GLfixed t = clipDivide(sd, sd-pd);
  856. c->arrays.clipVertex(c, buf, t, p, s);
  857. *output++ = buf++;
  858. oc++;
  859. if (++sentinel >= 3)
  860. return; // non-convex polygon!
  861. }
  862. } else {
  863. if (pd >= 0) {
  864. // s outside (entering)
  865. if (pd) {
  866. const GLfixed t = clipDivide(pd, pd-sd);
  867. c->arrays.clipVertex(c, buf, t, s, p);
  868. *output++ = buf++;
  869. oc++;
  870. if (++sentinel >= 3)
  871. return; // non-convex polygon!
  872. }
  873. *output++ = p;
  874. oc++;
  875. } else {
  876. // both outside
  877. }
  878. }
  879. s = p;
  880. sd = pd;
  881. }
  882. // output list become the new input list
  883. if (oc<3)
  884. return; // less than 3 vertices left? we're done!
  885. ivl = ovl;
  886. ic = oc;
  887. outi = 1-outi;
  888. }
  889. cc >>= 1;
  890. plane++;
  891. } while (cc);
  892. }
  893. // finally we can render our triangles...
  894. p0 = ivl[0];
  895. p1 = ivl[1];
  896. for (unsigned int i=2 ; i<ic ; i++) {
  897. p2 = ivl[i];
  898. c->lerp.initTriangle(p0, p1, p2);
  899. if (cull_triangle(c, p0, p1, p2)) {
  900. p1 = p2;
  901. continue; // culled!
  902. }
  903. triangle(c, p0, p1, p2);
  904. p1 = p2;
  905. }
  906. }
  907. unsigned int clip_line(ogles_context_t* c, vertex_t* s, vertex_t* p)
  908. {
  909. const uint32_t all_cc = (s->flags | p->flags) & vertex_t::CLIP_ALL;
  910. if (ggl_unlikely(all_cc & vertex_t::USER_CLIP_ALL))
  911. {
  912. unsigned int plane = 0;
  913. uint32_t cc = (all_cc & vertex_t::USER_CLIP_ALL) >> 8;
  914. do {
  915. if (cc & 1) {
  916. const vec4_t& equation = c->clipPlanes.plane[plane].equation;
  917. const GLfixed sd = dot4(equation.v, s->eye.v);
  918. const GLfixed pd = dot4(equation.v, p->eye.v);
  919. if (sd >= 0) {
  920. if (pd >= 0) {
  921. // both inside
  922. } else {
  923. // s inside, p outside (exiting)
  924. const GLfixed t = clipDivide(sd, sd-pd);
  925. c->arrays.clipEye(c, p, t, p, s);
  926. }
  927. } else {
  928. if (pd >= 0) {
  929. // s outside (entering)
  930. if (pd) {
  931. const GLfixed t = clipDivide(pd, pd-sd);
  932. c->arrays.clipEye(c, s, t, s, p);
  933. }
  934. } else {
  935. // both outside
  936. return 0;
  937. }
  938. }
  939. }
  940. cc >>= 1;
  941. plane++;
  942. } while (cc);
  943. }
  944. // frustum clip-planes
  945. if (all_cc & vertex_t::FRUSTUM_CLIP_ALL)
  946. {
  947. unsigned int plane = 0;
  948. uint32_t cc = all_cc & vertex_t::FRUSTUM_CLIP_ALL;
  949. do {
  950. if (cc & 1) {
  951. const GLfixed sd = frustumPlaneDist(plane, s->clip);
  952. const GLfixed pd = frustumPlaneDist(plane, p->clip);
  953. if (sd >= 0) {
  954. if (pd >= 0) {
  955. // both inside
  956. } else {
  957. // s inside, p outside (exiting)
  958. const GLfixed t = clipDivide(sd, sd-pd);
  959. c->arrays.clipVertex(c, p, t, p, s);
  960. }
  961. } else {
  962. if (pd >= 0) {
  963. // s outside (entering)
  964. if (pd) {
  965. const GLfixed t = clipDivide(pd, pd-sd);
  966. c->arrays.clipVertex(c, s, t, s, p);
  967. }
  968. } else {
  969. // both outside
  970. return 0;
  971. }
  972. }
  973. }
  974. cc >>= 1;
  975. plane++;
  976. } while (cc);
  977. }
  978. return 2;
  979. }
  980. }; // namespace android