texture.cpp 51 KB

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