PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/CS/migrated/branches/R0_92/plugins/video/renderer/opengl/ogl_txtmgr.cpp

#
C++ | 737 lines | 606 code | 72 blank | 59 comment | 120 complexity | 138dada001806027204a59da74d619ea MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1998 by Jorrit Tyberghein
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public
  12. License along with this library; if not, write to the Free
  13. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <stdarg.h>
  16. #include <math.h>
  17. #include "cssysdef.h"
  18. #include "ogl_g3dcom.h"
  19. #include "ogl_txtmgr.h"
  20. #include "ogl_txtcache.h"
  21. #include "ogl_proctexback.h"
  22. #include "ogl_proctexsoft.h"
  23. #include "csutil/scanstr.h"
  24. #include "csutil/debug.h"
  25. #include "iutil/cfgfile.h"
  26. #include "igraphic/image.h"
  27. //---------------------------------------------------------------------------
  28. csTextureOpenGL::csTextureOpenGL (csTextureHandle *Parent, iImage *Image)
  29. : csTexture (Parent)
  30. {
  31. DG_TYPE (this, "csTextureOpenGL");
  32. image_data = NULL;
  33. w = Image->GetWidth ();
  34. h = Image->GetHeight ();
  35. compute_masks ();
  36. size = 0;
  37. compressed = GL_FALSE;
  38. }
  39. csTextureOpenGL::~csTextureOpenGL ()
  40. {
  41. delete [] image_data;
  42. }
  43. csTextureProcOpenGL::~csTextureProcOpenGL ()
  44. {
  45. if (texG3D) texG3D->DecRef ();
  46. }
  47. csTextureProcOpenGL::csTextureProcOpenGL (csTextureHandle *Parent,
  48. iImage *image) : csTextureOpenGL (Parent, image), texG3D (NULL)
  49. {
  50. DG_TYPE (this, "csTextureProcOpenGL");
  51. }
  52. //---------------------------------------------------------------------------
  53. // make sure the lenient versions are listed ahead of specific ones
  54. CS_GL_FORMAT_TABLE (csTextureManagerOpenGL::glformats)
  55. CS_GL_FORMAT (GL_RGBA, GL_RGBA, 4, 0)
  56. CS_GL_FORMAT (GL_RGBA8,GL_RGBA, 4, 4)
  57. CS_GL_FORMAT (GL_RGB5_A1, GL_RGBA, 4, 2)
  58. CS_GL_FORMAT (GL_RGB10_A2, GL_RGBA, 4, 4)
  59. CS_GL_FORMAT (GL_RGBA16,GL_RGBA, 4, 8)
  60. CS_GL_FORMAT (GL_RGB, GL_RGB, 3, 0)
  61. CS_GL_FORMAT (GL_RGB8, GL_RGB, 3, 3)
  62. CS_GL_FORMAT (GL_RGB10, GL_RGB, 3, 4)
  63. CS_GL_FORMAT (GL_RGB16, GL_RGB, 3, 6)
  64. CS_GL_FORMAT (GL_RGB4, GL_RGB, 3, 2)
  65. CS_GL_FORMAT (GL_RGB5, GL_RGB, 3, 2)
  66. CS_GL_FORMAT (GL_R3_G3_B2, GL_RGB, 3, 1)
  67. CS_GL_FORMAT (GL_RGBA2, GL_RGBA, 4, 1)
  68. CS_GL_FORMAT (GL_ALPHA, GL_ALPHA, 1, 1)
  69. CS_GL_FORMAT (GL_ALPHA4, GL_ALPHA, 1, 1)
  70. CS_GL_FORMAT (GL_ALPHA8, GL_ALPHA, 1, 1)
  71. CS_GL_FORMAT (GL_ALPHA12, GL_ALPHA, 1, 2)
  72. CS_GL_FORMAT (GL_ALPHA16, GL_ALPHA, 1, 2)
  73. CS_GL_FORMAT (GL_BLUE, GL_BLUE, 1, 1)
  74. CS_GL_FORMAT (GL_GREEN, GL_GREEN, 1, 1)
  75. CS_GL_FORMAT (GL_RED, GL_RED, 1, 1)
  76. CS_GL_FORMAT (GL_INTENSITY, GL_INTENSITY, 1, 1)
  77. CS_GL_FORMAT (GL_INTENSITY4, GL_INTENSITY, 1, 1)
  78. CS_GL_FORMAT (GL_INTENSITY8, GL_INTENSITY, 1, 1)
  79. CS_GL_FORMAT (GL_INTENSITY12, GL_INTENSITY, 1, 2)
  80. CS_GL_FORMAT (GL_INTENSITY16, GL_INTENSITY, 1, 2)
  81. CS_GL_FORMAT (GL_LUMINANCE, GL_LUMINANCE, 1, 1)
  82. CS_GL_FORMAT (GL_LUMINANCE4, GL_LUMINANCE, 1, 1)
  83. CS_GL_FORMAT (GL_LUMINANCE8, GL_LUMINANCE, 1, 1)
  84. CS_GL_FORMAT (GL_LUMINANCE12, GL_LUMINANCE, 1, 2)
  85. CS_GL_FORMAT (GL_LUMINANCE16, GL_LUMINANCE, 1, 2)
  86. CS_GL_FORMAT (GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 2, 2)
  87. CS_GL_FORMAT (GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 2, 1)
  88. CS_GL_FORMAT (GL_LUMINANCE6_ALPHA2, GL_LUMINANCE_ALPHA, 2, 1)
  89. CS_GL_FORMAT (GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 2, 2)
  90. CS_GL_FORMAT (GL_LUMINANCE12_ALPHA4, GL_LUMINANCE_ALPHA, 2, 2)
  91. CS_GL_FORMAT (GL_LUMINANCE12_ALPHA12, GL_LUMINANCE_ALPHA, 2, 3)
  92. CS_GL_FORMAT (GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 2, 4)
  93. CS_GL_FORMAT_TABLE_END
  94. bool csTextureHandleOpenGL::FindFormatType ()
  95. {
  96. int i;
  97. for (i=0; csTextureManagerOpenGL::glformats[i].sourceFormat != sourceFormat
  98. && csTextureManagerOpenGL::glformats[i].components; i++);
  99. if (csTextureManagerOpenGL::glformats[i].sourceFormat != sourceFormat)
  100. {
  101. printf ("unknown source format \n");
  102. return false;
  103. }
  104. formatidx = i;
  105. // do we force it to some specific targetFormat ?
  106. if (csTextureManagerOpenGL::glformats[i].forcedFormat != 0)
  107. {
  108. targetFormat = csTextureManagerOpenGL::glformats[i].forcedFormat;
  109. for (i=0; csTextureManagerOpenGL::glformats[i].targetFormat != targetFormat
  110. && csTextureManagerOpenGL::glformats[i].components; i++);
  111. if (csTextureManagerOpenGL::glformats[i].targetFormat != targetFormat)
  112. formatidx = i;
  113. }
  114. sourceType = GL_UNSIGNED_BYTE;
  115. targetFormat = csTextureManagerOpenGL::glformats[formatidx].targetFormat;
  116. if (csTextureManagerOpenGL::glformats[formatidx].sourceFormat == GL_RGB
  117. || csTextureManagerOpenGL::glformats[formatidx].sourceFormat == GL_RGBA)
  118. {
  119. static GLenum formats [13][4] = {
  120. {GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_BYTE },
  121. {GL_RGBA8, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_BYTE },
  122. {GL_RGB5_A1, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_BYTE },
  123. {GL_RGB10_A2, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_BYTE },
  124. {GL_RGBA16, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_BYTE },
  125. {GL_RGB, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_BYTE },
  126. {GL_RGB8, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_BYTE },
  127. {GL_RGB10, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_BYTE },
  128. {GL_RGB16, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_BYTE },
  129. {GL_RGB4, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5 },
  130. {GL_RGB5, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5 },
  131. {GL_R3_G3_B2, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_3_3_2 },
  132. {GL_RGBA2, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4}
  133. };
  134. if (sourceFormat == GL_RGBA)
  135. {
  136. if (!transp)
  137. {
  138. if (!(image->GetFormat () & CS_IMGFMT_ALPHA))
  139. {
  140. sourceFormat = GL_RGB;
  141. // Again determine the formatidx and possible change it if we
  142. // have a forced targetformat
  143. for (i=0; csTextureManagerOpenGL::glformats[i].sourceFormat
  144. != sourceFormat; i++);
  145. formatidx = i;
  146. if (csTextureManagerOpenGL::glformats[i].forcedFormat != 0)
  147. {
  148. targetFormat = csTextureManagerOpenGL::glformats[i].forcedFormat;
  149. for (i=0; csTextureManagerOpenGL::glformats[i].targetFormat
  150. != targetFormat; i++);
  151. if (csTextureManagerOpenGL::glformats[i].targetFormat
  152. != targetFormat)
  153. formatidx = i;
  154. }
  155. targetFormat = csTextureManagerOpenGL::glformats[formatidx]
  156. .targetFormat;
  157. }
  158. else
  159. {
  160. // With a histogram we now could determine how many alpha values
  161. // we have here to possibly select a better targetFormat but due
  162. // to laziness we leave it as is.
  163. }
  164. }
  165. else
  166. {
  167. targetFormat = (bpp == 8 ? GL_RGBA : bpp < 32 ? GL_RGB5_A1 : GL_RGBA8);
  168. for (i=0; csTextureManagerOpenGL::glformats[i].targetFormat
  169. != targetFormat; i++);
  170. formatidx = i;
  171. int pixels = image->GetWidth () * image->GetHeight ();
  172. csRGBpixel *_src = (csRGBpixel *)image->GetImageData ();
  173. while (pixels--)
  174. {
  175. // By default, every csRGBpixel initializes its alpha component to
  176. // 255. Thus, we should just drop to zero alpha for transparent
  177. // pixels, if any.
  178. if (transp_color.eq (*_src))
  179. _src->alpha = 0;
  180. _src++;
  181. }
  182. }
  183. }
  184. int d;
  185. for (i=0; i < 12; i++)
  186. {
  187. if (targetFormat == formats[i][0])
  188. break;
  189. }
  190. d = (bpp == 32 ? 24 : bpp) >> 3;
  191. sourceType = formats[i][d];
  192. }
  193. return true;
  194. }
  195. bool csTextureHandleOpenGL::transform (iImage *Image, csTextureOpenGL *tex)
  196. {
  197. uint8 *h;
  198. uint8 *&image_data = tex->get_image_data ();
  199. csRGBpixel *data = (csRGBpixel *)Image->GetImageData ();
  200. int n = Image->GetWidth ()*Image->GetHeight ();;
  201. int i=0;
  202. int nCompo;
  203. // First we determine the exact sourceformat if targetformat is given
  204. // without bit specifications.
  205. switch (csTextureManagerOpenGL::glformats[formatidx].sourceFormat)
  206. {
  207. case GL_ALPHA: i++; // Fall thru
  208. case GL_BLUE: i++; // Fall thru
  209. case GL_GREEN: i++; // Fall thru
  210. case GL_RED:
  211. image_data = new uint8 [n];
  212. h = (uint8*)data;
  213. h += i;
  214. for (i=0; i<n; i++, h += 4)
  215. *image_data++ = *h;
  216. break;
  217. case GL_INTENSITY:
  218. image_data = new uint8 [n];
  219. for (i=0; i<n; i++, data++)
  220. *image_data++ = data->Intensity ();
  221. break;
  222. case GL_LUMINANCE:
  223. image_data = new uint8 [n];
  224. for (i=0; i<n; i++, data++)
  225. *image_data++ = data->Luminance ();
  226. break;
  227. case GL_LUMINANCE_ALPHA:
  228. image_data = new uint8 [n*2];
  229. for (i=0; i<n; i++, data++)
  230. {
  231. *image_data++ = data->Luminance ();
  232. *image_data++ = data->alpha;
  233. }
  234. break;
  235. default: // RGB/RGBA branch
  236. switch (sourceType)
  237. {
  238. case GL_UNSIGNED_BYTE:
  239. nCompo = csTextureManagerOpenGL::glformats[formatidx].components;
  240. h = image_data = new uint8 [n*nCompo];
  241. for (i=0; i<n; i++, data++, h+=nCompo)
  242. memcpy (h, data, nCompo);
  243. break;
  244. case GL_UNSIGNED_BYTE_3_3_2:
  245. h = image_data = new uint8 [n];
  246. for (i=0; i<n; i++, data++)
  247. *h++ = (data->red & 0xe0) | (data->green & 0xe0)>>5
  248. | (data->blue >> 6);
  249. break;
  250. case GL_UNSIGNED_SHORT_4_4_4_4:
  251. {
  252. image_data = new uint8 [n*2];
  253. unsigned short *ush = (unsigned short *)image_data;
  254. for (i=0; i<n; i++, data++)
  255. *ush++ = ((unsigned short)(data->red & 0xf0))<<8
  256. | ((unsigned short)(data->green & 0xf0))<<4
  257. | (unsigned short)(data->blue & 0xf0)
  258. | (unsigned short)(data->alpha >> 4) ;
  259. }
  260. break;
  261. case GL_UNSIGNED_SHORT_5_5_5_1:
  262. {
  263. image_data = new uint8 [n*2];
  264. unsigned short *ush = (unsigned short *)image_data;
  265. for (i=0; i<n; i++, data++)
  266. *ush++ = ((unsigned short)(data->red & 0xf8))<<8
  267. | ((unsigned short)(data->green & 0xf8))<<3
  268. | ((unsigned short)(data->blue & 0xf8))>>2
  269. | (unsigned short)(data->alpha >> 7) ;
  270. }
  271. break;
  272. case GL_UNSIGNED_SHORT_5_6_5:
  273. {
  274. image_data = new uint8 [n*2];
  275. unsigned short *ush = (unsigned short *)image_data;
  276. for (i=0; i<n; i++, data++)
  277. *ush++ = ((unsigned short)(data->red & 0xf8))<<8
  278. | ((unsigned short)(data->green & 0xfc))<<3
  279. | (unsigned short)(data->blue >> 3);
  280. }
  281. break;
  282. default:
  283. printf ("OpenGL Warning: no sourceType %x\n",
  284. (unsigned int)sourceType);
  285. }
  286. }
  287. if (csTextureManagerOpenGL::glformats[formatidx].compressedFormat != 0
  288. && tex->Compressable ())
  289. {
  290. GLuint t;
  291. glGenTextures (1, &t);
  292. glBindTexture (GL_TEXTURE_2D, t);
  293. glTexImage2D (GL_TEXTURE_2D, 0,
  294. csTextureManagerOpenGL::glformats[formatidx].compressedFormat,
  295. Image->GetWidth (), Image->GetHeight (), 0,
  296. csTextureManagerOpenGL::glformats[formatidx].sourceFormat,
  297. sourceType, image_data);
  298. glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB,
  299. &tex->compressed);
  300. /* if the compression has been successful */
  301. if (tex->compressed == GL_TRUE)
  302. {
  303. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
  304. &tex->internalFormat);
  305. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
  306. GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &tex->size);
  307. delete [] image_data;
  308. image_data = new uint8 [tex->size];
  309. csGraphics3DOGLCommon::glGetCompressedTexImageARB (GL_TEXTURE_2D, 0,
  310. image_data);
  311. }
  312. glDeleteTextures (1, &t);
  313. }
  314. else
  315. tex->size = n * csTextureManagerOpenGL::glformats[formatidx].texelbytes;
  316. size += tex->size;
  317. return true;
  318. }
  319. csTextureHandleOpenGL::csTextureHandleOpenGL (
  320. iImage *image, int flags, GLenum sourceFormat, int bpp,
  321. csGraphics3DOGLCommon *iG3D) : csTextureHandle (image, flags)
  322. {
  323. (G3D = iG3D)->IncRef ();
  324. (txtmgr = G3D->txtmgr)->IncRef ();
  325. has_alpha = false;
  326. this->sourceFormat = sourceFormat;
  327. this->bpp = bpp;
  328. size = 0;
  329. DG_TYPE (this, "csTextureHandleOpenGL");
  330. }
  331. csTextureHandleOpenGL::~csTextureHandleOpenGL ()
  332. {
  333. if (G3D->texture_cache)
  334. G3D->texture_cache->Uncache (this);
  335. txtmgr->UnregisterTexture (this);
  336. txtmgr->DecRef();
  337. G3D->DecRef ();
  338. int i;
  339. for (i = vTex.Length ()-1; i >= 0; i--)
  340. {
  341. if (vTex [i])
  342. {
  343. DG_UNLINK (this, vTex[i]);
  344. delete vTex [i];
  345. }
  346. }
  347. vTex.DeleteAll ();
  348. }
  349. void csTextureHandleOpenGL::Clear ()
  350. {
  351. if ((flags & CS_TEXTURE_PROC) == CS_TEXTURE_PROC && vTex.Length ())
  352. {
  353. SCF_DEC_REF (((csTextureProcOpenGL*)vTex[0])->texG3D);
  354. ((csTextureProcOpenGL*)vTex[0])->texG3D = NULL;
  355. }
  356. }
  357. csTexture *csTextureHandleOpenGL::NewTexture (iImage *Image)
  358. {
  359. if ((flags & CS_TEXTURE_PROC) == CS_TEXTURE_PROC)
  360. return new csTextureProcOpenGL (this, Image);
  361. else
  362. return new csTextureOpenGL (this, Image);
  363. }
  364. void csTextureHandleOpenGL::ShowFormat ()
  365. {
  366. printf ("TargetFormat: %s, size: %ld\n",
  367. csTextureManagerOpenGL::glformats[formatidx].name, size);
  368. }
  369. void csTextureHandleOpenGL::InitTexture (csTextureManagerOpenGL *texman,
  370. csPixelFormat *pfmt)
  371. {
  372. // Preserve original width/height so that in DrawPixmap subregions of
  373. // textures are calculated correctly. In other words, the app writer need
  374. // not know about opengl texture size adjustments. smgh
  375. if (!image) return;
  376. if (((flags & CS_TEXTURE_PROC) == CS_TEXTURE_PROC) && vTex.Length ())
  377. return;
  378. orig_width = image->GetWidth ();
  379. orig_height = image->GetHeight ();
  380. // If necessary rescale if bigger than maximum texture size
  381. if ((orig_width > texman->max_tex_size) ||
  382. (orig_height > texman->max_tex_size))
  383. {
  384. int nwidth = orig_width;
  385. int nheight = orig_height;
  386. if (orig_width > texman->max_tex_size) nwidth = texman->max_tex_size;
  387. if (orig_height > texman->max_tex_size) nheight = texman->max_tex_size;
  388. image->Rescale (nwidth, nheight);
  389. }
  390. // In opengl all textures, even non-mipmapped textures are required
  391. // to be powers of 2.
  392. AdjustSizePo2 ();
  393. // Determine the format and type of the source we gonna tranform the data to
  394. FindFormatType ();
  395. CreateMipmaps ();
  396. // printf ("proctex creation\n");
  397. if ((flags & CS_TEXTURE_PROC) == CS_TEXTURE_PROC)
  398. {
  399. bool alone_hint = (flags & CS_TEXTURE_PROC_ALONE_HINT) ==
  400. CS_TEXTURE_PROC_ALONE_HINT;
  401. switch (texman->proc_tex_type)
  402. {
  403. case BACK_BUFFER_TEXTURE:
  404. {
  405. csOpenGLProcBackBuffer *bbtexG3D = new csOpenGLProcBackBuffer(NULL);
  406. bool persistent = (flags & CS_TEXTURE_PROC_PERSISTENT) ==
  407. CS_TEXTURE_PROC_PERSISTENT;
  408. // already shares the texture cache/manager
  409. bbtexG3D->Prepare (texman->G3D, this, pfmt, persistent);
  410. ((csTextureProcOpenGL*)vTex[0])->texG3D = (iGraphics3D*) bbtexG3D;
  411. break;
  412. }
  413. case SOFTWARE_TEXTURE:
  414. {
  415. // This is always in 32bit no matter what the pfmt.
  416. csOpenGLProcSoftware *stexG3D = new csOpenGLProcSoftware (NULL);
  417. if (stexG3D->Prepare (texman->G3D, texman->head_soft_proc_tex,
  418. this, pfmt, image->GetImageData (), alone_hint))
  419. {
  420. ((csTextureProcOpenGL*)vTex[0])->texG3D = (iGraphics3D*) stexG3D;
  421. if (!texman->head_soft_proc_tex)
  422. texman->head_soft_proc_tex = stexG3D;
  423. }
  424. break;
  425. }
  426. case AUXILIARY_BUFFER_TEXTURE:
  427. default:
  428. break;
  429. }
  430. }
  431. // printf ("init done\n");
  432. }
  433. void csTextureHandleOpenGL::CreateMipmaps ()
  434. {
  435. if (!image) return;
  436. csRGBpixel *tc = transp ? &transp_color : (csRGBpixel *)NULL;
  437. // printf ("delete old\n");
  438. // Delete existing mipmaps, if any
  439. int i;
  440. for (i = vTex.Length ()-1; i >= 0; i--)
  441. {
  442. if (vTex [i])
  443. {
  444. DG_UNLINK (this, vTex[i]);
  445. delete vTex [i];
  446. }
  447. }
  448. vTex.DeleteAll ();
  449. size = 0;
  450. // printf ("push 0\n");
  451. csTexture* ntex = NewTexture (image);
  452. vTex.Push (ntex);
  453. DG_LINK (this, ntex);
  454. // printf ("transform 0\n");
  455. transform (image, vTex[0]);
  456. // 2D textures uses just the top-level mipmap
  457. if ((flags & (CS_TEXTURE_3D | CS_TEXTURE_NOMIPMAPS)) == CS_TEXTURE_3D
  458. && (flags & CS_TEXTURE_PROC) != CS_TEXTURE_PROC)
  459. {
  460. // Create each new level by creating a level 2 mipmap from previous level
  461. // we do this down to 1x1 as opengl defines it
  462. iImage *prevImage = image;
  463. iImage *thisImage;
  464. int w = prevImage->GetWidth ();
  465. int h = prevImage->GetHeight ();
  466. int nTex = 0;
  467. prevImage->IncRef ();
  468. while (w != 1 || h != 1)
  469. {
  470. nTex++;
  471. // printf ("make mipmap %d\n", nTex);
  472. thisImage = prevImage->MipMap (1, tc);
  473. // printf ("push %d\n", nTex);
  474. csTexture* ntex = NewTexture (thisImage);
  475. vTex.Push (ntex);
  476. DG_LINK (this, ntex);
  477. // printf ("transform %d\n", nTex);
  478. transform (thisImage, vTex[nTex]);
  479. w = thisImage->GetWidth ();
  480. h = thisImage->GetHeight ();
  481. prevImage->DecRef ();
  482. prevImage = thisImage;
  483. }
  484. // printf ("meancolor\n");
  485. ComputeMeanColor (vTex[nTex]->get_width (), vTex[nTex]->get_height (),
  486. (csRGBpixel *)prevImage->GetImageData ());
  487. prevImage->DecRef ();
  488. }
  489. else
  490. ComputeMeanColor (vTex[0]->get_width (), vTex[0]->get_height (),
  491. (csRGBpixel *)image->GetImageData ());
  492. }
  493. void csTextureHandleOpenGL::ComputeMeanColor (int w, int h, csRGBpixel *src)
  494. {
  495. int pixels = w * h;
  496. unsigned r = 0, g = 0, b = 0;
  497. int count = pixels;
  498. has_alpha = false;
  499. while (count--)
  500. {
  501. csRGBpixel &pix = *src++;
  502. r += pix.red;
  503. g += pix.green;
  504. b += pix.blue;
  505. if (pix.alpha < 255)
  506. has_alpha = true;
  507. }
  508. mean_color.red = r / pixels;
  509. mean_color.green = g / pixels;
  510. mean_color.blue = b / pixels;
  511. }
  512. bool csTextureHandleOpenGL::GetMipMapDimensions (int mipmap, int &w, int &h)
  513. {
  514. if (mipmap < vTex.Length ())
  515. {
  516. w = vTex[mipmap]->get_width ();
  517. h = vTex[mipmap]->get_height ();
  518. return true;
  519. }
  520. return false;
  521. }
  522. iGraphics3D *csTextureHandleOpenGL::GetProcTextureInterface ()
  523. {
  524. if ((flags & CS_TEXTURE_PROC) != CS_TEXTURE_PROC || vTex.Length () == 0)
  525. return NULL;
  526. return ((csTextureProcOpenGL*)vTex[0])->texG3D;
  527. }
  528. void csTextureHandleOpenGL::Prepare ()
  529. {
  530. InitTexture (txtmgr, &txtmgr->pfmt);
  531. }
  532. //---------------------------------------------------------------------------
  533. csTextureManagerOpenGL::csTextureManagerOpenGL (iObjectRegistry* object_reg,
  534. iGraphics2D* iG2D, iConfigFile *config, csGraphics3DOGLCommon *iG3D)
  535. : csTextureManager (object_reg, iG2D)
  536. {
  537. G3D = iG3D;
  538. head_soft_proc_tex = NULL;
  539. read_config (config);
  540. Clear ();
  541. }
  542. csTextureManagerOpenGL::~csTextureManagerOpenGL ()
  543. {
  544. csTextureManager::Clear ();
  545. }
  546. void csTextureManagerOpenGL::read_config (iConfigFile *config)
  547. {
  548. const char *proc_texture_type =
  549. config->GetStr ("Video.OpenGL.ProceduralTexture");
  550. if (!strcmp (proc_texture_type, "software"))
  551. proc_tex_type = SOFTWARE_TEXTURE;
  552. else if (!strcmp (proc_texture_type, "back_buffer"))
  553. proc_tex_type = BACK_BUFFER_TEXTURE;
  554. else if (!strcmp (proc_texture_type, "auxiliary_buffer"))
  555. proc_tex_type = AUXILIARY_BUFFER_TEXTURE;
  556. else // default
  557. proc_tex_type = BACK_BUFFER_TEXTURE;
  558. iConfigIterator *it = config->Enumerate ("Video.OpenGL.TargetFormat");
  559. while (it->Next ())
  560. AlterTargetFormat (it->GetKey (true)+1, it->GetStr ());
  561. it->DecRef ();
  562. }
  563. void csTextureManagerOpenGL::AlterTargetFormat (const char *oldTarget, const char *newTarget)
  564. {
  565. // first find the old target
  566. int theOld=0;
  567. while (glformats[theOld].name && strcmp (glformats[theOld].name, oldTarget))
  568. theOld++;
  569. if (glformats[theOld].name)
  570. {
  571. if (!strcmp (newTarget, "compressed") && G3D->ARB_texture_compression)
  572. {
  573. GLint compressedFormat;
  574. // is the format compressable at all ?
  575. switch (glformats[theOld].sourceFormat)
  576. {
  577. case GL_RGB:
  578. compressedFormat = GL_COMPRESSED_RGB_ARB;
  579. break;
  580. case GL_RGBA:
  581. compressedFormat = GL_COMPRESSED_RGBA_ARB;
  582. break;
  583. case GL_ALPHA:
  584. compressedFormat = GL_COMPRESSED_ALPHA_ARB;
  585. break;
  586. case GL_LUMINANCE:
  587. compressedFormat = GL_COMPRESSED_LUMINANCE_ARB;
  588. break;
  589. case GL_LUMINANCE_ALPHA:
  590. compressedFormat = GL_COMPRESSED_LUMINANCE_ALPHA_ARB;
  591. break;
  592. case GL_INTENSITY:
  593. compressedFormat = GL_COMPRESSED_INTENSITY_ARB;
  594. break;
  595. default:
  596. printf ("%s is not compressable !\n", oldTarget);
  597. return;
  598. }
  599. glformats[theOld].compressedFormat = compressedFormat;
  600. }
  601. else
  602. {
  603. // does the new format exist ?
  604. int theNew=0;
  605. while (glformats[theNew].name && strcmp (glformats[theNew].name, newTarget))
  606. theNew++;
  607. if (glformats[theNew].name)
  608. if (glformats[theNew].sourceFormat == glformats[theOld].sourceFormat)
  609. glformats[theOld].forcedFormat = glformats[theNew].targetFormat;
  610. else
  611. {
  612. printf ("You can only force a new targetFormat if both, old and new targetFormat,"
  613. " have the same sourceFormat\n");
  614. }
  615. }
  616. }
  617. }
  618. void csTextureManagerOpenGL::DetermineStorageSizes ()
  619. {
  620. int i=-1;
  621. int d = pfmt.PixelBytes;
  622. while (glformats[++i].components)
  623. {
  624. if (glformats[i].texelbytes == 0)
  625. {
  626. glformats[i].texelbytes = glformats[i].components * 8;
  627. if (glformats[i].texelbytes > d)
  628. glformats[i].texelbytes = d;
  629. }
  630. }
  631. }
  632. void csTextureManagerOpenGL::SetPixelFormat (csPixelFormat &PixelFormat)
  633. {
  634. pfmt = PixelFormat;
  635. max_tex_size = G3D->max_texture_size;
  636. DetermineStorageSizes ();
  637. }
  638. void csTextureManagerOpenGL::PrepareTextures ()
  639. {
  640. // Create mipmaps for all textures
  641. int i;
  642. for (i = 0; i < textures.Length (); i++)
  643. textures.Get (i)->Prepare ();
  644. }
  645. iTextureHandle *csTextureManagerOpenGL::RegisterTexture (iImage* image, int flags)
  646. {
  647. if (!image) return NULL;
  648. csTextureHandleOpenGL* txt = new csTextureHandleOpenGL (image, flags, GL_RGBA, pfmt.PixelBytes*8, G3D);
  649. textures.Push (txt);
  650. return txt;
  651. }
  652. void csTextureManagerOpenGL::UnregisterTexture (csTextureHandleOpenGL *handle)
  653. {
  654. int idx = textures.Find (handle);
  655. if (idx >= 0) textures.Delete (idx);
  656. }
  657. void csTextureManagerOpenGL::Clear ()
  658. {
  659. for (int i=0; i < textures.Length (); i++)
  660. ((csTextureHandleOpenGL *)textures.Get (i))->Clear ();
  661. csTextureManager::Clear ();
  662. }