array.cpp 47 KB

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