texture.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. /* libs/opengles/texture.cpp
  2. **
  3. ** Copyright 2006, The Android Open Source Project
  4. **
  5. ** Licensed under the Apache License, Version 2.0 (the "License");
  6. ** you may not use this file except in compliance with the License.
  7. ** You may obtain a copy of the License at
  8. **
  9. ** http://www.apache.org/licenses/LICENSE-2.0
  10. **
  11. ** Unless required by applicable law or agreed to in writing, software
  12. ** distributed under the License is distributed on an "AS IS" BASIS,
  13. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. ** See the License for the specific language governing permissions and
  15. ** limitations under the License.
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include "context.h"
  20. #include "fp.h"
  21. #include "state.h"
  22. #include "texture.h"
  23. #include "TextureObjectManager.h"
  24. #include <ETC1/etc1.h>
  25. namespace android {
  26. // ----------------------------------------------------------------------------
  27. static void bindTextureTmu(
  28. ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex);
  29. static __attribute__((noinline))
  30. void generateMipmap(ogles_context_t* c, GLint level);
  31. // ----------------------------------------------------------------------------
  32. #if 0
  33. #pragma mark -
  34. #pragma mark Init
  35. #endif
  36. void ogles_init_texture(ogles_context_t* c)
  37. {
  38. c->textures.packAlignment = 4;
  39. c->textures.unpackAlignment = 4;
  40. // each context has a default named (0) texture (not shared)
  41. c->textures.defaultTexture = new EGLTextureObject();
  42. c->textures.defaultTexture->incStrong(c);
  43. // bind the default texture to each texture unit
  44. for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  45. bindTextureTmu(c, i, 0, c->textures.defaultTexture);
  46. memset(c->current.texture[i].v, 0, sizeof(vec4_t));
  47. c->current.texture[i].Q = 0x10000;
  48. }
  49. }
  50. void ogles_uninit_texture(ogles_context_t* c)
  51. {
  52. if (c->textures.ggl)
  53. gglUninit(c->textures.ggl);
  54. c->textures.defaultTexture->decStrong(c);
  55. for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  56. if (c->textures.tmu[i].texture)
  57. c->textures.tmu[i].texture->decStrong(c);
  58. }
  59. }
  60. static __attribute__((noinline))
  61. void validate_tmu(ogles_context_t* c, int i)
  62. {
  63. texture_unit_t& u(c->textures.tmu[i]);
  64. if (u.dirty) {
  65. u.dirty = 0;
  66. c->rasterizer.procs.activeTexture(c, i);
  67. c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
  68. c->rasterizer.procs.texGeni(c, GGL_S,
  69. GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
  70. c->rasterizer.procs.texGeni(c, GGL_T,
  71. GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC);
  72. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  73. GGL_TEXTURE_WRAP_S, u.texture->wraps);
  74. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  75. GGL_TEXTURE_WRAP_T, u.texture->wrapt);
  76. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  77. GGL_TEXTURE_MIN_FILTER, u.texture->min_filter);
  78. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  79. GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter);
  80. // disable this texture unit if it's not complete
  81. if (!u.texture->isComplete()) {
  82. c->rasterizer.procs.disable(c, GGL_TEXTURE_2D);
  83. }
  84. }
  85. }
  86. void ogles_validate_texture(ogles_context_t* c)
  87. {
  88. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  89. if (c->rasterizer.state.texture[i].enable)
  90. validate_tmu(c, i);
  91. }
  92. c->rasterizer.procs.activeTexture(c, c->textures.active);
  93. }
  94. static
  95. void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) {
  96. c->textures.tmu[tmu].dirty = flags;
  97. }
  98. /*
  99. * If the active textures are EGLImage, they need to be locked before
  100. * they can be used.
  101. *
  102. * FIXME: code below is far from being optimal
  103. *
  104. */
  105. void ogles_lock_textures(ogles_context_t* c)
  106. {
  107. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  108. if (c->rasterizer.state.texture[i].enable) {
  109. texture_unit_t& u(c->textures.tmu[i]);
  110. ANativeWindowBuffer* native_buffer = u.texture->buffer;
  111. if (native_buffer) {
  112. c->rasterizer.procs.activeTexture(c, i);
  113. hw_module_t const* pModule;
  114. if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
  115. continue;
  116. gralloc_module_t const* module =
  117. reinterpret_cast<gralloc_module_t const*>(pModule);
  118. void* vaddr;
  119. int err = module->lock(module, native_buffer->handle,
  120. GRALLOC_USAGE_SW_READ_OFTEN,
  121. 0, 0, native_buffer->width, native_buffer->height,
  122. &vaddr);
  123. u.texture->setImageBits(vaddr);
  124. c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
  125. }
  126. }
  127. }
  128. }
  129. void ogles_unlock_textures(ogles_context_t* c)
  130. {
  131. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  132. if (c->rasterizer.state.texture[i].enable) {
  133. texture_unit_t& u(c->textures.tmu[i]);
  134. ANativeWindowBuffer* native_buffer = u.texture->buffer;
  135. if (native_buffer) {
  136. c->rasterizer.procs.activeTexture(c, i);
  137. hw_module_t const* pModule;
  138. if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule))
  139. continue;
  140. gralloc_module_t const* module =
  141. reinterpret_cast<gralloc_module_t const*>(pModule);
  142. module->unlock(module, native_buffer->handle);
  143. u.texture->setImageBits(NULL);
  144. c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
  145. }
  146. }
  147. }
  148. c->rasterizer.procs.activeTexture(c, c->textures.active);
  149. }
  150. // ----------------------------------------------------------------------------
  151. #if 0
  152. #pragma mark -
  153. #pragma mark Format conversion
  154. #endif
  155. static uint32_t gl2format_table[6][4] = {
  156. // BYTE, 565, 4444, 5551
  157. { GGL_PIXEL_FORMAT_A_8,
  158. 0, 0, 0 }, // GL_ALPHA
  159. { GGL_PIXEL_FORMAT_RGB_888,
  160. GGL_PIXEL_FORMAT_RGB_565,
  161. 0, 0 }, // GL_RGB
  162. { GGL_PIXEL_FORMAT_RGBA_8888,
  163. 0,
  164. GGL_PIXEL_FORMAT_RGBA_4444,
  165. GGL_PIXEL_FORMAT_RGBA_5551 }, // GL_RGBA
  166. { GGL_PIXEL_FORMAT_L_8,
  167. 0, 0, 0 }, // GL_LUMINANCE
  168. { GGL_PIXEL_FORMAT_LA_88,
  169. 0, 0, 0 }, // GL_LUMINANCE_ALPHA
  170. };
  171. static int32_t convertGLPixelFormat(GLint format, GLenum type)
  172. {
  173. int32_t fi = -1;
  174. int32_t ti = -1;
  175. switch (format) {
  176. case GL_ALPHA: fi = 0; break;
  177. case GL_RGB: fi = 1; break;
  178. case GL_RGBA: fi = 2; break;
  179. case GL_LUMINANCE: fi = 3; break;
  180. case GL_LUMINANCE_ALPHA: fi = 4; break;
  181. }
  182. switch (type) {
  183. case GL_UNSIGNED_BYTE: ti = 0; break;
  184. case GL_UNSIGNED_SHORT_5_6_5: ti = 1; break;
  185. case GL_UNSIGNED_SHORT_4_4_4_4: ti = 2; break;
  186. case GL_UNSIGNED_SHORT_5_5_5_1: ti = 3; break;
  187. }
  188. if (fi==-1 || ti==-1)
  189. return 0;
  190. return gl2format_table[fi][ti];
  191. }
  192. // ----------------------------------------------------------------------------
  193. static GLenum validFormatType(ogles_context_t* c, GLenum format, GLenum type)
  194. {
  195. GLenum error = 0;
  196. if (format<GL_ALPHA || format>GL_LUMINANCE_ALPHA) {
  197. error = GL_INVALID_ENUM;
  198. }
  199. if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT_4_4_4_4 &&
  200. type != GL_UNSIGNED_SHORT_5_5_5_1 && type != GL_UNSIGNED_SHORT_5_6_5) {
  201. error = GL_INVALID_ENUM;
  202. }
  203. if (type == GL_UNSIGNED_SHORT_5_6_5 && format != GL_RGB) {
  204. error = GL_INVALID_OPERATION;
  205. }
  206. if ((type == GL_UNSIGNED_SHORT_4_4_4_4 ||
  207. type == GL_UNSIGNED_SHORT_5_5_5_1) && format != GL_RGBA) {
  208. error = GL_INVALID_OPERATION;
  209. }
  210. if (error) {
  211. ogles_error(c, error);
  212. }
  213. return error;
  214. }
  215. // ----------------------------------------------------------------------------
  216. GGLContext* getRasterizer(ogles_context_t* c)
  217. {
  218. GGLContext* ggl = c->textures.ggl;
  219. if (ggl_unlikely(!ggl)) {
  220. // this is quite heavy the first time...
  221. gglInit(&ggl);
  222. if (!ggl) {
  223. return 0;
  224. }
  225. GGLfixed colors[4] = { 0, 0, 0, 0x10000 };
  226. c->textures.ggl = ggl;
  227. ggl->activeTexture(ggl, 0);
  228. ggl->enable(ggl, GGL_TEXTURE_2D);
  229. ggl->texEnvi(ggl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
  230. ggl->disable(ggl, GGL_DITHER);
  231. ggl->shadeModel(ggl, GGL_FLAT);
  232. ggl->color4xv(ggl, colors);
  233. }
  234. return ggl;
  235. }
  236. static __attribute__((noinline))
  237. int copyPixels(
  238. ogles_context_t* c,
  239. const GGLSurface& dst,
  240. GLint xoffset, GLint yoffset,
  241. const GGLSurface& src,
  242. GLint x, GLint y, GLsizei w, GLsizei h)
  243. {
  244. if ((dst.format == src.format) &&
  245. (dst.stride == src.stride) &&
  246. (dst.width == src.width) &&
  247. (dst.height == src.height) &&
  248. (dst.stride > 0) &&
  249. ((x|y) == 0) &&
  250. ((xoffset|yoffset) == 0))
  251. {
  252. // this is a common case...
  253. const GGLFormat& pixelFormat(c->rasterizer.formats[src.format]);
  254. const size_t size = src.height * src.stride * pixelFormat.size;
  255. memcpy(dst.data, src.data, size);
  256. return 0;
  257. }
  258. // use pixel-flinger to handle all the conversions
  259. GGLContext* ggl = getRasterizer(c);
  260. if (!ggl) {
  261. // the only reason this would fail is because we ran out of memory
  262. return GL_OUT_OF_MEMORY;
  263. }
  264. ggl->colorBuffer(ggl, &dst);
  265. ggl->bindTexture(ggl, &src);
  266. ggl->texCoord2i(ggl, x-xoffset, y-yoffset);
  267. ggl->recti(ggl, xoffset, yoffset, xoffset+w, yoffset+h);
  268. return 0;
  269. }
  270. // ----------------------------------------------------------------------------
  271. static __attribute__((noinline))
  272. sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c)
  273. {
  274. sp<EGLTextureObject> tex;
  275. const int active = c->textures.active;
  276. const GLuint name = c->textures.tmu[active].name;
  277. // free the reference to the previously bound object
  278. texture_unit_t& u(c->textures.tmu[active]);
  279. if (u.texture)
  280. u.texture->decStrong(c);
  281. if (name == 0) {
  282. // 0 is our local texture object, not shared with anyone.
  283. // But it affects all bound TMUs immediately.
  284. // (we need to invalidate all units bound to this texture object)
  285. tex = c->textures.defaultTexture;
  286. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  287. if (c->textures.tmu[i].texture == tex.get())
  288. invalidate_texture(c, i);
  289. }
  290. } else {
  291. // get a new texture object for that name
  292. tex = c->surfaceManager->replaceTexture(name);
  293. }
  294. // bind this texture to the current active texture unit
  295. // and add a reference to this texture object
  296. u.texture = tex.get();
  297. u.texture->incStrong(c);
  298. u.name = name;
  299. invalidate_texture(c, active);
  300. return tex;
  301. }
  302. void bindTextureTmu(
  303. ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex)
  304. {
  305. if (tex.get() == c->textures.tmu[tmu].texture)
  306. return;
  307. // free the reference to the previously bound object
  308. texture_unit_t& u(c->textures.tmu[tmu]);
  309. if (u.texture)
  310. u.texture->decStrong(c);
  311. // bind this texture to the current active texture unit
  312. // and add a reference to this texture object
  313. u.texture = tex.get();
  314. u.texture->incStrong(c);
  315. u.name = texture;
  316. invalidate_texture(c, tmu);
  317. }
  318. int createTextureSurface(ogles_context_t* c,
  319. GGLSurface** outSurface, int32_t* outSize, GLint level,
  320. GLenum format, GLenum type, GLsizei width, GLsizei height,
  321. GLenum compressedFormat = 0)
  322. {
  323. // find out which texture is bound to the current unit
  324. const int active = c->textures.active;
  325. const GLuint name = c->textures.tmu[active].name;
  326. // convert the pixelformat to one we can handle
  327. const int32_t formatIdx = convertGLPixelFormat(format, type);
  328. if (formatIdx == 0) { // we don't know what to do with this
  329. return GL_INVALID_OPERATION;
  330. }
  331. // figure out the size we need as well as the stride
  332. const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
  333. const int32_t align = c->textures.unpackAlignment-1;
  334. const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
  335. const size_t size = bpr * height;
  336. const int32_t stride = bpr / pixelFormat.size;
  337. if (level > 0) {
  338. const int active = c->textures.active;
  339. EGLTextureObject* tex = c->textures.tmu[active].texture;
  340. status_t err = tex->reallocate(level,
  341. width, height, stride, formatIdx, compressedFormat, bpr);
  342. if (err != NO_ERROR)
  343. return GL_OUT_OF_MEMORY;
  344. GGLSurface& surface = tex->editMip(level);
  345. *outSurface = &surface;
  346. *outSize = size;
  347. return 0;
  348. }
  349. sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
  350. status_t err = tex->reallocate(level,
  351. width, height, stride, formatIdx, compressedFormat, bpr);
  352. if (err != NO_ERROR)
  353. return GL_OUT_OF_MEMORY;
  354. tex->internalformat = format;
  355. *outSurface = &tex->surface;
  356. *outSize = size;
  357. return 0;
  358. }
  359. static size_t dataSizePalette4(int numLevels, int width, int height, int format)
  360. {
  361. int indexBits = 8;
  362. int entrySize = 0;
  363. switch (format) {
  364. case GL_PALETTE4_RGB8_OES:
  365. indexBits = 4;
  366. /* FALLTHROUGH */
  367. case GL_PALETTE8_RGB8_OES:
  368. entrySize = 3;
  369. break;
  370. case GL_PALETTE4_RGBA8_OES:
  371. indexBits = 4;
  372. /* FALLTHROUGH */
  373. case GL_PALETTE8_RGBA8_OES:
  374. entrySize = 4;
  375. break;
  376. case GL_PALETTE4_R5_G6_B5_OES:
  377. case GL_PALETTE4_RGBA4_OES:
  378. case GL_PALETTE4_RGB5_A1_OES:
  379. indexBits = 4;
  380. /* FALLTHROUGH */
  381. case GL_PALETTE8_R5_G6_B5_OES:
  382. case GL_PALETTE8_RGBA4_OES:
  383. case GL_PALETTE8_RGB5_A1_OES:
  384. entrySize = 2;
  385. break;
  386. }
  387. size_t size = (1 << indexBits) * entrySize; // palette size
  388. for (int i=0 ; i< numLevels ; i++) {
  389. int w = (width >> i) ? : 1;
  390. int h = (height >> i) ? : 1;
  391. int levelSize = h * ((w * indexBits) / 8) ? : 1;
  392. size += levelSize;
  393. }
  394. return size;
  395. }
  396. static void decodePalette4(const GLvoid *data, int level, int width, int height,
  397. void *surface, int stride, int format)
  398. {
  399. int indexBits = 8;
  400. int entrySize = 0;
  401. switch (format) {
  402. case GL_PALETTE4_RGB8_OES:
  403. indexBits = 4;
  404. /* FALLTHROUGH */
  405. case GL_PALETTE8_RGB8_OES:
  406. entrySize = 3;
  407. break;
  408. case GL_PALETTE4_RGBA8_OES:
  409. indexBits = 4;
  410. /* FALLTHROUGH */
  411. case GL_PALETTE8_RGBA8_OES:
  412. entrySize = 4;
  413. break;
  414. case GL_PALETTE4_R5_G6_B5_OES:
  415. case GL_PALETTE4_RGBA4_OES:
  416. case GL_PALETTE4_RGB5_A1_OES:
  417. indexBits = 4;
  418. /* FALLTHROUGH */
  419. case GL_PALETTE8_R5_G6_B5_OES:
  420. case GL_PALETTE8_RGBA4_OES:
  421. case GL_PALETTE8_RGB5_A1_OES:
  422. entrySize = 2;
  423. break;
  424. }
  425. const int paletteSize = (1 << indexBits) * entrySize;
  426. uint8_t const* pixels = (uint8_t *)data + paletteSize;
  427. for (int i=0 ; i<level ; i++) {
  428. int w = (width >> i) ? : 1;
  429. int h = (height >> i) ? : 1;
  430. pixels += h * ((w * indexBits) / 8);
  431. }
  432. width = (width >> level) ? : 1;
  433. height = (height >> level) ? : 1;
  434. if (entrySize == 2) {
  435. uint8_t const* const palette = (uint8_t*)data;
  436. for (int y=0 ; y<height ; y++) {
  437. uint8_t* p = (uint8_t*)surface + y*stride*2;
  438. if (indexBits == 8) {
  439. for (int x=0 ; x<width ; x++) {
  440. int index = 2 * (*pixels++);
  441. *p++ = palette[index + 0];
  442. *p++ = palette[index + 1];
  443. }
  444. } else {
  445. for (int x=0 ; x<width ; x+=2) {
  446. int v = *pixels++;
  447. int index = 2 * (v >> 4);
  448. *p++ = palette[index + 0];
  449. *p++ = palette[index + 1];
  450. if (x+1 < width) {
  451. index = 2 * (v & 0xF);
  452. *p++ = palette[index + 0];
  453. *p++ = palette[index + 1];
  454. }
  455. }
  456. }
  457. }
  458. } else if (entrySize == 3) {
  459. uint8_t const* const palette = (uint8_t*)data;
  460. for (int y=0 ; y<height ; y++) {
  461. uint8_t* p = (uint8_t*)surface + y*stride*3;
  462. if (indexBits == 8) {
  463. for (int x=0 ; x<width ; x++) {
  464. int index = 3 * (*pixels++);
  465. *p++ = palette[index + 0];
  466. *p++ = palette[index + 1];
  467. *p++ = palette[index + 2];
  468. }
  469. } else {
  470. for (int x=0 ; x<width ; x+=2) {
  471. int v = *pixels++;
  472. int index = 3 * (v >> 4);
  473. *p++ = palette[index + 0];
  474. *p++ = palette[index + 1];
  475. *p++ = palette[index + 2];
  476. if (x+1 < width) {
  477. index = 3 * (v & 0xF);
  478. *p++ = palette[index + 0];
  479. *p++ = palette[index + 1];
  480. *p++ = palette[index + 2];
  481. }
  482. }
  483. }
  484. }
  485. } else if (entrySize == 4) {
  486. uint8_t const* const palette = (uint8_t*)data;
  487. for (int y=0 ; y<height ; y++) {
  488. uint8_t* p = (uint8_t*)surface + y*stride*4;
  489. if (indexBits == 8) {
  490. for (int x=0 ; x<width ; x++) {
  491. int index = 4 * (*pixels++);
  492. *p++ = palette[index + 0];
  493. *p++ = palette[index + 1];
  494. *p++ = palette[index + 2];
  495. *p++ = palette[index + 3];
  496. }
  497. } else {
  498. for (int x=0 ; x<width ; x+=2) {
  499. int v = *pixels++;
  500. int index = 4 * (v >> 4);
  501. *p++ = palette[index + 0];
  502. *p++ = palette[index + 1];
  503. *p++ = palette[index + 2];
  504. *p++ = palette[index + 3];
  505. if (x+1 < width) {
  506. index = 4 * (v & 0xF);
  507. *p++ = palette[index + 0];
  508. *p++ = palette[index + 1];
  509. *p++ = palette[index + 2];
  510. *p++ = palette[index + 3];
  511. }
  512. }
  513. }
  514. }
  515. }
  516. }
  517. static __attribute__((noinline))
  518. void set_depth_and_fog(ogles_context_t* c, GGLfixed z)
  519. {
  520. const uint32_t enables = c->rasterizer.state.enables;
  521. // we need to compute Zw
  522. int32_t iterators[3];
  523. iterators[1] = iterators[2] = 0;
  524. GGLfixed Zw;
  525. GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear);
  526. GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar);
  527. if (z<=0) Zw = n;
  528. else if (z>=0x10000) Zw = f;
  529. else Zw = gglMulAddx(z, (f-n), n);
  530. if (enables & GGL_ENABLE_FOG) {
  531. // set up fog if needed...
  532. iterators[0] = c->fog.fog(c, Zw);
  533. c->rasterizer.procs.fogGrad3xv(c, iterators);
  534. }
  535. if (enables & GGL_ENABLE_DEPTH_TEST) {
  536. // set up z-test if needed...
  537. int32_t z = (Zw & ~(Zw>>31));
  538. if (z >= 0x10000)
  539. z = 0xFFFF;
  540. iterators[0] = (z << 16) | z;
  541. c->rasterizer.procs.zGrad3xv(c, iterators);
  542. }
  543. }
  544. // ----------------------------------------------------------------------------
  545. #if 0
  546. #pragma mark -
  547. #pragma mark Generate mimaps
  548. #endif
  549. extern status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex);
  550. void generateMipmap(ogles_context_t* c, GLint level)
  551. {
  552. if (level == 0) {
  553. const int active = c->textures.active;
  554. EGLTextureObject* tex = c->textures.tmu[active].texture;
  555. if (tex->generate_mipmap) {
  556. if (buildAPyramid(c, tex) != NO_ERROR) {
  557. ogles_error(c, GL_OUT_OF_MEMORY);
  558. return;
  559. }
  560. }
  561. }
  562. }
  563. static void texParameterx(
  564. GLenum target, GLenum pname, GLfixed param, ogles_context_t* c)
  565. {
  566. if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
  567. ogles_error(c, GL_INVALID_ENUM);
  568. return;
  569. }
  570. EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
  571. switch (pname) {
  572. case GL_TEXTURE_WRAP_S:
  573. if ((param == GL_REPEAT) ||
  574. (param == GL_CLAMP_TO_EDGE)) {
  575. textureObject->wraps = param;
  576. } else {
  577. goto invalid_enum;
  578. }
  579. break;
  580. case GL_TEXTURE_WRAP_T:
  581. if ((param == GL_REPEAT) ||
  582. (param == GL_CLAMP_TO_EDGE)) {
  583. textureObject->wrapt = param;
  584. } else {
  585. goto invalid_enum;
  586. }
  587. break;
  588. case GL_TEXTURE_MIN_FILTER:
  589. if ((param == GL_NEAREST) ||
  590. (param == GL_LINEAR) ||
  591. (param == GL_NEAREST_MIPMAP_NEAREST) ||
  592. (param == GL_LINEAR_MIPMAP_NEAREST) ||
  593. (param == GL_NEAREST_MIPMAP_LINEAR) ||
  594. (param == GL_LINEAR_MIPMAP_LINEAR)) {
  595. textureObject->min_filter = param;
  596. } else {
  597. goto invalid_enum;
  598. }
  599. break;
  600. case GL_TEXTURE_MAG_FILTER:
  601. if ((param == GL_NEAREST) ||
  602. (param == GL_LINEAR)) {
  603. textureObject->mag_filter = param;
  604. } else {
  605. goto invalid_enum;
  606. }
  607. break;
  608. case GL_GENERATE_MIPMAP:
  609. textureObject->generate_mipmap = param;
  610. break;
  611. default:
  612. invalid_enum:
  613. ogles_error(c, GL_INVALID_ENUM);
  614. return;
  615. }
  616. invalidate_texture(c, c->textures.active);
  617. }
  618. static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
  619. ogles_context_t* c)
  620. {
  621. ogles_lock_textures(c);
  622. const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
  623. y = gglIntToFixed(cbSurface.height) - (y + h);
  624. w >>= FIXED_BITS;
  625. h >>= FIXED_BITS;
  626. // set up all texture units
  627. for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
  628. if (!c->rasterizer.state.texture[i].enable)
  629. continue;
  630. int32_t texcoords[8];
  631. texture_unit_t& u(c->textures.tmu[i]);
  632. // validate this tmu (bind, wrap, filter)
  633. validate_tmu(c, i);
  634. // we CLAMP here, which works with premultiplied (s,t)
  635. c->rasterizer.procs.texParameteri(c,
  636. GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP);
  637. c->rasterizer.procs.texParameteri(c,
  638. GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP);
  639. u.dirty = 0xFF; // XXX: should be more subtle
  640. EGLTextureObject* textureObject = u.texture;
  641. const GLint Ucr = textureObject->crop_rect[0] << 16;
  642. const GLint Vcr = textureObject->crop_rect[1] << 16;
  643. const GLint Wcr = textureObject->crop_rect[2] << 16;
  644. const GLint Hcr = textureObject->crop_rect[3] << 16;
  645. // computes texture coordinates (pre-multiplied)
  646. int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt
  647. int32_t dtdy =-Hcr / h; // dtdy = -((Hcr/h)/Ht)*Ht
  648. int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx
  649. int32_t t0 = (Vcr+Hcr) - gglMulx(dtdy, y); // t0 = (Vcr+Hcr) - y*dtdy
  650. texcoords[0] = s0;
  651. texcoords[1] = dsdx;
  652. texcoords[2] = 0;
  653. texcoords[3] = t0;
  654. texcoords[4] = 0;
  655. texcoords[5] = dtdy;
  656. texcoords[6] = 0;
  657. texcoords[7] = 0;
  658. c->rasterizer.procs.texCoordGradScale8xv(c, i, texcoords);
  659. }
  660. const uint32_t enables = c->rasterizer.state.enables;
  661. if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
  662. set_depth_and_fog(c, z);
  663. c->rasterizer.procs.activeTexture(c, c->textures.active);
  664. c->rasterizer.procs.color4xv(c, c->currentColorClamped.v);
  665. c->rasterizer.procs.disable(c, GGL_W_LERP);
  666. c->rasterizer.procs.disable(c, GGL_AA);
  667. c->rasterizer.procs.shadeModel(c, GL_FLAT);
  668. c->rasterizer.procs.recti(c,
  669. gglFixedToIntRound(x),
  670. gglFixedToIntRound(y),
  671. gglFixedToIntRound(x)+w,
  672. gglFixedToIntRound(y)+h);
  673. ogles_unlock_textures(c);
  674. }
  675. static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h,
  676. ogles_context_t* c)
  677. {
  678. // quickly reject empty rects
  679. if ((w|h) <= 0)
  680. return;
  681. drawTexxOESImp(x, y, z, w, h, c);
  682. }
  683. static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c)
  684. {
  685. // All coordinates are integer, so if we have only one
  686. // texture unit active and no scaling is required
  687. // THEN, we can use our special 1:1 mapping
  688. // which is a lot faster.
  689. if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) {
  690. const int tmu = 0;
  691. texture_unit_t& u(c->textures.tmu[tmu]);
  692. EGLTextureObject* textureObject = u.texture;
  693. const GLint Wcr = textureObject->crop_rect[2];
  694. const GLint Hcr = textureObject->crop_rect[3];
  695. if ((w == Wcr) && (h == -Hcr)) {
  696. if ((w|h) <= 0) return; // quickly reject empty rects
  697. if (u.dirty) {
  698. c->rasterizer.procs.activeTexture(c, tmu);
  699. c->rasterizer.procs.bindTexture(c, &(u.texture->surface));
  700. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  701. GGL_TEXTURE_MIN_FILTER, u.texture->min_filter);
  702. c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D,
  703. GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter);
  704. }
  705. c->rasterizer.procs.texGeni(c, GGL_S,
  706. GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
  707. c->rasterizer.procs.texGeni(c, GGL_T,
  708. GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
  709. u.dirty = 0xFF; // XXX: should be more subtle
  710. c->rasterizer.procs.activeTexture(c, c->textures.active);
  711. const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
  712. y = cbSurface.height - (y + h);
  713. const GLint Ucr = textureObject->crop_rect[0];
  714. const GLint Vcr = textureObject->crop_rect[1];
  715. const GLint s0 = Ucr - x;
  716. const GLint t0 = (Vcr + Hcr) - y;
  717. const GLuint tw = textureObject->surface.width;
  718. const GLuint th = textureObject->surface.height;
  719. if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) {
  720. // The GL spec is unclear about what should happen
  721. // in this case, so we just use the slow case, which
  722. // at least won't crash
  723. goto slow_case;
  724. }
  725. ogles_lock_textures(c);
  726. c->rasterizer.procs.texCoord2i(c, s0, t0);
  727. const uint32_t enables = c->rasterizer.state.enables;
  728. if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
  729. set_depth_and_fog(c, gglIntToFixed(z));
  730. c->rasterizer.procs.color4xv(c, c->currentColorClamped.v);
  731. c->rasterizer.procs.disable(c, GGL_W_LERP);
  732. c->rasterizer.procs.disable(c, GGL_AA);
  733. c->rasterizer.procs.shadeModel(c, GL_FLAT);
  734. c->rasterizer.procs.recti(c, x, y, x+w, y+h);
  735. ogles_unlock_textures(c);
  736. return;
  737. }
  738. }
  739. slow_case:
  740. drawTexxOESImp(
  741. gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z),
  742. gglIntToFixed(w), gglIntToFixed(h),
  743. c);
  744. }
  745. }; // namespace android
  746. // ----------------------------------------------------------------------------
  747. using namespace android;
  748. #if 0
  749. #pragma mark -
  750. #pragma mark Texture API
  751. #endif
  752. void glActiveTexture(GLenum texture)
  753. {
  754. ogles_context_t* c = ogles_context_t::get();
  755. if (uint32_t(texture-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
  756. ogles_error(c, GL_INVALID_ENUM);
  757. return;
  758. }
  759. c->textures.active = texture - GL_TEXTURE0;
  760. c->rasterizer.procs.activeTexture(c, c->textures.active);
  761. }
  762. void glBindTexture(GLenum target, GLuint texture)
  763. {
  764. ogles_context_t* c = ogles_context_t::get();
  765. if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
  766. ogles_error(c, GL_INVALID_ENUM);
  767. return;
  768. }
  769. // Bind or create a texture
  770. sp<EGLTextureObject> tex;
  771. if (texture == 0) {
  772. // 0 is our local texture object
  773. tex = c->textures.defaultTexture;
  774. } else {
  775. tex = c->surfaceManager->texture(texture);
  776. if (ggl_unlikely(tex == 0)) {
  777. tex = c->surfaceManager->createTexture(texture);
  778. if (tex == 0) {
  779. ogles_error(c, GL_OUT_OF_MEMORY);
  780. return;
  781. }
  782. }
  783. }
  784. bindTextureTmu(c, c->textures.active, texture, tex);
  785. }
  786. void glGenTextures(GLsizei n, GLuint *textures)
  787. {
  788. ogles_context_t* c = ogles_context_t::get();
  789. if (n<0) {
  790. ogles_error(c, GL_INVALID_VALUE);
  791. return;
  792. }
  793. // generate unique (shared) texture names
  794. c->surfaceManager->getToken(n, textures);
  795. }
  796. void glDeleteTextures(GLsizei n, const GLuint *textures)
  797. {
  798. ogles_context_t* c = ogles_context_t::get();
  799. if (n<0) {
  800. ogles_error(c, GL_INVALID_VALUE);
  801. return;
  802. }
  803. // If deleting a bound texture, bind this unit to 0
  804. for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) {
  805. if (c->textures.tmu[t].name == 0)
  806. continue;
  807. for (int i=0 ; i<n ; i++) {
  808. if (textures[i] && (textures[i] == c->textures.tmu[t].name)) {
  809. // bind this tmu to texture 0
  810. sp<EGLTextureObject> tex(c->textures.defaultTexture);
  811. bindTextureTmu(c, t, 0, tex);
  812. }
  813. }
  814. }
  815. c->surfaceManager->deleteTextures(n, textures);
  816. c->surfaceManager->recycleTokens(n, textures);
  817. }
  818. void glMultiTexCoord4f(
  819. GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
  820. {
  821. ogles_context_t* c = ogles_context_t::get();
  822. if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
  823. ogles_error(c, GL_INVALID_ENUM);
  824. return;
  825. }
  826. const int tmu = target-GL_TEXTURE0;
  827. c->current.texture[tmu].S = gglFloatToFixed(s);
  828. c->current.texture[tmu].T = gglFloatToFixed(t);
  829. c->current.texture[tmu].R = gglFloatToFixed(r);
  830. c->current.texture[tmu].Q = gglFloatToFixed(q);
  831. }
  832. void glMultiTexCoord4x(
  833. GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
  834. {
  835. ogles_context_t* c = ogles_context_t::get();
  836. if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) {
  837. ogles_error(c, GL_INVALID_ENUM);
  838. return;
  839. }
  840. const int tmu = target-GL_TEXTURE0;
  841. c->current.texture[tmu].S = s;
  842. c->current.texture[tmu].T = t;
  843. c->current.texture[tmu].R = r;
  844. c->current.texture[tmu].Q = q;
  845. }
  846. void glPixelStorei(GLenum pname, GLint param)
  847. {
  848. ogles_context_t* c = ogles_context_t::get();
  849. if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) {
  850. ogles_error(c, GL_INVALID_ENUM);
  851. return;
  852. }
  853. if ((param<=0 || param>8) || (param & (param-1))) {
  854. ogles_error(c, GL_INVALID_VALUE);
  855. return;
  856. }
  857. if (pname == GL_PACK_ALIGNMENT)
  858. c->textures.packAlignment = param;
  859. if (pname == GL_UNPACK_ALIGNMENT)
  860. c->textures.unpackAlignment = param;
  861. }
  862. void glTexEnvf(GLenum target, GLenum pname, GLfloat param)
  863. {
  864. ogles_context_t* c = ogles_context_t::get();
  865. c->rasterizer.procs.texEnvi(c, target, pname, GLint(param));
  866. }
  867. void glTexEnvfv(
  868. GLenum target, GLenum pname, const GLfloat *params)
  869. {
  870. ogles_context_t* c = ogles_context_t::get();
  871. if (pname == GL_TEXTURE_ENV_MODE) {
  872. c->rasterizer.procs.texEnvi(c, target, pname, GLint(*params));
  873. return;
  874. }
  875. if (pname == GL_TEXTURE_ENV_COLOR) {
  876. GGLfixed fixed[4];
  877. for (int i=0 ; i<4 ; i++)
  878. fixed[i] = gglFloatToFixed(params[i]);
  879. c->rasterizer.procs.texEnvxv(c, target, pname, fixed);
  880. return;
  881. }
  882. ogles_error(c, GL_INVALID_ENUM);
  883. }
  884. void glTexEnvx(GLenum target, GLenum pname, GLfixed param)
  885. {
  886. ogles_context_t* c = ogles_context_t::get();
  887. c->rasterizer.procs.texEnvi(c, target, pname, param);
  888. }
  889. void glTexEnvxv(
  890. GLenum target, GLenum pname, const GLfixed *params)
  891. {
  892. ogles_context_t* c = ogles_context_t::get();
  893. c->rasterizer.procs.texEnvxv(c, target, pname, params);
  894. }
  895. void glTexParameteriv(
  896. GLenum target, GLenum pname, const GLint* params)
  897. {
  898. ogles_context_t* c = ogles_context_t::get();
  899. if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
  900. ogles_error(c, GL_INVALID_ENUM);
  901. return;
  902. }
  903. EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture;
  904. switch (pname) {
  905. case GL_TEXTURE_CROP_RECT_OES:
  906. memcpy(textureObject->crop_rect, params, 4*sizeof(GLint));
  907. break;
  908. default:
  909. texParameterx(target, pname, GLfixed(params[0]), c);
  910. return;
  911. }
  912. }
  913. void glTexParameterf(
  914. GLenum target, GLenum pname, GLfloat param)
  915. {
  916. ogles_context_t* c = ogles_context_t::get();
  917. texParameterx(target, pname, GLfixed(param), c);
  918. }
  919. void glTexParameterx(
  920. GLenum target, GLenum pname, GLfixed param)
  921. {
  922. ogles_context_t* c = ogles_context_t::get();
  923. texParameterx(target, pname, param, c);
  924. }
  925. void glTexParameteri(
  926. GLenum target, GLenum pname, GLint param)
  927. {
  928. ogles_context_t* c = ogles_context_t::get();
  929. texParameterx(target, pname, GLfixed(param), c);
  930. }
  931. // ----------------------------------------------------------------------------
  932. #if 0
  933. #pragma mark -
  934. #endif
  935. void glCompressedTexImage2D(
  936. GLenum target, GLint level, GLenum internalformat,
  937. GLsizei width, GLsizei height, GLint border,
  938. GLsizei imageSize, const GLvoid *data)
  939. {
  940. ogles_context_t* c = ogles_context_t::get();
  941. if (target != GL_TEXTURE_2D) {
  942. ogles_error(c, GL_INVALID_ENUM);
  943. return;
  944. }
  945. if (width<0 || height<0 || border!=0) {
  946. ogles_error(c, GL_INVALID_VALUE);
  947. return;
  948. }
  949. // "uncompress" the texture since pixelflinger doesn't support
  950. // any compressed texture format natively.
  951. GLenum format;
  952. GLenum type;
  953. switch (internalformat) {
  954. case GL_PALETTE8_RGB8_OES:
  955. case GL_PALETTE4_RGB8_OES:
  956. format = GL_RGB;
  957. type = GL_UNSIGNED_BYTE;
  958. break;
  959. case GL_PALETTE8_RGBA8_OES:
  960. case GL_PALETTE4_RGBA8_OES:
  961. format = GL_RGBA;
  962. type = GL_UNSIGNED_BYTE;
  963. break;
  964. case GL_PALETTE8_R5_G6_B5_OES:
  965. case GL_PALETTE4_R5_G6_B5_OES:
  966. format = GL_RGB;
  967. type = GL_UNSIGNED_SHORT_5_6_5;
  968. break;
  969. case GL_PALETTE8_RGBA4_OES:
  970. case GL_PALETTE4_RGBA4_OES:
  971. format = GL_RGBA;
  972. type = GL_UNSIGNED_SHORT_4_4_4_4;
  973. break;
  974. case GL_PALETTE8_RGB5_A1_OES:
  975. case GL_PALETTE4_RGB5_A1_OES:
  976. format = GL_RGBA;
  977. type = GL_UNSIGNED_SHORT_5_5_5_1;
  978. break;
  979. #ifdef GL_OES_compressed_ETC1_RGB8_texture
  980. case GL_ETC1_RGB8_OES:
  981. format = GL_RGB;
  982. type = GL_UNSIGNED_BYTE;
  983. break;
  984. #endif
  985. default:
  986. ogles_error(c, GL_INVALID_ENUM);
  987. return;
  988. }
  989. if (!data || !width || !height) {
  990. // unclear if this is an error or not...
  991. return;
  992. }
  993. int32_t size;
  994. GGLSurface* surface;
  995. #ifdef GL_OES_compressed_ETC1_RGB8_texture
  996. if (internalformat == GL_ETC1_RGB8_OES) {
  997. GLsizei compressedSize = etc1_get_encoded_data_size(width, height);
  998. if (compressedSize > imageSize) {
  999. ogles_error(c, GL_INVALID_VALUE);
  1000. return;
  1001. }
  1002. int error = createTextureSurface(c, &surface, &size,
  1003. level, format, type, width, height);
  1004. if (error) {
  1005. ogles_error(c, error);
  1006. return;
  1007. }
  1008. if (etc1_decode_image(
  1009. (const etc1_byte*)data,
  1010. (etc1_byte*)surface->data,
  1011. width, height, 3, surface->stride*3) != 0) {
  1012. ogles_error(c, GL_INVALID_OPERATION);
  1013. }
  1014. return;
  1015. }
  1016. #endif
  1017. // all mipmap levels are specified at once.
  1018. const int numLevels = level<0 ? -level : 1;
  1019. if (dataSizePalette4(numLevels, width, height, format) > imageSize) {
  1020. ogles_error(c, GL_INVALID_VALUE);
  1021. return;
  1022. }
  1023. for (int i=0 ; i<numLevels ; i++) {
  1024. int lod_w = (width >> i) ? : 1;
  1025. int lod_h = (height >> i) ? : 1;
  1026. int error = createTextureSurface(c, &surface, &size,
  1027. i, format, type, lod_w, lod_h);
  1028. if (error) {
  1029. ogles_error(c, error);
  1030. return;
  1031. }
  1032. decodePalette4(data, i, width, height,
  1033. surface->data, surface->stride, internalformat);
  1034. }
  1035. }
  1036. void glTexImage2D(
  1037. GLenum target, GLint level, GLint internalformat,
  1038. GLsizei width, GLsizei height, GLint border,
  1039. GLenum format, GLenum type, const GLvoid *pixels)
  1040. {
  1041. ogles_context_t* c = ogles_context_t::get();
  1042. if (target != GL_TEXTURE_2D) {
  1043. ogles_error(c, GL_INVALID_ENUM);
  1044. return;
  1045. }
  1046. if (width<0 || height<0 || border!=0 || level < 0) {
  1047. ogles_error(c, GL_INVALID_VALUE);
  1048. return;
  1049. }
  1050. if (format != (GLenum)internalformat) {
  1051. ogles_error(c, GL_INVALID_OPERATION);
  1052. return;
  1053. }
  1054. if (validFormatType(c, format, type)) {
  1055. return;
  1056. }
  1057. int32_t size = 0;
  1058. GGLSurface* surface = 0;
  1059. int error = createTextureSurface(c, &surface, &size,
  1060. level, format, type, width, height);
  1061. if (error) {
  1062. ogles_error(c, error);
  1063. return;
  1064. }
  1065. if (pixels) {
  1066. const int32_t formatIdx = convertGLPixelFormat(format, type);
  1067. const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
  1068. const int32_t align = c->textures.unpackAlignment-1;
  1069. const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
  1070. const size_t size = bpr * height;
  1071. const int32_t stride = bpr / pixelFormat.size;
  1072. GGLSurface userSurface;
  1073. userSurface.version = sizeof(userSurface);
  1074. userSurface.width = width;
  1075. userSurface.height = height;
  1076. userSurface.stride = stride;
  1077. userSurface.format = formatIdx;
  1078. userSurface.compressedFormat = 0;
  1079. userSurface.data = (GLubyte*)pixels;
  1080. int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height);
  1081. if (err) {
  1082. ogles_error(c, err);
  1083. return;
  1084. }
  1085. generateMipmap(c, level);
  1086. }
  1087. }
  1088. // ----------------------------------------------------------------------------
  1089. void glCompressedTexSubImage2D(
  1090. GLenum /*target*/, GLint /*level*/, GLint /*xoffset*/,
  1091. GLint /*yoffset*/, GLsizei /*width*/, GLsizei /*height*/,
  1092. GLenum /*format*/, GLsizei /*imageSize*/,
  1093. const GLvoid* /*data*/)
  1094. {
  1095. ogles_context_t* c = ogles_context_t::get();
  1096. ogles_error(c, GL_INVALID_ENUM);
  1097. }
  1098. void glTexSubImage2D(
  1099. GLenum target, GLint level, GLint xoffset,
  1100. GLint yoffset, GLsizei width, GLsizei height,
  1101. GLenum format, GLenum type, const GLvoid *pixels)
  1102. {
  1103. ogles_context_t* c = ogles_context_t::get();
  1104. if (target != GL_TEXTURE_2D) {
  1105. ogles_error(c, GL_INVALID_ENUM);
  1106. return;
  1107. }
  1108. if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) {
  1109. ogles_error(c, GL_INVALID_VALUE);
  1110. return;
  1111. }
  1112. if (validFormatType(c, format, type)) {
  1113. return;
  1114. }
  1115. // find out which texture is bound to the current unit
  1116. const int active = c->textures.active;
  1117. EGLTextureObject* tex = c->textures.tmu[active].texture;
  1118. const GGLSurface& surface(tex->mip(level));
  1119. if (!tex->internalformat || tex->direct) {
  1120. ogles_error(c, GL_INVALID_OPERATION);
  1121. return;
  1122. }
  1123. if (format != tex->internalformat) {
  1124. ogles_error(c, GL_INVALID_OPERATION);
  1125. return;
  1126. }
  1127. if ((xoffset + width > GLsizei(surface.width)) ||
  1128. (yoffset + height > GLsizei(surface.height))) {
  1129. ogles_error(c, GL_INVALID_VALUE);
  1130. return;
  1131. }
  1132. if (!width || !height) {
  1133. return; // okay, but no-op.
  1134. }
  1135. // figure out the size we need as well as the stride
  1136. const int32_t formatIdx = convertGLPixelFormat(format, type);
  1137. if (formatIdx == 0) { // we don't know what to do with this
  1138. ogles_error(c, GL_INVALID_OPERATION);
  1139. return;
  1140. }
  1141. const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
  1142. const int32_t align = c->textures.unpackAlignment-1;
  1143. const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
  1144. const size_t size = bpr * height;
  1145. const int32_t stride = bpr / pixelFormat.size;
  1146. GGLSurface userSurface;
  1147. userSurface.version = sizeof(userSurface);
  1148. userSurface.width = width;
  1149. userSurface.height = height;
  1150. userSurface.stride = stride;
  1151. userSurface.format = formatIdx;
  1152. userSurface.compressedFormat = 0;
  1153. userSurface.data = (GLubyte*)pixels;
  1154. int err = copyPixels(c,
  1155. surface, xoffset, yoffset,
  1156. userSurface, 0, 0, width, height);
  1157. if (err) {
  1158. ogles_error(c, err);
  1159. return;
  1160. }
  1161. generateMipmap(c, level);
  1162. // since we only changed the content of the texture, we don't need
  1163. // to call bindTexture on the main rasterizer.
  1164. }
  1165. // ----------------------------------------------------------------------------
  1166. void glCopyTexImage2D(
  1167. GLenum target, GLint level, GLenum internalformat,
  1168. GLint x, GLint y, GLsizei width, GLsizei height,
  1169. GLint border)
  1170. {
  1171. ogles_context_t* c = ogles_context_t::get();
  1172. if (target != GL_TEXTURE_2D) {
  1173. ogles_error(c, GL_INVALID_ENUM);
  1174. return;
  1175. }
  1176. if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) {
  1177. ogles_error(c, GL_INVALID_ENUM);
  1178. return;
  1179. }
  1180. if (width<0 || height<0 || border!=0 || level<0) {
  1181. ogles_error(c, GL_INVALID_VALUE);
  1182. return;
  1183. }
  1184. GLenum format = 0;
  1185. GLenum type = GL_UNSIGNED_BYTE;
  1186. const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
  1187. const int cbFormatIdx = cbSurface.format;
  1188. switch (cbFormatIdx) {
  1189. case GGL_PIXEL_FORMAT_RGB_565:
  1190. type = GL_UNSIGNED_SHORT_5_6_5;
  1191. break;
  1192. case GGL_PIXEL_FORMAT_RGBA_5551:
  1193. type = GL_UNSIGNED_SHORT_5_5_5_1;
  1194. break;
  1195. case GGL_PIXEL_FORMAT_RGBA_4444:
  1196. type = GL_UNSIGNED_SHORT_4_4_4_4;
  1197. break;
  1198. }
  1199. switch (internalformat) {
  1200. case GL_ALPHA:
  1201. case GL_LUMINANCE_ALPHA:
  1202. case GL_LUMINANCE:
  1203. type = GL_UNSIGNED_BYTE;
  1204. break;
  1205. }
  1206. // figure out the format to use for the new texture
  1207. switch (cbFormatIdx) {
  1208. case GGL_PIXEL_FORMAT_RGBA_8888:
  1209. case GGL_PIXEL_FORMAT_A_8:
  1210. case GGL_PIXEL_FORMAT_RGBA_5551:
  1211. case GGL_PIXEL_FORMAT_RGBA_4444:
  1212. format = internalformat;
  1213. break;
  1214. case GGL_PIXEL_FORMAT_RGBX_8888:
  1215. case GGL_PIXEL_FORMAT_RGB_888:
  1216. case GGL_PIXEL_FORMAT_RGB_565:
  1217. case GGL_PIXEL_FORMAT_L_8:
  1218. switch (internalformat) {
  1219. case GL_LUMINANCE:
  1220. case GL_RGB:
  1221. format = internalformat;
  1222. break;
  1223. }
  1224. break;
  1225. }
  1226. if (format == 0) {
  1227. // invalid combination
  1228. ogles_error(c, GL_INVALID_ENUM);
  1229. return;
  1230. }
  1231. // create the new texture...
  1232. int32_t size;
  1233. GGLSurface* surface;
  1234. int error = createTextureSurface(c, &surface, &size,
  1235. level, format, type, width, height);
  1236. if (error) {
  1237. ogles_error(c, error);
  1238. return;
  1239. }
  1240. // The bottom row is stored first in textures
  1241. GGLSurface txSurface(*surface);
  1242. txSurface.stride = -txSurface.stride;
  1243. // (x,y) is the lower-left corner of colorBuffer
  1244. y = cbSurface.height - (y + height);
  1245. /* The GLES spec says:
  1246. * If any of the pixels within the specified rectangle are outside
  1247. * the framebuffer associated with the current rendering context,
  1248. * then the values obtained for those pixels are undefined.
  1249. */
  1250. if (x+width > GLint(cbSurface.width))
  1251. width = cbSurface.width - x;
  1252. if (y+height > GLint(cbSurface.height))
  1253. height = cbSurface.height - y;
  1254. int err = copyPixels(c,
  1255. txSurface, 0, 0,
  1256. cbSurface, x, y, width, height);
  1257. if (err) {
  1258. ogles_error(c, err);
  1259. }
  1260. generateMipmap(c, level);
  1261. }
  1262. void glCopyTexSubImage2D(
  1263. GLenum target, GLint level, GLint xoffset, GLint yoffset,
  1264. GLint x, GLint y, GLsizei width, GLsizei height)
  1265. {
  1266. ogles_context_t* c = ogles_context_t::get();
  1267. if (target != GL_TEXTURE_2D) {
  1268. ogles_error(c, GL_INVALID_ENUM);
  1269. return;
  1270. }
  1271. if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) {
  1272. ogles_error(c, GL_INVALID_VALUE);
  1273. return;
  1274. }
  1275. if (!width || !height) {
  1276. return; // okay, but no-op.
  1277. }
  1278. // find out which texture is bound to the current unit
  1279. const int active = c->textures.active;
  1280. EGLTextureObject* tex = c->textures.tmu[active].texture;
  1281. const GGLSurface& surface(tex->mip(level));
  1282. if (!tex->internalformat) {
  1283. ogles_error(c, GL_INVALID_OPERATION);
  1284. return;
  1285. }
  1286. if ((xoffset + width > GLsizei(surface.width)) ||
  1287. (yoffset + height > GLsizei(surface.height))) {
  1288. ogles_error(c, GL_INVALID_VALUE);
  1289. return;
  1290. }
  1291. // The bottom row is stored first in textures
  1292. GGLSurface txSurface(surface);
  1293. txSurface.stride = -txSurface.stride;
  1294. // (x,y) is the lower-left corner of colorBuffer
  1295. const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
  1296. y = cbSurface.height - (y + height);
  1297. /* The GLES spec says:
  1298. * If any of the pixels within the specified rectangle are outside
  1299. * the framebuffer associated with the current rendering context,
  1300. * then the values obtained for those pixels are undefined.
  1301. */
  1302. if (x+width > GLint(cbSurface.width))
  1303. width = cbSurface.width - x;
  1304. if (y+height > GLint(cbSurface.height))
  1305. height = cbSurface.height - y;
  1306. int err = copyPixels(c,
  1307. txSurface, xoffset, yoffset,
  1308. cbSurface, x, y, width, height);
  1309. if (err) {
  1310. ogles_error(c, err);
  1311. return;
  1312. }
  1313. generateMipmap(c, level);
  1314. }
  1315. void glReadPixels(
  1316. GLint x, GLint y, GLsizei width, GLsizei height,
  1317. GLenum format, GLenum type, GLvoid *pixels)
  1318. {
  1319. ogles_context_t* c = ogles_context_t::get();
  1320. if ((format != GL_RGBA) && (format != GL_RGB)) {
  1321. ogles_error(c, GL_INVALID_ENUM);
  1322. return;
  1323. }
  1324. if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) {
  1325. ogles_error(c, GL_INVALID_ENUM);
  1326. return;
  1327. }
  1328. if (width<0 || height<0) {
  1329. ogles_error(c, GL_INVALID_VALUE);
  1330. return;
  1331. }
  1332. if (x<0 || y<0) {
  1333. ogles_error(c, GL_INVALID_VALUE);
  1334. return;
  1335. }
  1336. int32_t formatIdx = GGL_PIXEL_FORMAT_NONE;
  1337. if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) {
  1338. formatIdx = GGL_PIXEL_FORMAT_RGBA_8888;
  1339. } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) {
  1340. formatIdx = GGL_PIXEL_FORMAT_RGB_565;
  1341. } else {
  1342. ogles_error(c, GL_INVALID_OPERATION);
  1343. return;
  1344. }
  1345. const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s;
  1346. if ((x+width > GLint(readSurface.width)) ||
  1347. (y+height > GLint(readSurface.height))) {
  1348. ogles_error(c, GL_INVALID_VALUE);
  1349. return;
  1350. }
  1351. const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]);
  1352. const int32_t align = c->textures.packAlignment-1;
  1353. const int32_t bpr = ((width * pixelFormat.size) + align) & ~align;
  1354. const int32_t stride = bpr / pixelFormat.size;
  1355. GGLSurface userSurface;
  1356. userSurface.version = sizeof(userSurface);
  1357. userSurface.width = width;
  1358. userSurface.height = height;
  1359. userSurface.stride = -stride; // bottom row is transfered first
  1360. userSurface.format = formatIdx;
  1361. userSurface.compressedFormat = 0;
  1362. userSurface.data = (GLubyte*)pixels;
  1363. // use pixel-flinger to handle all the conversions
  1364. GGLContext* ggl = getRasterizer(c);
  1365. if (!ggl) {
  1366. // the only reason this would fail is because we ran out of memory
  1367. ogles_error(c, GL_OUT_OF_MEMORY);
  1368. return;
  1369. }
  1370. ggl->colorBuffer(ggl, &userSurface); // destination is user buffer
  1371. ggl->bindTexture(ggl, &readSurface); // source is read-buffer
  1372. ggl->texCoord2i(ggl, x, readSurface.height - (y + height));
  1373. ggl->recti(ggl, 0, 0, width, height);
  1374. }
  1375. // ----------------------------------------------------------------------------
  1376. #if 0
  1377. #pragma mark -
  1378. #pragma mark DrawTexture Extension
  1379. #endif
  1380. void glDrawTexsvOES(const GLshort* coords) {
  1381. ogles_context_t* c = ogles_context_t::get();
  1382. drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
  1383. }
  1384. void glDrawTexivOES(const GLint* coords) {
  1385. ogles_context_t* c = ogles_context_t::get();
  1386. drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
  1387. }
  1388. void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) {
  1389. ogles_context_t* c = ogles_context_t::get();
  1390. drawTexiOES(x, y, z, w, h, c);
  1391. }
  1392. void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) {
  1393. ogles_context_t* c = ogles_context_t::get();
  1394. drawTexiOES(x, y, z, w, h, c);
  1395. }
  1396. void glDrawTexfvOES(const GLfloat* coords) {
  1397. ogles_context_t* c = ogles_context_t::get();
  1398. drawTexxOES(
  1399. gglFloatToFixed(coords[0]),
  1400. gglFloatToFixed(coords[1]),
  1401. gglFloatToFixed(coords[2]),
  1402. gglFloatToFixed(coords[3]),
  1403. gglFloatToFixed(coords[4]),
  1404. c);
  1405. }
  1406. void glDrawTexxvOES(const GLfixed* coords) {
  1407. ogles_context_t* c = ogles_context_t::get();
  1408. drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c);
  1409. }
  1410. void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){
  1411. ogles_context_t* c = ogles_context_t::get();
  1412. drawTexxOES(
  1413. gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z),
  1414. gglFloatToFixed(w), gglFloatToFixed(h),
  1415. c);
  1416. }
  1417. void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) {
  1418. ogles_context_t* c = ogles_context_t::get();
  1419. drawTexxOES(x, y, z, w, h, c);
  1420. }
  1421. // ----------------------------------------------------------------------------
  1422. #if 0
  1423. #pragma mark -
  1424. #pragma mark EGL Image Extension
  1425. #endif
  1426. void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
  1427. {
  1428. ogles_context_t* c = ogles_context_t::get();
  1429. if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) {
  1430. ogles_error(c, GL_INVALID_ENUM);
  1431. return;
  1432. }
  1433. if (image == EGL_NO_IMAGE_KHR) {
  1434. ogles_error(c, GL_INVALID_VALUE);
  1435. return;
  1436. }
  1437. ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image;
  1438. if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
  1439. ogles_error(c, GL_INVALID_VALUE);
  1440. return;
  1441. }
  1442. if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) {
  1443. ogles_error(c, GL_INVALID_VALUE);
  1444. return;
  1445. }
  1446. // bind it to the texture unit
  1447. sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c);
  1448. tex->setImage(native_buffer);
  1449. }
  1450. void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
  1451. {
  1452. ogles_context_t* c = ogles_context_t::get();
  1453. if (target != GL_RENDERBUFFER_OES) {
  1454. ogles_error(c, GL_INVALID_ENUM);
  1455. return;
  1456. }
  1457. if (image == EGL_NO_IMAGE_KHR) {
  1458. ogles_error(c, GL_INVALID_VALUE);
  1459. return;
  1460. }
  1461. ANativeWindowBuffer* native_buffer = (ANativeWindowBuffer*)image;
  1462. if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
  1463. ogles_error(c, GL_INVALID_VALUE);
  1464. return;
  1465. }
  1466. if (native_buffer->common.version != sizeof(ANativeWindowBuffer)) {
  1467. ogles_error(c, GL_INVALID_VALUE);
  1468. return;
  1469. }
  1470. // well, we're not supporting this extension anyways
  1471. }