PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

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

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