array.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590
  1. /*
  2. ** Copyright 2006, The Android Open Source Project
  3. **
  4. ** Licensed under the Apache License, Version 2.0 (the "License");
  5. ** you may not use this file except in compliance with the License.
  6. ** You may obtain a copy of the License at
  7. **
  8. ** http://www.apache.org/licenses/LICENSE-2.0
  9. **
  10. ** Unless required by applicable law or agreed to in writing, software
  11. ** distributed under the License is distributed on an "AS IS" BASIS,
  12. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ** See the License for the specific language governing permissions and
  14. ** limitations under the License.
  15. */
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include "context.h"
  19. #include "fp.h"
  20. #include "state.h"
  21. #include "matrix.h"
  22. #include "vertex.h"
  23. #include "light.h"
  24. #include "primitives.h"
  25. #include "texture.h"
  26. #include "BufferObjectManager.h"
  27. // ----------------------------------------------------------------------------
  28. #define VC_CACHE_STATISTICS 0
  29. #define VC_CACHE_TYPE_NONE 0
  30. #define VC_CACHE_TYPE_INDEXED 1
  31. #define VC_CACHE_TYPE_LRU 2
  32. #define VC_CACHE_TYPE VC_CACHE_TYPE_INDEXED
  33. #if VC_CACHE_STATISTICS
  34. #include <utils/Timers.h>
  35. #endif
  36. // ----------------------------------------------------------------------------
  37. namespace android {
  38. static void validate_arrays(ogles_context_t* c, GLenum mode);
  39. static void compileElements__generic(ogles_context_t*,
  40. vertex_t*, GLint, GLsizei);
  41. static void compileElement__generic(ogles_context_t*,
  42. vertex_t*, GLint);
  43. static void drawPrimitivesPoints(ogles_context_t*, GLint, GLsizei);
  44. static void drawPrimitivesLineStrip(ogles_context_t*, GLint, GLsizei);
  45. static void drawPrimitivesLineLoop(ogles_context_t*, GLint, GLsizei);
  46. static void drawPrimitivesLines(ogles_context_t*, GLint, GLsizei);
  47. static void drawPrimitivesTriangleStrip(ogles_context_t*, GLint, GLsizei);
  48. static void drawPrimitivesTriangleFan(ogles_context_t*, GLint, GLsizei);
  49. static void drawPrimitivesTriangles(ogles_context_t*, GLint, GLsizei);
  50. static void drawIndexedPrimitivesPoints(ogles_context_t*,
  51. GLsizei, const GLvoid*);
  52. static void drawIndexedPrimitivesLineStrip(ogles_context_t*,
  53. GLsizei, const GLvoid*);
  54. static void drawIndexedPrimitivesLineLoop(ogles_context_t*,
  55. GLsizei, const GLvoid*);
  56. static void drawIndexedPrimitivesLines(ogles_context_t*,
  57. GLsizei, const GLvoid*);
  58. static void drawIndexedPrimitivesTriangleStrip(ogles_context_t*,
  59. GLsizei, const GLvoid*);
  60. static void drawIndexedPrimitivesTriangleFan(ogles_context_t*,
  61. GLsizei, const GLvoid*);
  62. static void drawIndexedPrimitivesTriangles(ogles_context_t*,
  63. GLsizei, const GLvoid*);
  64. // ----------------------------------------------------------------------------
  65. typedef void (*arrays_prims_fct_t)(ogles_context_t*, GLint, GLsizei);
  66. static const arrays_prims_fct_t drawArraysPrims[] = {
  67. drawPrimitivesPoints,
  68. drawPrimitivesLines,
  69. drawPrimitivesLineLoop,
  70. drawPrimitivesLineStrip,
  71. drawPrimitivesTriangles,
  72. drawPrimitivesTriangleStrip,
  73. drawPrimitivesTriangleFan
  74. };
  75. typedef void (*elements_prims_fct_t)(ogles_context_t*, GLsizei, const GLvoid*);
  76. static const elements_prims_fct_t drawElementsPrims[] = {
  77. drawIndexedPrimitivesPoints,
  78. drawIndexedPrimitivesLines,
  79. drawIndexedPrimitivesLineLoop,
  80. drawIndexedPrimitivesLineStrip,
  81. drawIndexedPrimitivesTriangles,
  82. drawIndexedPrimitivesTriangleStrip,
  83. drawIndexedPrimitivesTriangleFan
  84. };
  85. // ----------------------------------------------------------------------------
  86. #if 0
  87. #pragma mark -
  88. #endif
  89. void ogles_init_array(ogles_context_t* c)
  90. {
  91. c->arrays.vertex.size = 4;
  92. c->arrays.vertex.type = GL_FLOAT;
  93. c->arrays.color.size = 4;
  94. c->arrays.color.type = GL_FLOAT;
  95. c->arrays.normal.size = 4;
  96. c->arrays.normal.type = GL_FLOAT;
  97. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  98. c->arrays.texture[i].size = 4;
  99. c->arrays.texture[i].type = GL_FLOAT;
  100. }
  101. c->vc.init();
  102. if (!c->vc.vBuffer) {
  103. // this could have failed
  104. ogles_error(c, GL_OUT_OF_MEMORY);
  105. }
  106. }
  107. void ogles_uninit_array(ogles_context_t* c)
  108. {
  109. c->vc.uninit();
  110. }
  111. // ----------------------------------------------------------------------------
  112. #if 0
  113. #pragma mark -
  114. #pragma mark Array fetchers
  115. #endif
  116. static void currentColor(ogles_context_t* c, GLfixed* v, const GLvoid*) {
  117. memcpy(v, c->current.color.v, sizeof(vec4_t));
  118. }
  119. static void currentNormal(ogles_context_t* c, GLfixed* v, const GLvoid*) {
  120. memcpy(v, c->currentNormal.v, sizeof(vec3_t));
  121. }
  122. static void currentTexCoord(ogles_context_t* c, GLfixed* v, const GLvoid*) {
  123. memcpy(v, c->current.texture[c->arrays.tmu].v, sizeof(vec4_t));
  124. }
  125. static void fetchNop(ogles_context_t*, GLfixed*, const GLvoid*) {
  126. }
  127. static void fetch2b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
  128. v[0] = gglIntToFixed(p[0]);
  129. v[1] = gglIntToFixed(p[1]);
  130. }
  131. static void fetch2s(ogles_context_t*, GLfixed* v, const GLshort* p) {
  132. v[0] = gglIntToFixed(p[0]);
  133. v[1] = gglIntToFixed(p[1]);
  134. }
  135. static void fetch2x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
  136. memcpy(v, p, 2*sizeof(GLfixed));
  137. }
  138. static void fetch2f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
  139. v[0] = gglFloatToFixed(p[0]);
  140. v[1] = gglFloatToFixed(p[1]);
  141. }
  142. static void fetch3b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
  143. v[0] = gglIntToFixed(p[0]);
  144. v[1] = gglIntToFixed(p[1]);
  145. v[2] = gglIntToFixed(p[2]);
  146. }
  147. static void fetch3s(ogles_context_t*, GLfixed* v, const GLshort* p) {
  148. v[0] = gglIntToFixed(p[0]);
  149. v[1] = gglIntToFixed(p[1]);
  150. v[2] = gglIntToFixed(p[2]);
  151. }
  152. static void fetch3x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
  153. memcpy(v, p, 3*sizeof(GLfixed));
  154. }
  155. static void fetch3f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
  156. v[0] = gglFloatToFixed(p[0]);
  157. v[1] = gglFloatToFixed(p[1]);
  158. v[2] = gglFloatToFixed(p[2]);
  159. }
  160. static void fetch4b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
  161. v[0] = gglIntToFixed(p[0]);
  162. v[1] = gglIntToFixed(p[1]);
  163. v[2] = gglIntToFixed(p[2]);
  164. v[3] = gglIntToFixed(p[3]);
  165. }
  166. static void fetch4s(ogles_context_t*, GLfixed* v, const GLshort* p) {
  167. v[0] = gglIntToFixed(p[0]);
  168. v[1] = gglIntToFixed(p[1]);
  169. v[2] = gglIntToFixed(p[2]);
  170. v[3] = gglIntToFixed(p[3]);
  171. }
  172. static void fetch4x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
  173. memcpy(v, p, 4*sizeof(GLfixed));
  174. }
  175. static void fetch4f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
  176. v[0] = gglFloatToFixed(p[0]);
  177. v[1] = gglFloatToFixed(p[1]);
  178. v[2] = gglFloatToFixed(p[2]);
  179. v[3] = gglFloatToFixed(p[3]);
  180. }
  181. static void fetchExpand4ub(ogles_context_t*, GLfixed* v, const GLubyte* p) {
  182. v[0] = GGL_UB_TO_X(p[0]);
  183. v[1] = GGL_UB_TO_X(p[1]);
  184. v[2] = GGL_UB_TO_X(p[2]);
  185. v[3] = GGL_UB_TO_X(p[3]);
  186. }
  187. static void fetchClamp4x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
  188. v[0] = gglClampx(p[0]);
  189. v[1] = gglClampx(p[1]);
  190. v[2] = gglClampx(p[2]);
  191. v[3] = gglClampx(p[3]);
  192. }
  193. static void fetchClamp4f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
  194. v[0] = gglClampx(gglFloatToFixed(p[0]));
  195. v[1] = gglClampx(gglFloatToFixed(p[1]));
  196. v[2] = gglClampx(gglFloatToFixed(p[2]));
  197. v[3] = gglClampx(gglFloatToFixed(p[3]));
  198. }
  199. static void fetchExpand3ub(ogles_context_t*, GLfixed* v, const GLubyte* p) {
  200. v[0] = GGL_UB_TO_X(p[0]);
  201. v[1] = GGL_UB_TO_X(p[1]);
  202. v[2] = GGL_UB_TO_X(p[2]);
  203. v[3] = 0x10000;
  204. }
  205. static void fetchClamp3x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
  206. v[0] = gglClampx(p[0]);
  207. v[1] = gglClampx(p[1]);
  208. v[2] = gglClampx(p[2]);
  209. v[3] = 0x10000;
  210. }
  211. static void fetchClamp3f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
  212. v[0] = gglClampx(gglFloatToFixed(p[0]));
  213. v[1] = gglClampx(gglFloatToFixed(p[1]));
  214. v[2] = gglClampx(gglFloatToFixed(p[2]));
  215. v[3] = 0x10000;
  216. }
  217. static void fetchExpand3b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
  218. v[0] = GGL_B_TO_X(p[0]);
  219. v[1] = GGL_B_TO_X(p[1]);
  220. v[2] = GGL_B_TO_X(p[2]);
  221. }
  222. static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) {
  223. v[0] = GGL_S_TO_X(p[0]);
  224. v[1] = GGL_S_TO_X(p[1]);
  225. v[2] = GGL_S_TO_X(p[2]);
  226. }
  227. typedef array_t::fetcher_t fn_t;
  228. static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x}
  229. { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
  230. (fn_t)fetch3f, 0, 0, 0, 0, 0,
  231. (fn_t)fetch3x },
  232. { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0,
  233. (fn_t)fetch4f, 0, 0, 0, 0, 0,
  234. (fn_t)fetch4x },
  235. };
  236. static const fn_t color_clamp_fct[2][16] = { // size={3,4}, type={ub,f,x}
  237. { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
  238. (fn_t)fetchClamp3f, 0, 0, 0, 0, 0,
  239. (fn_t)fetchClamp3x },
  240. { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0,
  241. (fn_t)fetchClamp4f, 0, 0, 0, 0, 0,
  242. (fn_t)fetchClamp4x },
  243. };
  244. static const fn_t normal_fct[1][16] = { // size={3}, type={b,s,f,x}
  245. { (fn_t)fetchExpand3b, 0,
  246. (fn_t)fetchExpand3s, 0, 0, 0,
  247. (fn_t)fetch3f, 0, 0, 0, 0, 0,
  248. (fn_t)fetch3x },
  249. };
  250. static const fn_t vertex_fct[3][16] = { // size={2,3,4}, type={b,s,f,x}
  251. { (fn_t)fetch2b, 0,
  252. (fn_t)fetch2s, 0, 0, 0,
  253. (fn_t)fetch2f, 0, 0, 0, 0, 0,
  254. (fn_t)fetch3x },
  255. { (fn_t)fetch3b, 0,
  256. (fn_t)fetch3s, 0, 0, 0,
  257. (fn_t)fetch3f, 0, 0, 0, 0, 0,
  258. (fn_t)fetch3x },
  259. { (fn_t)fetch4b, 0,
  260. (fn_t)fetch4s, 0, 0, 0,
  261. (fn_t)fetch4f, 0, 0, 0, 0, 0,
  262. (fn_t)fetch4x }
  263. };
  264. static const fn_t texture_fct[3][16] = { // size={2,3,4}, type={b,s,f,x}
  265. { (fn_t)fetch2b, 0,
  266. (fn_t)fetch2s, 0, 0, 0,
  267. (fn_t)fetch2f, 0, 0, 0, 0, 0,
  268. (fn_t)fetch2x },
  269. { (fn_t)fetch3b, 0,
  270. (fn_t)fetch3s, 0, 0, 0,
  271. (fn_t)fetch3f, 0, 0, 0, 0, 0,
  272. (fn_t)fetch3x },
  273. { (fn_t)fetch4b, 0,
  274. (fn_t)fetch4s, 0, 0, 0,
  275. (fn_t)fetch4f, 0, 0, 0, 0, 0,
  276. (fn_t)fetch4x }
  277. };
  278. // ----------------------------------------------------------------------------
  279. #if 0
  280. #pragma mark -
  281. #pragma mark array_t
  282. #endif
  283. void array_t::init(
  284. GLint size, GLenum type, GLsizei stride,
  285. const GLvoid *pointer, const buffer_t* bo, GLsizei count)
  286. {
  287. if (!stride) {
  288. stride = size;
  289. switch (type) {
  290. case GL_SHORT:
  291. case GL_UNSIGNED_SHORT:
  292. stride *= 2;
  293. break;
  294. case GL_FLOAT:
  295. case GL_FIXED:
  296. stride *= 4;
  297. break;
  298. }
  299. }
  300. this->size = size;
  301. this->type = type;
  302. this->stride = stride;
  303. this->pointer = pointer;
  304. this->bo = bo;
  305. this->bounds = count;
  306. }
  307. inline void array_t::resolve()
  308. {
  309. physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer;
  310. }
  311. // ----------------------------------------------------------------------------
  312. #if 0
  313. #pragma mark -
  314. #pragma mark vertex_cache_t
  315. #endif
  316. void vertex_cache_t::init()
  317. {
  318. // make sure the size of vertex_t allows cache-line alignment
  319. CTA<(sizeof(vertex_t) & 0x1F) == 0> assertAlignedSize;
  320. (void)assertAlignedSize; // suppress unused warning.
  321. const int align = 32;
  322. const size_t s = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
  323. const size_t size = s*sizeof(vertex_t) + align;
  324. base = malloc(size);
  325. if (base) {
  326. memset(base, 0, size);
  327. vBuffer = (vertex_t*)((size_t(base) + align - 1) & ~(align-1));
  328. vCache = vBuffer + VERTEX_BUFFER_SIZE;
  329. sequence = 0;
  330. }
  331. }
  332. void vertex_cache_t::uninit()
  333. {
  334. free(base);
  335. base = vBuffer = vCache = 0;
  336. }
  337. void vertex_cache_t::clear()
  338. {
  339. #if VC_CACHE_STATISTICS
  340. startTime = systemTime(SYSTEM_TIME_THREAD);
  341. total = 0;
  342. misses = 0;
  343. #endif
  344. #if VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
  345. vertex_t* v = vBuffer;
  346. size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
  347. do {
  348. v->mru = 0;
  349. v++;
  350. } while (--count);
  351. #endif
  352. sequence += INDEX_SEQ;
  353. if (sequence >= 0x80000000LU) {
  354. sequence = INDEX_SEQ;
  355. vertex_t* v = vBuffer;
  356. size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
  357. do {
  358. v->index = 0;
  359. v++;
  360. } while (--count);
  361. }
  362. }
  363. #if VC_CACHE_STATISTICS
  364. void vertex_cache_t::dump_stats(GLenum mode)
  365. {
  366. nsecs_t time = systemTime(SYSTEM_TIME_THREAD) - startTime;
  367. uint32_t hits = total - misses;
  368. uint32_t prim_count;
  369. switch (mode) {
  370. case GL_POINTS: prim_count = total; break;
  371. case GL_LINE_STRIP: prim_count = total - 1; break;
  372. case GL_LINE_LOOP: prim_count = total - 1; break;
  373. case GL_LINES: prim_count = total / 2; break;
  374. case GL_TRIANGLE_STRIP: prim_count = total - 2; break;
  375. case GL_TRIANGLE_FAN: prim_count = total - 2; break;
  376. case GL_TRIANGLES: prim_count = total / 3; break;
  377. default: return;
  378. }
  379. printf( "total=%5u, hits=%5u, miss=%5u, hitrate=%3u%%,"
  380. " prims=%5u, time=%6u us, prims/s=%d, v/t=%f\n",
  381. total, hits, misses, (hits*100)/total,
  382. prim_count, int(ns2us(time)), int(prim_count*float(seconds(1))/time),
  383. float(misses) / prim_count);
  384. }
  385. #else
  386. void vertex_cache_t::dump_stats(GLenum /*mode*/)
  387. {
  388. }
  389. #endif
  390. // ----------------------------------------------------------------------------
  391. #if 0
  392. #pragma mark -
  393. #endif
  394. static __attribute__((noinline))
  395. void enableDisableClientState(ogles_context_t* c, GLenum array, bool enable)
  396. {
  397. const int tmu = c->arrays.activeTexture;
  398. array_t* a;
  399. switch (array) {
  400. case GL_COLOR_ARRAY: a = &c->arrays.color; break;
  401. case GL_NORMAL_ARRAY: a = &c->arrays.normal; break;
  402. case GL_TEXTURE_COORD_ARRAY: a = &c->arrays.texture[tmu]; break;
  403. case GL_VERTEX_ARRAY: a = &c->arrays.vertex; break;
  404. default:
  405. ogles_error(c, GL_INVALID_ENUM);
  406. return;
  407. }
  408. a->enable = enable ? GL_TRUE : GL_FALSE;
  409. }
  410. // ----------------------------------------------------------------------------
  411. #if 0
  412. #pragma mark -
  413. #pragma mark Vertex Cache
  414. #endif
  415. static __attribute__((noinline))
  416. vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index)
  417. {
  418. #if VC_CACHE_STATISTICS
  419. c->vc.misses++;
  420. #endif
  421. if (ggl_unlikely(v->locked)) {
  422. // we're just looking for an entry in the cache that is not locked.
  423. // and we know that there cannot be more than 2 locked entries
  424. // because a triangle needs at most 3 vertices.
  425. // We never use the first and second entries because they might be in
  426. // use by the striper or faner. Any other entry will do as long as
  427. // it's not locked.
  428. // We compute directly the index of a "free" entry from the locked
  429. // state of v[2] and v[3].
  430. v = c->vc.vBuffer + 2;
  431. v += v[0].locked | (v[1].locked<<1);
  432. }
  433. // note: compileElement clears v->flags
  434. c->arrays.compileElement(c, v, index);
  435. v->locked = 1;
  436. return v;
  437. }
  438. static __attribute__((noinline))
  439. vertex_t* fetch_vertex(ogles_context_t* c, size_t index)
  440. {
  441. index |= c->vc.sequence;
  442. #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED
  443. vertex_t* const v = c->vc.vCache +
  444. (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1));
  445. if (ggl_likely(v->index == index)) {
  446. v->locked = 1;
  447. return v;
  448. }
  449. return cache_vertex(c, v, index);
  450. #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
  451. vertex_t* v = c->vc.vCache +
  452. (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2;
  453. // always record LRU in v[0]
  454. if (ggl_likely(v[0].index == index)) {
  455. v[0].locked = 1;
  456. v[0].mru = 0;
  457. return &v[0];
  458. }
  459. if (ggl_likely(v[1].index == index)) {
  460. v[1].locked = 1;
  461. v[0].mru = 1;
  462. return &v[1];
  463. }
  464. const int lru = 1 - v[0].mru;
  465. v[0].mru = lru;
  466. return cache_vertex(c, &v[lru], index);
  467. #elif VC_CACHE_TYPE == VC_CACHE_TYPE_NONE
  468. // just for debugging...
  469. vertex_t* v = c->vc.vBuffer + 2;
  470. return cache_vertex(c, v, index);
  471. #endif
  472. }
  473. // ----------------------------------------------------------------------------
  474. #if 0
  475. #pragma mark -
  476. #pragma mark Primitive Assembly
  477. #endif
  478. void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count)
  479. {
  480. if (ggl_unlikely(count < 1))
  481. return;
  482. // vertex cache size must be multiple of 1
  483. const GLsizei vcs =
  484. (vertex_cache_t::VERTEX_BUFFER_SIZE +
  485. vertex_cache_t::VERTEX_CACHE_SIZE);
  486. do {
  487. vertex_t* v = c->vc.vBuffer;
  488. GLsizei num = count > vcs ? vcs : count;
  489. c->arrays.cull = vertex_t::CLIP_ALL;
  490. c->arrays.compileElements(c, v, first, num);
  491. first += num;
  492. count -= num;
  493. if (!c->arrays.cull) {
  494. // quick/trivial reject of the whole batch
  495. do {
  496. const uint32_t cc = v[0].flags;
  497. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  498. c->prims.renderPoint(c, v);
  499. v++;
  500. num--;
  501. } while (num);
  502. }
  503. } while (count);
  504. }
  505. // ----------------------------------------------------------------------------
  506. void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count)
  507. {
  508. if (ggl_unlikely(count < 2))
  509. return;
  510. vertex_t *v, *v0, *v1;
  511. c->arrays.cull = vertex_t::CLIP_ALL;
  512. c->arrays.compileElement(c, c->vc.vBuffer, first);
  513. first += 1;
  514. count -= 1;
  515. // vertex cache size must be multiple of 1
  516. const GLsizei vcs =
  517. (vertex_cache_t::VERTEX_BUFFER_SIZE +
  518. vertex_cache_t::VERTEX_CACHE_SIZE - 1);
  519. do {
  520. v0 = c->vc.vBuffer + 0;
  521. v = c->vc.vBuffer + 1;
  522. GLsizei num = count > vcs ? vcs : count;
  523. c->arrays.compileElements(c, v, first, num);
  524. first += num;
  525. count -= num;
  526. if (!c->arrays.cull) {
  527. // quick/trivial reject of the whole batch
  528. do {
  529. v1 = v++;
  530. const uint32_t cc = v0->flags & v1->flags;
  531. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  532. c->prims.renderLine(c, v0, v1);
  533. v0 = v1;
  534. num--;
  535. } while (num);
  536. }
  537. // copy back the last processed vertex
  538. c->vc.vBuffer[0] = *v0;
  539. c->arrays.cull = v0->flags & vertex_t::CLIP_ALL;
  540. } while (count);
  541. }
  542. void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count)
  543. {
  544. if (ggl_unlikely(count < 2))
  545. return;
  546. drawPrimitivesLineStrip(c, first, count);
  547. if (ggl_likely(count >= 3)) {
  548. vertex_t* v0 = c->vc.vBuffer;
  549. vertex_t* v1 = c->vc.vBuffer + 1;
  550. c->arrays.compileElement(c, v1, first);
  551. const uint32_t cc = v0->flags & v1->flags;
  552. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  553. c->prims.renderLine(c, v0, v1);
  554. }
  555. }
  556. void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count)
  557. {
  558. if (ggl_unlikely(count < 2))
  559. return;
  560. // vertex cache size must be multiple of 2
  561. const GLsizei vcs =
  562. ((vertex_cache_t::VERTEX_BUFFER_SIZE +
  563. vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2;
  564. do {
  565. vertex_t* v = c->vc.vBuffer;
  566. GLsizei num = count > vcs ? vcs : count;
  567. c->arrays.cull = vertex_t::CLIP_ALL;
  568. c->arrays.compileElements(c, v, first, num);
  569. first += num;
  570. count -= num;
  571. if (!c->arrays.cull) {
  572. // quick/trivial reject of the whole batch
  573. num -= 2;
  574. do {
  575. const uint32_t cc = v[0].flags & v[1].flags;
  576. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  577. c->prims.renderLine(c, v, v+1);
  578. v += 2;
  579. num -= 2;
  580. } while (num >= 0);
  581. }
  582. } while (count >= 2);
  583. }
  584. // ----------------------------------------------------------------------------
  585. static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c,
  586. GLint first, GLsizei count, int winding)
  587. {
  588. // winding == 2 : fan
  589. // winding == 1 : strip
  590. if (ggl_unlikely(count < 3))
  591. return;
  592. vertex_t *v, *v0, *v1, *v2;
  593. c->arrays.cull = vertex_t::CLIP_ALL;
  594. c->arrays.compileElements(c, c->vc.vBuffer, first, 2);
  595. first += 2;
  596. count -= 2;
  597. // vertex cache size must be multiple of 2. This is extremely important
  598. // because it allows us to preserve the same winding when the whole
  599. // batch is culled. We also need 2 extra vertices in the array, because
  600. // we always keep the two first ones.
  601. const GLsizei vcs =
  602. ((vertex_cache_t::VERTEX_BUFFER_SIZE +
  603. vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2;
  604. do {
  605. v0 = c->vc.vBuffer + 0;
  606. v1 = c->vc.vBuffer + 1;
  607. v = c->vc.vBuffer + 2;
  608. GLsizei num = count > vcs ? vcs : count;
  609. c->arrays.compileElements(c, v, first, num);
  610. first += num;
  611. count -= num;
  612. if (!c->arrays.cull) {
  613. // quick/trivial reject of the whole batch
  614. do {
  615. v2 = v++;
  616. const uint32_t cc = v0->flags & v1->flags & v2->flags;
  617. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  618. c->prims.renderTriangle(c, v0, v1, v2);
  619. swap(((winding^=1) ? v1 : v0), v2);
  620. num--;
  621. } while (num);
  622. }
  623. if (count) {
  624. v0 = c->vc.vBuffer + 2 + vcs - 2;
  625. v1 = c->vc.vBuffer + 2 + vcs - 1;
  626. if ((winding&2) == 0) {
  627. // for strips copy back the two last compiled vertices
  628. c->vc.vBuffer[0] = *v0;
  629. }
  630. c->vc.vBuffer[1] = *v1;
  631. c->arrays.cull = v0->flags & v1->flags & vertex_t::CLIP_ALL;
  632. }
  633. } while (count > 0);
  634. }
  635. void drawPrimitivesTriangleStrip(ogles_context_t* c,
  636. GLint first, GLsizei count) {
  637. drawPrimitivesTriangleFanOrStrip(c, first, count, 1);
  638. }
  639. void drawPrimitivesTriangleFan(ogles_context_t* c,
  640. GLint first, GLsizei count) {
  641. drawPrimitivesTriangleFanOrStrip(c, first, count, 2);
  642. }
  643. void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count)
  644. {
  645. if (ggl_unlikely(count < 3))
  646. return;
  647. // vertex cache size must be multiple of 3
  648. const GLsizei vcs =
  649. ((vertex_cache_t::VERTEX_BUFFER_SIZE +
  650. vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3;
  651. do {
  652. vertex_t* v = c->vc.vBuffer;
  653. GLsizei num = count > vcs ? vcs : count;
  654. c->arrays.cull = vertex_t::CLIP_ALL;
  655. c->arrays.compileElements(c, v, first, num);
  656. first += num;
  657. count -= num;
  658. if (!c->arrays.cull) {
  659. // quick/trivial reject of the whole batch
  660. num -= 3;
  661. do {
  662. const uint32_t cc = v[0].flags & v[1].flags & v[2].flags;
  663. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  664. c->prims.renderTriangle(c, v, v+1, v+2);
  665. v += 3;
  666. num -= 3;
  667. } while (num >= 0);
  668. }
  669. } while (count >= 3);
  670. }
  671. // ----------------------------------------------------------------------------
  672. #if 0
  673. #pragma mark -
  674. #endif
  675. // this looks goofy, but gcc does a great job with this...
  676. static inline unsigned int read_index(int type, const GLvoid*& p) {
  677. unsigned int r;
  678. if (type) {
  679. r = *(const GLubyte*)p;
  680. p = (const GLubyte*)p + 1;
  681. } else {
  682. r = *(const GLushort*)p;
  683. p = (const GLushort*)p + 1;
  684. }
  685. return r;
  686. }
  687. // ----------------------------------------------------------------------------
  688. void drawIndexedPrimitivesPoints(ogles_context_t* c,
  689. GLsizei count, const GLvoid *indices)
  690. {
  691. if (ggl_unlikely(count < 1))
  692. return;
  693. const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
  694. do {
  695. vertex_t * v = fetch_vertex(c, read_index(type, indices));
  696. if (ggl_likely(!(v->flags & vertex_t::CLIP_ALL)))
  697. c->prims.renderPoint(c, v);
  698. v->locked = 0;
  699. count--;
  700. } while(count);
  701. }
  702. // ----------------------------------------------------------------------------
  703. void drawIndexedPrimitivesLineStrip(ogles_context_t* c,
  704. GLsizei count, const GLvoid *indices)
  705. {
  706. if (ggl_unlikely(count < 2))
  707. return;
  708. vertex_t * const v = c->vc.vBuffer;
  709. vertex_t* v0 = v;
  710. vertex_t* v1;
  711. const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
  712. c->arrays.compileElement(c, v0, read_index(type, indices));
  713. count -= 1;
  714. do {
  715. v1 = fetch_vertex(c, read_index(type, indices));
  716. const uint32_t cc = v0->flags & v1->flags;
  717. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  718. c->prims.renderLine(c, v0, v1);
  719. v0->locked = 0;
  720. v0 = v1;
  721. count--;
  722. } while (count);
  723. v1->locked = 0;
  724. }
  725. void drawIndexedPrimitivesLineLoop(ogles_context_t* c,
  726. GLsizei count, const GLvoid *indices)
  727. {
  728. if (ggl_unlikely(count <= 2)) {
  729. drawIndexedPrimitivesLines(c, count, indices);
  730. return;
  731. }
  732. vertex_t * const v = c->vc.vBuffer;
  733. vertex_t* v0 = v;
  734. vertex_t* v1;
  735. const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
  736. c->arrays.compileElement(c, v0, read_index(type, indices));
  737. count -= 1;
  738. do {
  739. v1 = fetch_vertex(c, read_index(type, indices));
  740. const uint32_t cc = v0->flags & v1->flags;
  741. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  742. c->prims.renderLine(c, v0, v1);
  743. v0->locked = 0;
  744. v0 = v1;
  745. count--;
  746. } while (count);
  747. v1->locked = 0;
  748. v1 = c->vc.vBuffer;
  749. const uint32_t cc = v0->flags & v1->flags;
  750. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  751. c->prims.renderLine(c, v0, v1);
  752. }
  753. void drawIndexedPrimitivesLines(ogles_context_t* c,
  754. GLsizei count, const GLvoid *indices)
  755. {
  756. if (ggl_unlikely(count < 2))
  757. return;
  758. count -= 2;
  759. const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
  760. do {
  761. vertex_t* const v0 = fetch_vertex(c, read_index(type, indices));
  762. vertex_t* const v1 = fetch_vertex(c, read_index(type, indices));
  763. const uint32_t cc = v0->flags & v1->flags;
  764. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  765. c->prims.renderLine(c, v0, v1);
  766. v0->locked = 0;
  767. v1->locked = 0;
  768. count -= 2;
  769. } while (count >= 0);
  770. }
  771. // ----------------------------------------------------------------------------
  772. static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c,
  773. GLsizei count, const GLvoid *indices, int winding)
  774. {
  775. // winding == 2 : fan
  776. // winding == 1 : strip
  777. if (ggl_unlikely(count < 3))
  778. return;
  779. vertex_t * const v = c->vc.vBuffer;
  780. vertex_t* v0 = v;
  781. vertex_t* v1 = v+1;
  782. vertex_t* v2;
  783. const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
  784. c->arrays.compileElement(c, v0, read_index(type, indices));
  785. c->arrays.compileElement(c, v1, read_index(type, indices));
  786. count -= 2;
  787. // note: GCC 4.1.1 here makes a prety interesting optimization
  788. // where it duplicates the loop below based on c->arrays.indicesType
  789. do {
  790. v2 = fetch_vertex(c, read_index(type, indices));
  791. const uint32_t cc = v0->flags & v1->flags & v2->flags;
  792. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  793. c->prims.renderTriangle(c, v0, v1, v2);
  794. vertex_t* & consumed = ((winding^=1) ? v1 : v0);
  795. consumed->locked = 0;
  796. consumed = v2;
  797. count--;
  798. } while (count);
  799. v0->locked = v1->locked = 0;
  800. v2->locked = 0;
  801. }
  802. void drawIndexedPrimitivesTriangleStrip(ogles_context_t* c,
  803. GLsizei count, const GLvoid *indices) {
  804. drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 1);
  805. }
  806. void drawIndexedPrimitivesTriangleFan(ogles_context_t* c,
  807. GLsizei count, const GLvoid *indices) {
  808. drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 2);
  809. }
  810. void drawIndexedPrimitivesTriangles(ogles_context_t* c,
  811. GLsizei count, const GLvoid *indices)
  812. {
  813. if (ggl_unlikely(count < 3))
  814. return;
  815. count -= 3;
  816. if (ggl_likely(c->arrays.indicesType == GL_UNSIGNED_SHORT)) {
  817. // This case is probably our most common case...
  818. uint16_t const * p = (uint16_t const *)indices;
  819. do {
  820. vertex_t* const v0 = fetch_vertex(c, *p++);
  821. vertex_t* const v1 = fetch_vertex(c, *p++);
  822. vertex_t* const v2 = fetch_vertex(c, *p++);
  823. const uint32_t cc = v0->flags & v1->flags & v2->flags;
  824. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  825. c->prims.renderTriangle(c, v0, v1, v2);
  826. v0->locked = 0;
  827. v1->locked = 0;
  828. v2->locked = 0;
  829. count -= 3;
  830. } while (count >= 0);
  831. } else {
  832. uint8_t const * p = (uint8_t const *)indices;
  833. do {
  834. vertex_t* const v0 = fetch_vertex(c, *p++);
  835. vertex_t* const v1 = fetch_vertex(c, *p++);
  836. vertex_t* const v2 = fetch_vertex(c, *p++);
  837. const uint32_t cc = v0->flags & v1->flags & v2->flags;
  838. if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
  839. c->prims.renderTriangle(c, v0, v1, v2);
  840. v0->locked = 0;
  841. v1->locked = 0;
  842. v2->locked = 0;
  843. count -= 3;
  844. } while (count >= 0);
  845. }
  846. }
  847. // ----------------------------------------------------------------------------
  848. #if 0
  849. #pragma mark -
  850. #pragma mark Array compilers
  851. #endif
  852. void compileElement__generic(ogles_context_t* c,
  853. vertex_t* v, GLint first)
  854. {
  855. v->flags = 0;
  856. v->index = first;
  857. first &= vertex_cache_t::INDEX_MASK;
  858. const GLubyte* vp = c->arrays.vertex.element(first);
  859. v->obj.z = 0;
  860. v->obj.w = 0x10000;
  861. c->arrays.vertex.fetch(c, v->obj.v, vp);
  862. c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj);
  863. c->arrays.perspective(c, v);
  864. }
  865. void compileElements__generic(ogles_context_t* c,
  866. vertex_t* v, GLint first, GLsizei count)
  867. {
  868. const GLubyte* vp = c->arrays.vertex.element(
  869. first & vertex_cache_t::INDEX_MASK);
  870. const size_t stride = c->arrays.vertex.stride;
  871. transform_t const* const mvp = &c->transforms.mvp;
  872. do {
  873. v->flags = 0;
  874. v->index = first++;
  875. v->obj.z = 0;
  876. v->obj.w = 0x10000;
  877. c->arrays.vertex.fetch(c, v->obj.v, vp);
  878. c->arrays.mvp_transform(mvp, &v->clip, &v->obj);
  879. c->arrays.perspective(c, v);
  880. vp += stride;
  881. v++;
  882. } while (--count);
  883. }
  884. /*
  885. void compileElements__3x_full(ogles_context_t* c,
  886. vertex_t* v, GLint first, GLsizei count)
  887. {
  888. const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first);
  889. const size_t stride = c->arrays.vertex.stride / 4;
  890. // const GLfixed* const& m = c->transforms.mvp.matrix.m;
  891. GLfixed m[16];
  892. memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m));
  893. do {
  894. const GLfixed rx = vp[0];
  895. const GLfixed ry = vp[1];
  896. const GLfixed rz = vp[2];
  897. vp += stride;
  898. v->index = first++;
  899. v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
  900. v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
  901. v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
  902. v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]);
  903. const GLfixed w = v->clip.w;
  904. uint32_t clip = 0;
  905. if (v->clip.x < -w) clip |= vertex_t::CLIP_L;
  906. if (v->clip.x > w) clip |= vertex_t::CLIP_R;
  907. if (v->clip.y < -w) clip |= vertex_t::CLIP_B;
  908. if (v->clip.y > w) clip |= vertex_t::CLIP_T;
  909. if (v->clip.z < -w) clip |= vertex_t::CLIP_N;
  910. if (v->clip.z > w) clip |= vertex_t::CLIP_F;
  911. v->flags = clip;
  912. c->arrays.cull &= clip;
  913. //c->arrays.perspective(c, v);
  914. v++;
  915. } while (--count);
  916. }
  917. */
  918. // ----------------------------------------------------------------------------
  919. #if 0
  920. #pragma mark -
  921. #pragma mark clippers
  922. #endif
  923. static void clipVec4(vec4_t& nv,
  924. GLfixed t, const vec4_t& s, const vec4_t& p)
  925. {
  926. for (int i=0; i<4 ; i++)
  927. nv.v[i] = gglMulAddx(t, s.v[i] - p.v[i], p.v[i], 28);
  928. }
  929. static void clipVertex(ogles_context_t* c, vertex_t* nv,
  930. GLfixed t, const vertex_t* s, const vertex_t* p)
  931. {
  932. clipVec4(nv->clip, t, s->clip, p->clip);
  933. nv->fog = gglMulAddx(t, s->fog - p->fog, p->fog, 28);
  934. ogles_vertex_project(c, nv);
  935. nv->flags |= vertex_t::LIT | vertex_t::EYE | vertex_t::TT;
  936. nv->flags &= ~vertex_t::CLIP_ALL;
  937. }
  938. static void clipVertexC(ogles_context_t* c, vertex_t* nv,
  939. GLfixed t, const vertex_t* s, const vertex_t* p)
  940. {
  941. clipVec4(nv->color, t, s->color, p->color);
  942. clipVertex(c, nv, t, s, p);
  943. }
  944. static void clipVertexT(ogles_context_t* c, vertex_t* nv,
  945. GLfixed t, const vertex_t* s, const vertex_t* p)
  946. {
  947. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  948. if (c->rasterizer.state.texture[i].enable)
  949. clipVec4(nv->texture[i], t, s->texture[i], p->texture[i]);
  950. }
  951. clipVertex(c, nv, t, s, p);
  952. }
  953. static void clipVertexAll(ogles_context_t* c, vertex_t* nv,
  954. GLfixed t, const vertex_t* s, const vertex_t* p)
  955. {
  956. clipVec4(nv->color, t, s->color, p->color);
  957. clipVertexT(c, nv, t, s, p);
  958. }
  959. static void clipEye(ogles_context_t* c, vertex_t* nv,
  960. GLfixed t, const vertex_t* s, const vertex_t* p)
  961. {
  962. nv->clear();
  963. c->arrays.clipVertex(c, nv, t, p, s);
  964. clipVec4(nv->eye, t, s->eye, p->eye);
  965. }
  966. // ----------------------------------------------------------------------------
  967. #if 0
  968. #pragma mark -
  969. #endif
  970. void validate_arrays(ogles_context_t* c, GLenum mode)
  971. {
  972. uint32_t enables = c->rasterizer.state.enables;
  973. // Perspective correction is not need if Ortho transform, but
  974. // the user can still provide the w coordinate manually, so we can't
  975. // automatically turn it off (in fact we could when the 4th coordinate
  976. // is not spcified in the vertex array).
  977. // W interpolation is never needed for points.
  978. GLboolean perspective =
  979. c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS);
  980. c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective);
  981. // set anti-aliasing
  982. GLboolean smooth = GL_FALSE;
  983. switch (mode) {
  984. case GL_POINTS:
  985. smooth = c->point.smooth;
  986. break;
  987. case GL_LINES:
  988. case GL_LINE_LOOP:
  989. case GL_LINE_STRIP:
  990. smooth = c->line.smooth;
  991. break;
  992. }
  993. if (((enables & GGL_ENABLE_AA)?1:0) != smooth)
  994. c->rasterizer.procs.enableDisable(c, GGL_AA, smooth);
  995. // set the shade model for this primitive
  996. c->rasterizer.procs.shadeModel(c,
  997. (mode == GL_POINTS) ? GL_FLAT : c->lighting.shadeModel);
  998. // compute all the matrices we'll need...
  999. uint32_t want =
  1000. transform_state_t::MVP |
  1001. transform_state_t::VIEWPORT;
  1002. if (c->lighting.enable) { // needs normal transforms and eye coords
  1003. want |= transform_state_t::MVUI;
  1004. want |= transform_state_t::MODELVIEW;
  1005. }
  1006. if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
  1007. want |= transform_state_t::TEXTURE;
  1008. }
  1009. if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
  1010. want |= transform_state_t::MODELVIEW; // needs eye coords
  1011. }
  1012. ogles_validate_transform(c, want);
  1013. // textures...
  1014. if (enables & GGL_ENABLE_TMUS)
  1015. ogles_validate_texture(c);
  1016. // vertex compilers
  1017. c->arrays.compileElement = compileElement__generic;
  1018. c->arrays.compileElements = compileElements__generic;
  1019. // vertex transform
  1020. c->arrays.mvp_transform =
  1021. c->transforms.mvp.pointv[c->arrays.vertex.size - 2];
  1022. c->arrays.mv_transform =
  1023. c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2];
  1024. /*
  1025. * ***********************************************************************
  1026. * pick fetchers
  1027. * ***********************************************************************
  1028. */
  1029. array_machine_t& am = c->arrays;
  1030. am.vertex.fetch = fetchNop;
  1031. am.normal.fetch = currentNormal;
  1032. am.color.fetch = currentColor;
  1033. if (am.vertex.enable) {
  1034. am.vertex.resolve();
  1035. if (am.vertex.bo || am.vertex.pointer) {
  1036. am.vertex.fetch = vertex_fct[am.vertex.size-2][am.vertex.type & 0xF];
  1037. }
  1038. }
  1039. if (am.normal.enable) {
  1040. am.normal.resolve();
  1041. if (am.normal.bo || am.normal.pointer) {
  1042. am.normal.fetch = normal_fct[am.normal.size-3][am.normal.type & 0xF];
  1043. }
  1044. }
  1045. if (am.color.enable) {
  1046. am.color.resolve();
  1047. if (c->lighting.enable) {
  1048. if (am.color.bo || am.color.pointer) {
  1049. am.color.fetch = color_fct[am.color.size-3][am.color.type & 0xF];
  1050. }
  1051. } else {
  1052. if (am.color.bo || am.color.pointer) {
  1053. am.color.fetch = color_clamp_fct[am.color.size-3][am.color.type & 0xF];
  1054. }
  1055. }
  1056. }
  1057. int activeTmuCount = 0;
  1058. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  1059. am.texture[i].fetch = currentTexCoord;
  1060. if (c->rasterizer.state.texture[i].enable) {
  1061. // texture fetchers...
  1062. if (am.texture[i].enable) {
  1063. am.texture[i].resolve();
  1064. if (am.texture[i].bo || am.texture[i].pointer) {
  1065. am.texture[i].fetch = texture_fct[am.texture[i].size-2][am.texture[i].type & 0xF];
  1066. }
  1067. }
  1068. // texture transform...
  1069. const int index = c->arrays.texture[i].size - 2;
  1070. c->arrays.tex_transform[i] =
  1071. c->transforms.texture[i].transform.pointv[index];
  1072. am.tmu = i;
  1073. activeTmuCount++;
  1074. }
  1075. }
  1076. // pick the vertex-clipper
  1077. uint32_t clipper = 0;
  1078. // we must reload 'enables' here
  1079. enables = c->rasterizer.state.enables;
  1080. if (enables & GGL_ENABLE_SMOOTH)
  1081. clipper |= 1; // we need to interpolate colors
  1082. if (enables & GGL_ENABLE_TMUS)
  1083. clipper |= 2; // we need to interpolate textures
  1084. switch (clipper) {
  1085. case 0: c->arrays.clipVertex = clipVertex; break;
  1086. case 1: c->arrays.clipVertex = clipVertexC; break;
  1087. case 2: c->arrays.clipVertex = clipVertexT; break;
  1088. case 3: c->arrays.clipVertex = clipVertexAll; break;
  1089. }
  1090. c->arrays.clipEye = clipEye;
  1091. // pick the primitive rasterizer
  1092. ogles_validate_primitives(c);
  1093. }
  1094. // ----------------------------------------------------------------------------
  1095. }; // namespace android
  1096. // ----------------------------------------------------------------------------
  1097. using namespace android;
  1098. #if 0
  1099. #pragma mark -
  1100. #pragma mark array API
  1101. #endif
  1102. void glVertexPointer(
  1103. GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1104. {
  1105. ogles_context_t* c = ogles_context_t::get();
  1106. if (size<2 || size>4 || stride<0) {
  1107. ogles_error(c, GL_INVALID_VALUE);
  1108. return;
  1109. }
  1110. switch (type) {
  1111. case GL_BYTE:
  1112. case GL_SHORT:
  1113. case GL_FIXED:
  1114. case GL_FLOAT:
  1115. break;
  1116. default:
  1117. ogles_error(c, GL_INVALID_ENUM);
  1118. return;
  1119. }
  1120. c->arrays.vertex.init(size, type, stride, pointer, c->arrays.array_buffer, 0);
  1121. }
  1122. void glColorPointer(
  1123. GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1124. {
  1125. ogles_context_t* c = ogles_context_t::get();
  1126. if (size!=4 || stride<0) {
  1127. ogles_error(c, GL_INVALID_VALUE);
  1128. return;
  1129. }
  1130. switch (type) {
  1131. case GL_UNSIGNED_BYTE:
  1132. case GL_FIXED:
  1133. case GL_FLOAT:
  1134. break;
  1135. default:
  1136. ogles_error(c, GL_INVALID_ENUM);
  1137. return;
  1138. }
  1139. c->arrays.color.init(size, type, stride, pointer, c->arrays.array_buffer, 0);
  1140. }
  1141. void glNormalPointer(
  1142. GLenum type, GLsizei stride, const GLvoid *pointer)
  1143. {
  1144. ogles_context_t* c = ogles_context_t::get();
  1145. if (stride<0) {
  1146. ogles_error(c, GL_INVALID_VALUE);
  1147. return;
  1148. }
  1149. switch (type) {
  1150. case GL_BYTE:
  1151. case GL_SHORT:
  1152. case GL_FIXED:
  1153. case GL_FLOAT:
  1154. break;
  1155. default:
  1156. ogles_error(c, GL_INVALID_ENUM);
  1157. return;
  1158. }
  1159. c->arrays.normal.init(3, type, stride, pointer, c->arrays.array_buffer, 0);
  1160. }
  1161. void glTexCoordPointer(
  1162. GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1163. {
  1164. ogles_context_t* c = ogles_context_t::get();
  1165. if (size<2 || size>4 || stride<0) {
  1166. ogles_error(c, GL_INVALID_VALUE);
  1167. return;
  1168. }
  1169. switch (type) {
  1170. case GL_BYTE:
  1171. case GL_SHORT:
  1172. case GL_FIXED:
  1173. case GL_FLOAT:
  1174. break;
  1175. default:
  1176. ogles_error(c, GL_INVALID_ENUM);
  1177. return;
  1178. }
  1179. const int tmu = c->arrays.activeTexture;
  1180. c->arrays.texture[tmu].init(size, type, stride, pointer,
  1181. c->arrays.array_buffer, 0);
  1182. }
  1183. void glEnableClientState(GLenum array) {
  1184. ogles_context_t* c = ogles_context_t::get();
  1185. enableDisableClientState(c, array, true);
  1186. }
  1187. void glDisableClientState(GLenum array) {
  1188. ogles_context_t* c = ogles_context_t::get();
  1189. enableDisableClientState(c, array, false);
  1190. }
  1191. void glClientActiveTexture(GLenum texture)
  1192. {
  1193. ogles_context_t* c = ogles_context_t::get();
  1194. if (texture<GL_TEXTURE0 || texture>=GL_TEXTURE0+GGL_TEXTURE_UNIT_COUNT) {
  1195. ogles_error(c, GL_INVALID_ENUM);
  1196. return;
  1197. }
  1198. c->arrays.activeTexture = texture - GL_TEXTURE0;
  1199. }
  1200. void glDrawArrays(GLenum mode, GLint first, GLsizei count)
  1201. {
  1202. ogles_context_t* c = ogles_context_t::get();
  1203. if (count<0) {
  1204. ogles_error(c, GL_INVALID_VALUE);
  1205. return;
  1206. }
  1207. switch (mode) {
  1208. case GL_POINTS:
  1209. case GL_LINE_STRIP:
  1210. case GL_LINE_LOOP:
  1211. case GL_LINES:
  1212. case GL_TRIANGLE_STRIP:
  1213. case GL_TRIANGLE_FAN:
  1214. case GL_TRIANGLES:
  1215. break;
  1216. default:
  1217. ogles_error(c, GL_INVALID_ENUM);
  1218. return;
  1219. }
  1220. if (count == 0 || !c->arrays.vertex.enable)
  1221. return;
  1222. if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
  1223. return; // all triangles are culled
  1224. validate_arrays(c, mode);
  1225. const uint32_t enables = c->rasterizer.state.enables;
  1226. if (enables & GGL_ENABLE_TMUS)
  1227. ogles_lock_textures(c);
  1228. drawArraysPrims[mode](c, first, count);
  1229. if (enables & GGL_ENABLE_TMUS)
  1230. ogles_unlock_textures(c);
  1231. #if VC_CACHE_STATISTICS
  1232. c->vc.total = count;
  1233. c->vc.dump_stats(mode);
  1234. #endif
  1235. }
  1236. void glDrawElements(
  1237. GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
  1238. {
  1239. ogles_context_t* c = ogles_context_t::get();
  1240. if (count<0) {
  1241. ogles_error(c, GL_INVALID_VALUE);
  1242. return;
  1243. }
  1244. switch (mode) {
  1245. case GL_POINTS:
  1246. case GL_LINE_STRIP:
  1247. case GL_LINE_LOOP:
  1248. case GL_LINES:
  1249. case GL_TRIANGLE_STRIP:
  1250. case GL_TRIANGLE_FAN:
  1251. case GL_TRIANGLES:
  1252. break;
  1253. default:
  1254. ogles_error(c, GL_INVALID_ENUM);
  1255. return;
  1256. }
  1257. switch (type) {
  1258. case GL_UNSIGNED_BYTE:
  1259. case GL_UNSIGNED_SHORT:
  1260. c->arrays.indicesType = type;
  1261. break;
  1262. default:
  1263. ogles_error(c, GL_INVALID_ENUM);
  1264. return;
  1265. }
  1266. if (count == 0 || !c->arrays.vertex.enable)
  1267. return;
  1268. if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
  1269. return; // all triangles are culled
  1270. // clear the vertex-cache
  1271. c->vc.clear();
  1272. validate_arrays(c, mode);
  1273. // if indices are in a buffer object, the pointer is treated as an
  1274. // offset in that buffer.
  1275. if (c->arrays.element_array_buffer) {
  1276. indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
  1277. }
  1278. const uint32_t enables = c->rasterizer.state.enables;
  1279. if (enables & GGL_ENABLE_TMUS)
  1280. ogles_lock_textures(c);
  1281. drawElementsPrims[mode](c, count, indices);
  1282. if (enables & GGL_ENABLE_TMUS)
  1283. ogles_unlock_textures(c);
  1284. #if VC_CACHE_STATISTICS
  1285. c->vc.total = count;
  1286. c->vc.dump_stats(mode);
  1287. #endif
  1288. }
  1289. // ----------------------------------------------------------------------------
  1290. // buffers
  1291. // ----------------------------------------------------------------------------
  1292. void glBindBuffer(GLenum target, GLuint buffer)
  1293. {
  1294. ogles_context_t* c = ogles_context_t::get();
  1295. if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
  1296. ogles_error(c, GL_INVALID_ENUM);
  1297. return;
  1298. }
  1299. // create a buffer object, or bind an existing one
  1300. buffer_t const* bo = 0;
  1301. if (buffer) {
  1302. bo = c->bufferObjectManager->bind(buffer);
  1303. if (!bo) {
  1304. ogles_error(c, GL_OUT_OF_MEMORY);
  1305. return;
  1306. }
  1307. }
  1308. ((target == GL_ARRAY_BUFFER) ?
  1309. c->arrays.array_buffer : c->arrays.element_array_buffer) = bo;
  1310. }
  1311. void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
  1312. {
  1313. ogles_context_t* c = ogles_context_t::get();
  1314. if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
  1315. ogles_error(c, GL_INVALID_ENUM);
  1316. return;
  1317. }
  1318. if (size<0) {
  1319. ogles_error(c, GL_INVALID_VALUE);
  1320. return;
  1321. }
  1322. if ((usage!=GL_STATIC_DRAW) && (usage!=GL_DYNAMIC_DRAW)) {
  1323. ogles_error(c, GL_INVALID_ENUM);
  1324. return;
  1325. }
  1326. buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
  1327. c->arrays.array_buffer : c->arrays.element_array_buffer);
  1328. if (bo == 0) {
  1329. // can't modify buffer 0
  1330. ogles_error(c, GL_INVALID_OPERATION);
  1331. return;
  1332. }
  1333. buffer_t* edit_bo = const_cast<buffer_t*>(bo);
  1334. if (c->bufferObjectManager->allocateStore(edit_bo, size, usage) != 0) {
  1335. ogles_error(c, GL_OUT_OF_MEMORY);
  1336. return;
  1337. }
  1338. if (data) {
  1339. memcpy(bo->data, data, size);
  1340. }
  1341. }
  1342. void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
  1343. {
  1344. ogles_context_t* c = ogles_context_t::get();
  1345. if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
  1346. ogles_error(c, GL_INVALID_ENUM);
  1347. return;
  1348. }
  1349. if (offset<0 || size<0 || data==0) {
  1350. ogles_error(c, GL_INVALID_VALUE);
  1351. return;
  1352. }
  1353. buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
  1354. c->arrays.array_buffer : c->arrays.element_array_buffer);
  1355. if (bo == 0) {
  1356. // can't modify buffer 0
  1357. ogles_error(c, GL_INVALID_OPERATION);
  1358. return;
  1359. }
  1360. if (offset+size > bo->size) {
  1361. ogles_error(c, GL_INVALID_VALUE);
  1362. return;
  1363. }
  1364. memcpy(bo->data + offset, data, size);
  1365. }
  1366. void glDeleteBuffers(GLsizei n, const GLuint* buffers)
  1367. {
  1368. ogles_context_t* c = ogles_context_t::get();
  1369. if (n<0) {
  1370. ogles_error(c, GL_INVALID_VALUE);
  1371. return;
  1372. }
  1373. for (int i=0 ; i<n ; i++) {
  1374. GLuint name = buffers[i];
  1375. if (name) {
  1376. // unbind bound deleted buffers...
  1377. if (c->arrays.element_array_buffer) {
  1378. if (c->arrays.element_array_buffer->name == name) {
  1379. c->arrays.element_array_buffer = 0;
  1380. }
  1381. }
  1382. if (c->arrays.array_buffer) {
  1383. if (c->arrays.array_buffer->name == name) {
  1384. c->arrays.array_buffer = 0;
  1385. }
  1386. }
  1387. if (c->arrays.vertex.bo) {
  1388. if (c->arrays.vertex.bo->name == name) {
  1389. c->arrays.vertex.bo = 0;
  1390. }
  1391. }
  1392. if (c->arrays.normal.bo) {
  1393. if (c->arrays.normal.bo->name == name) {
  1394. c->arrays.normal.bo = 0;
  1395. }
  1396. }
  1397. if (c->arrays.color.bo) {
  1398. if (c->arrays.color.bo->name == name) {
  1399. c->arrays.color.bo = 0;
  1400. }
  1401. }
  1402. for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) {
  1403. if (c->arrays.texture[t].bo) {
  1404. if (c->arrays.texture[t].bo->name == name) {
  1405. c->arrays.texture[t].bo = 0;
  1406. }
  1407. }
  1408. }
  1409. }
  1410. }
  1411. c->bufferObjectManager->deleteBuffers(n, buffers);
  1412. c->bufferObjectManager->recycleTokens(n, buffers);
  1413. }
  1414. void glGenBuffers(GLsizei n, GLuint* buffers)
  1415. {
  1416. ogles_context_t* c = ogles_context_t::get();
  1417. if (n<0) {
  1418. ogles_error(c, GL_INVALID_VALUE);
  1419. return;
  1420. }
  1421. c->bufferObjectManager->getToken(n, buffers);
  1422. }