Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1078 lines
27 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: texture.c
  3. *
  4. * Texture handling functions
  5. *
  6. * Copyright (c) 1994 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <sys/types.h>
  14. #include <time.h>
  15. #include <windows.h>
  16. #include <scrnsave.h>
  17. #include <commdlg.h>
  18. #include "mtk.h"
  19. #include "texture.hxx"
  20. #include "glutil.hxx"
  21. //static int VerifyTextureFile( TEXFILE *pTexFile );
  22. static int GetTexFileType( TEXFILE *pTexFile );
  23. static PFNGLCOLORTABLEEXTPROC pfnColorTableEXT;
  24. static PFNGLCOLORSUBTABLEEXTPROC pfnColorSubTableEXT;
  25. /******************************Public*Routine******************************\
  26. *
  27. * TEXTURE
  28. *
  29. * Create a texture from a BMP or RGB file
  30. *
  31. \**************************************************************************/
  32. TEXTURE::TEXTURE( TEXFILE *pTexFile )
  33. {
  34. TK_RGBImageRec *image = (TK_RGBImageRec *) NULL;
  35. LPTSTR pszBmpfile = pTexFile->szPathName;
  36. int type;
  37. Init();
  38. // Verify file / set type
  39. if( !(type = mtk_VerifyTextureFileData( pTexFile )) )
  40. return;
  41. // While we're still calling into the tk routines, disable popups
  42. // Eventually should pull tk code in here - all that's required is the
  43. // file parsing code.
  44. tkErrorPopups( FALSE );
  45. //mf: I guess can't have TEX_A8 type file ?
  46. if( type == TEX_BMP ) {
  47. #ifdef UNICODE
  48. image = tkDIBImageLoadAW( (char *) pszBmpfile, TRUE );
  49. #else
  50. image = tkDIBImageLoadAW( (char *) pszBmpfile, FALSE );
  51. #endif
  52. } else {
  53. #ifdef UNICODE
  54. image = tkRGBImageLoadAW( (char *) pszBmpfile, TRUE );
  55. #else
  56. image = tkRGBImageLoadAW( (char *) pszBmpfile, FALSE );
  57. #endif
  58. }
  59. if( !image ) {
  60. return;
  61. }
  62. ProcessTkTexture( image );
  63. }
  64. TEXTURE::TEXTURE( LPTSTR pszBmpFile )
  65. {
  66. TK_RGBImageRec *image = (TK_RGBImageRec *) NULL;
  67. int type;
  68. TEXFILE texFile; // path name, plus offset to file name
  69. Init();
  70. //mf: this VerifyFile stuff needs some work
  71. // Look for file, and set nOffset if found
  72. lstrcpy( texFile.szPathName, pszBmpFile );
  73. if( ! mtk_VerifyTextureFilePath( &texFile ) )
  74. return;
  75. // Now determine the file type (this also aborts if size is too big)
  76. if( !(type = mtk_VerifyTextureFileData( &texFile )) )
  77. return;
  78. // Now the bmp file should point to the full path for tk
  79. pszBmpFile = texFile.szPathName;
  80. //mf: I guess can't have TEX_A8 type file ?
  81. if( type == TEX_BMP ) {
  82. #ifdef UNICODE
  83. image = tkDIBImageLoadAW( (char *) pszBmpFile, TRUE );
  84. #else
  85. image = tkDIBImageLoadAW( (char *) pszBmpFile, FALSE );
  86. #endif
  87. } else {
  88. #ifdef UNICODE
  89. image = tkRGBImageLoadAW( (char *) pszBmpFile, TRUE );
  90. #else
  91. image = tkRGBImageLoadAW( (char *) pszBmpFile, FALSE );
  92. #endif
  93. }
  94. if( !image ) {
  95. return;
  96. }
  97. ProcessTkTexture( image );
  98. }
  99. /******************************Public*Routine******************************\
  100. *
  101. * TEXTURE
  102. *
  103. * Create a texture from a BMP or other resource (RGB , A8, etc. )
  104. *
  105. \**************************************************************************/
  106. TEXTURE::TEXTURE( TEX_RES *pTexRes, HINSTANCE hInst )
  107. {
  108. HMODULE hModule;
  109. Init();
  110. if( hInst )
  111. hModule = hInst;
  112. else
  113. hModule = GetModuleHandle(NULL);
  114. if( pTexRes->type == TEX_BMP )
  115. LoadBitmapResource( MAKEINTRESOURCE( pTexRes->name ), hModule );
  116. else
  117. LoadOtherResource( pTexRes, hModule );
  118. }
  119. /******************************Public*Routine******************************\
  120. *
  121. * TEXTURE
  122. *
  123. * Create a texture from an HBITMAP
  124. *
  125. \**************************************************************************/
  126. TEXTURE::TEXTURE( HBITMAP hBitmap )
  127. {
  128. if (hBitmap == NULL)
  129. {
  130. SS_ERROR( "TEXTURE::TEXTURE : hBitmap is NULL\n" );
  131. return;
  132. }
  133. Init();
  134. LoadFromBitmap( hBitmap );
  135. }
  136. /******************************Public*Routine******************************\
  137. *
  138. * Load a bitmap texture resource, creating the HBITMAP from the resource
  139. * identifier
  140. *
  141. \**************************************************************************/
  142. BOOL
  143. TEXTURE::LoadBitmapResource( LPTSTR pRes, HINSTANCE hInst )
  144. {
  145. HBITMAP hBitmap = LoadBitmap( hInst, pRes );
  146. if( hBitmap == NULL ) {
  147. SS_ERROR( "TEXTURE::LoadBitmapResource : LoadBitmap failure\n" );
  148. return FALSE;
  149. }
  150. LoadFromBitmap( hBitmap );
  151. DeleteObject( hBitmap );
  152. return TRUE;
  153. }
  154. /******************************Public*Routine******************************\
  155. *
  156. * Load a non-bmp texture resource
  157. *
  158. \**************************************************************************/
  159. BOOL
  160. TEXTURE::LoadOtherResource( TEX_RES *pTexRes, HINSTANCE hInst )
  161. {
  162. HRSRC hr;
  163. HGLOBAL hg;
  164. LPVOID pv;
  165. LPCTSTR lpType;
  166. BOOL fLoaded = FALSE;
  167. switch(pTexRes->type)
  168. {
  169. case TEX_RGB:
  170. lpType = MAKEINTRESOURCE(RT_RGB);
  171. break;
  172. case TEX_A8:
  173. lpType = MAKEINTRESOURCE(RT_A8);
  174. break;
  175. default :
  176. return FALSE;
  177. }
  178. hr = FindResource(hInst, MAKEINTRESOURCE(pTexRes->name), lpType);
  179. if (hr == NULL)
  180. {
  181. SS_ERROR( "TEXTURE::LoadOtherResource() : Can't find texture resource\n" );
  182. goto EH_NotFound;
  183. }
  184. hg = LoadResource(hInst, hr);
  185. if (hg == NULL)
  186. {
  187. SS_ERROR( "TEXTURE::LoadOtherResource() : Error loading texture resource\n" );
  188. goto EH_FreeResource;
  189. }
  190. pv = (PSZ)LockResource(hg);
  191. if (pv == NULL)
  192. {
  193. SS_ERROR( "TEXTURE::LoadOtherResource() : Error locking texture resource\n" );
  194. goto EH_FreeResource;
  195. }
  196. switch(pTexRes->type)
  197. {
  198. case TEX_RGB:
  199. fLoaded = RGBImageLoad( pv );
  200. break;
  201. case TEX_A8:
  202. fLoaded = A8ImageLoad( pv );
  203. break;
  204. }
  205. EH_FreeResource:
  206. FreeResource(hr);
  207. EH_NotFound:
  208. if( !fLoaded ) {
  209. SS_ERROR( "TEXTURE::LoadOtherResource() : Texture resource did not load\n" );
  210. return FALSE;
  211. }
  212. Process();
  213. return TRUE;
  214. }
  215. /******************************Public*Routine******************************\
  216. *
  217. * Load a bitmap texture resource from an HBITMAP
  218. *
  219. \**************************************************************************/
  220. BOOL
  221. TEXTURE::LoadFromBitmap( HBITMAP hBitmap )
  222. {
  223. BOOL fLoaded = DIBImageLoad( hBitmap );
  224. if( !fLoaded ) {
  225. SS_ERROR( "TEXTURE::LoadFromBitmap : bitmap texture did not load\n" );
  226. return FALSE;
  227. }
  228. Process();
  229. return TRUE;
  230. }
  231. /******************************Public*Routine******************************\
  232. *
  233. * Init
  234. *
  235. * Common constructor intialization
  236. *
  237. \**************************************************************************/
  238. void
  239. TEXTURE::Init()
  240. {
  241. width = 0;
  242. height = 0;
  243. data = NULL;
  244. pal_size = 0;
  245. pal = NULL;
  246. texObj = 0;
  247. iPalRot = 0;
  248. bMipmap = FALSE;
  249. }
  250. /******************************Public*Routine******************************\
  251. *
  252. * ValidateTextureSize
  253. *
  254. * - Scales the texture to powers of 2
  255. *
  256. \**************************************************************************/
  257. BOOL
  258. TEXTURE::ValidateSize()
  259. {
  260. double xPow2, yPow2;
  261. int ixPow2, iyPow2;
  262. int xSize2, ySize2;
  263. float fxFact, fyFact;
  264. GLint glMaxTexDim;
  265. if( (width <= 0) || (height <= 0) ) {
  266. SS_WARNING( "ValidateTextureSize : invalid texture dimensions\n" );
  267. return FALSE;
  268. }
  269. // origAspectRatio = (float) height / (float) width;
  270. //mf: changed this to standard x/y
  271. origAspectRatio = (float) width / (float) height;
  272. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);
  273. if( glMaxTexDim <= 0 )
  274. return FALSE;
  275. if( format != GL_COLOR_INDEX ) {
  276. // We limit the max dimension here for performance reasons
  277. glMaxTexDim = min(256, glMaxTexDim);
  278. if (width <= glMaxTexDim)
  279. xPow2 = log((double)width) / log((double)2.0);
  280. else
  281. xPow2 = log((double)glMaxTexDim) / log((double)2.0);
  282. if (height <= glMaxTexDim)
  283. yPow2 = log((double)height) / log((double)2.0);
  284. else
  285. yPow2 = log((double)glMaxTexDim) / log((double)2.0);
  286. ixPow2 = (int)xPow2;
  287. iyPow2 = (int)yPow2;
  288. // Always scale to higher nearest power
  289. if (xPow2 != (double)ixPow2)
  290. ixPow2++;
  291. if (yPow2 != (double)iyPow2)
  292. iyPow2++;
  293. xSize2 = 1 << ixPow2;
  294. ySize2 = 1 << iyPow2;
  295. if (xSize2 != width ||
  296. ySize2 != height)
  297. {
  298. BYTE *pData;
  299. pData = (BYTE *) malloc(xSize2 * ySize2 * components * sizeof(BYTE));
  300. if (!pData) {
  301. SS_WARNING( "ValidateTextureSize : can't alloc pData\n" );
  302. return FALSE;
  303. }
  304. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  305. if( gluScaleImage(format, width, height,
  306. GL_UNSIGNED_BYTE, data,
  307. xSize2, ySize2, GL_UNSIGNED_BYTE,
  308. pData) )
  309. {
  310. // glu failure
  311. SS_WARNING( "ValidateTextureSize : gluScaleImage failure\n" );
  312. return FALSE;
  313. }
  314. // set the new width,height,data
  315. width = xSize2;
  316. height = ySize2;
  317. free(data);
  318. data = pData;
  319. }
  320. } else { // paletted texture case
  321. //mf
  322. // paletted texture: must be power of 2 - but might need to enforce
  323. // here if not done in a8 load. Also have to check against
  324. // GL_MAX_TEXTURE_SIZE. Could then clip it to power of 2 size
  325. }
  326. return TRUE;
  327. }
  328. /******************************Public*Routine******************************\
  329. *
  330. * SetDefaultTextureParams
  331. *
  332. \**************************************************************************/
  333. void
  334. TEXTURE::SetDefaultParams()
  335. {
  336. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  337. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  338. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  339. if( bMipmap )
  340. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  341. GL_LINEAR_MIPMAP_LINEAR);
  342. else
  343. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  344. }
  345. /******************************Public*Routine******************************\
  346. *
  347. * ProcessTexture
  348. *
  349. * - Verifies texture size
  350. * - Fills out TEXTURE structure with required data
  351. * - Creates a texture object if extension exists
  352. *
  353. \**************************************************************************/
  354. int
  355. TEXTURE::Process()
  356. {
  357. // Enforce proper texture size (power of 2, etc.)
  358. if( !ValidateSize() )
  359. return 0;
  360. // if texturing objects available, init the object
  361. if( gGLCaps.bTextureObjects ) {
  362. glGenTextures( 1, &texObj );
  363. glBindTexture( GL_TEXTURE_2D, texObj );
  364. //mf: mipmap stuff
  365. // Default attributes for texObj
  366. SetDefaultParams();
  367. if( bMipmap )
  368. //mf: error return...
  369. gluBuild2DMipmaps( GL_TEXTURE_2D, components,
  370. width, height, format,
  371. GL_UNSIGNED_BYTE, data );
  372. else
  373. glTexImage2D( GL_TEXTURE_2D, 0, components,
  374. width, height, 0, format,
  375. GL_UNSIGNED_BYTE, data );
  376. if (gGLCaps.bPalettedTexture && pal != NULL)
  377. {
  378. pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
  379. GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
  380. }
  381. } else
  382. texObj = 0;
  383. return 1;
  384. }
  385. /******************************Public*Routine******************************\
  386. *
  387. * ProcessTkTexture
  388. *
  389. * Simple wrapper for ProcessTexture which fills out a TEXTURE
  390. * from a TK_RGBImageRec
  391. *
  392. * Frees the ImageRec if ProcessTexture succeeds
  393. *
  394. \**************************************************************************/
  395. int
  396. TEXTURE::ProcessTkTexture( TK_RGBImageRec *image )
  397. {
  398. width = image->sizeX;
  399. height = image->sizeY;
  400. format = GL_RGB;
  401. components = 3;
  402. data = image->data;
  403. pal_size = 0;
  404. pal = NULL;
  405. if( Process() )
  406. {
  407. //mf: ?? don't understand this freeing stuff...
  408. free(image);
  409. return 1;
  410. }
  411. else
  412. {
  413. return 0;
  414. }
  415. }
  416. /******************************Public*Routine******************************\
  417. *
  418. * MakeCurrent
  419. *
  420. \**************************************************************************/
  421. void
  422. TEXTURE::MakeCurrent()
  423. {
  424. if( texObj ) {
  425. glBindTexture( GL_TEXTURE_2D, texObj );
  426. return;
  427. }
  428. if( bMipmap )
  429. gluBuild2DMipmaps( GL_TEXTURE_2D, components,
  430. width, height, format,
  431. GL_UNSIGNED_BYTE, data );
  432. else
  433. glTexImage2D( GL_TEXTURE_2D, 0, components,
  434. width, height, 0, format,
  435. GL_UNSIGNED_BYTE, data );
  436. //mf: ? no rotation if no tex objs ?
  437. if( pal )
  438. {
  439. pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
  440. GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
  441. }
  442. }
  443. #if 0
  444. /******************************Public*Routine******************************\
  445. *
  446. * ss_CopyTexture
  447. *
  448. * Make a copy of a texture.
  449. *
  450. \**************************************************************************/
  451. BOOL
  452. TEXTURE::ss_CopyTexture( TEXTURE *pTexDst, TEXTURE *pTexSrc )
  453. {
  454. int size;
  455. if( (pTexDst == NULL) || (pTexSrc == NULL) )
  456. return FALSE;
  457. *pTexDst = *pTexSrc;
  458. if( gGLCaps.bTextureObjects && pTexSrc->texObj ) {
  459. glGenTextures( 1, &pTexDst->texObj );
  460. }
  461. // copy image data
  462. size = pTexSrc->width * pTexSrc->height;
  463. if( pTexSrc->components != GL_COLOR_INDEX8_EXT )
  464. size *= pTexSrc->components; // since data format always UNSIGNED_BYTE
  465. pTexDst->data = (unsigned char *) malloc( size );
  466. if( pTexDst->pal == NULL )
  467. return FALSE;
  468. memcpy( pTexDst->data, pTexSrc->data, size );
  469. // copy palette data
  470. if( gGLCaps.bPalettedTexture && pTexSrc->pal != NULL )
  471. {
  472. size = pTexSrc->pal_size*sizeof(RGBQUAD);
  473. pTexDst->pal = (RGBQUAD *) malloc(size);
  474. if( pTexDst->pal == NULL )
  475. {
  476. free(pTexDst->data);
  477. return FALSE;
  478. }
  479. memcpy( pTexDst->pal, pTexSrc->pal, size );
  480. }
  481. if( pTexDst->texObj ) {
  482. glBindTexture( GL_TEXTURE_2D, pTexDst->texObj );
  483. // Default attributes for texObj
  484. SetDefaultTextureParams( pTexDst );
  485. if( pTexDst->bMipmap )
  486. gluBuild2DMipmaps( GL_TEXTURE_2D, pTexDst->components,
  487. pTexDst->width, pTexDst->height, pTexDst->format,
  488. GL_UNSIGNED_BYTE, pTexDst->data );
  489. else
  490. glTexImage2D( GL_TEXTURE_2D, 0, pTexDst->components,
  491. pTexDst->width, pTexDst->height, 0, pTexDst->format,
  492. GL_UNSIGNED_BYTE, pTexDst->data );
  493. if( pTexDst->pal )
  494. {
  495. pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pTexDst->pal_size,
  496. GL_BGRA_EXT, GL_UNSIGNED_BYTE, pTexDst->pal);
  497. }
  498. }
  499. return TRUE;
  500. }
  501. #endif
  502. /******************************Public*Routine******************************\
  503. *
  504. * ss_SetTexturePalette
  505. *
  506. * Set a texture's palette according to the supplied index. This index
  507. * indicates the start of the palette, which then wraps around if necessary.
  508. * Of course this only works on paletted textures.
  509. *
  510. \**************************************************************************/
  511. void
  512. TEXTURE::SetPaletteRotation( int index )
  513. {
  514. if( index == iPalRot )
  515. return;
  516. if( pal && pal_size ) {
  517. iPalRot = index & (pal_size - 1);
  518. MakeCurrent();
  519. SetPalette();
  520. }
  521. }
  522. void
  523. TEXTURE::IncrementPaletteRotation()
  524. {
  525. if( pal && pal_size ) {
  526. iPalRot = ++iPalRot & (pal_size - 1);
  527. MakeCurrent();
  528. SetPalette();
  529. }
  530. }
  531. void
  532. TEXTURE::SetPalette()
  533. {
  534. int start, count;
  535. start = iPalRot & (pal_size - 1);
  536. count = pal_size - start;
  537. pfnColorSubTableEXT(GL_TEXTURE_2D, 0, count, GL_BGRA_EXT,
  538. GL_UNSIGNED_BYTE, pal + start);
  539. if (start != 0)
  540. {
  541. pfnColorSubTableEXT(GL_TEXTURE_2D, count, start, GL_BGRA_EXT,
  542. GL_UNSIGNED_BYTE, pal);
  543. }
  544. }
  545. /******************************Public*Routine******************************\
  546. *
  547. * SetTextureAlpha
  548. *
  549. * Set a constant alpha value for the texture
  550. * Again, don't overwrite any existing 0 alpha values, as explained in
  551. * ss_SetTextureTransparency
  552. *
  553. \**************************************************************************/
  554. void
  555. TEXTURE::SetAlpha( float fAlpha )
  556. {
  557. int i;
  558. unsigned char *pData = data;
  559. RGBA8 *pColor = (RGBA8 *) data;
  560. BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
  561. if( components != 4 )
  562. return;
  563. for( i = 0; i < width*height; i ++, pColor++ ) {
  564. if( pColor->a != 0 )
  565. pColor->a = bAlpha;
  566. }
  567. }
  568. /******************************Public*Routine******************************\
  569. *
  570. * ConvertToRGBA
  571. *
  572. * Convert RGB texture to RGBA
  573. *
  574. \**************************************************************************/
  575. BOOL
  576. TEXTURE::ConvertToRGBA( float fAlpha )
  577. {
  578. unsigned char *pNewData;
  579. int count = width * height;
  580. unsigned char *src, *dst;
  581. BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
  582. int i;
  583. if( components != 3 ) {
  584. SS_ERROR( "TEXTURE::ConvertToRGBA : Can't convert, components != 3\n" );
  585. return FALSE;
  586. }
  587. pNewData = (unsigned char *) LocalAlloc(LMEM_FIXED, count * sizeof(RGBA8));
  588. if( !pNewData ) {
  589. SS_ERROR( "TEXTURE::ConvertToRGBA : memory failure\n" );
  590. return FALSE;
  591. }
  592. src = data;
  593. dst = pNewData;
  594. if( format == GL_RGB ) {
  595. // R is lsb, A will be msb
  596. for( i = 0; i < count; i ++ ) {
  597. *((RGB8 *)dst) = *((RGB8 *)src);
  598. dst += sizeof(RGB8);
  599. src += sizeof(RGB8);
  600. *dst++ = bAlpha;
  601. }
  602. format = GL_RGBA;
  603. } else { // format == GL_BGR_EXT
  604. // R is msb, A will be msb
  605. for( i = 0; i < count; i ++ ) {
  606. *dst++ = bAlpha;
  607. *((RGB8 *)dst) = *((RGB8 *)src);
  608. dst += sizeof(RGB8);
  609. src += sizeof(RGB8);
  610. }
  611. format = GL_BGRA_EXT;
  612. }
  613. LocalFree( data );
  614. data = pNewData;
  615. components = 4;
  616. return TRUE;
  617. }
  618. /******************************Public*Routine******************************\
  619. *
  620. * ss_SetTextureTransparency
  621. *
  622. * Set transparency for a texture by adding or modifying the alpha data.
  623. * Transparency value must be between 0.0 (opaque) and 1.0 (fully transparent)
  624. * If the texture data previously had no alpha, add it in.
  625. * If bSet is TRUE, make this the current texture.
  626. *
  627. * Note: Currently fully transparent pixels (alpha=0) will not be altered, since
  628. * it is assumed these should be permanently transparent (could make this an
  629. * option? - bPreserveTransparentPixels )
  630. *
  631. \**************************************************************************/
  632. BOOL
  633. TEXTURE::SetTransparency( float fTransp, BOOL bSet )
  634. {
  635. int i;
  636. float fAlpha;
  637. SS_CLAMP_TO_RANGE2( fTransp, 0.0f, 1.0f );
  638. fAlpha = 1 - fTransp;
  639. if( format == GL_COLOR_INDEX )
  640. {
  641. // just need to modify the palette
  642. RGBQUAD *pPal = pal;
  643. BYTE bAlpha = (BYTE) (fAlpha * 255.0f);
  644. if( !pPal )
  645. return FALSE;
  646. for( i = 0; i < pal_size; i ++, pPal++ ) {
  647. if( pPal->rgbReserved != 0 )
  648. pPal->rgbReserved = bAlpha;
  649. }
  650. // need to send down the new palette for texture objects
  651. if( texObj && pal )
  652. {
  653. glBindTexture( GL_TEXTURE_2D, texObj );
  654. pfnColorTableEXT(GL_TEXTURE_2D, GL_RGBA, pal_size,
  655. GL_BGRA_EXT, GL_UNSIGNED_BYTE, pal);
  656. }
  657. }
  658. else {
  659. // Need to setup new texture data
  660. if( components != 4 ) {
  661. // Make room for alpha component
  662. //mf: ? change to byte Alpha ?
  663. if( !ConvertToRGBA( fAlpha ) )
  664. return FALSE;
  665. } else {
  666. // Set alpha component
  667. SetAlpha( fAlpha );
  668. }
  669. // Send down new data if texture objects
  670. if( texObj )
  671. {
  672. glBindTexture( GL_TEXTURE_2D, texObj );
  673. if( bMipmap )
  674. //mf: inefficient !!!
  675. gluBuild2DMipmaps( GL_TEXTURE_2D, components,
  676. width, height, format,
  677. GL_UNSIGNED_BYTE, data );
  678. else
  679. glTexImage2D( GL_TEXTURE_2D, 0, components,
  680. width, height, 0, format,
  681. GL_UNSIGNED_BYTE, data );
  682. }
  683. }
  684. if( bSet )
  685. MakeCurrent();
  686. return TRUE;
  687. }
  688. /******************************Public*Routine******************************\
  689. *
  690. * ss_DeleteTexture
  691. *
  692. \**************************************************************************/
  693. TEXTURE::~TEXTURE()
  694. {
  695. if( texObj ) {
  696. glDeleteTextures( 1, &texObj );
  697. }
  698. if (pal != NULL)
  699. {
  700. free(pal);
  701. }
  702. if( data )
  703. free( data );
  704. }
  705. /******************************Public*Routine******************************\
  706. *
  707. * ss_TextureObjectsEnabled
  708. *
  709. * Returns BOOL set by ss_QueryGLVersion (Texture Objects only supported on
  710. * GL v.1.1 or greater)
  711. *
  712. \**************************************************************************/
  713. BOOL
  714. mtk_TextureObjectsEnabled( void )
  715. {
  716. return gGLCaps.bTextureObjects;
  717. }
  718. /******************************Public*Routine******************************\
  719. *
  720. * ss_PalettedTextureEnabled
  721. *
  722. * Returns result from ss_QueryPalettedTextureEXT
  723. *
  724. \**************************************************************************/
  725. BOOL
  726. mtk_PalettedTextureEnabled( void )
  727. {
  728. return gGLCaps.bPalettedTexture;
  729. }
  730. /******************************Public*Routine******************************\
  731. *
  732. * ss_QueryPalettedTextureEXT
  733. *
  734. * Queries the OpenGL implementation to see if paletted texture is supported
  735. * Typically called once at app startup.
  736. *
  737. \**************************************************************************/
  738. BOOL
  739. mtk_QueryPalettedTextureEXT( void )
  740. {
  741. PFNGLGETCOLORTABLEPARAMETERIVEXTPROC pfnGetColorTableParameterivEXT;
  742. int size;
  743. pfnColorTableEXT = (PFNGLCOLORTABLEEXTPROC)
  744. wglGetProcAddress("glColorTableEXT");
  745. if (pfnColorTableEXT == NULL)
  746. return FALSE;
  747. pfnColorSubTableEXT = (PFNGLCOLORSUBTABLEEXTPROC)
  748. wglGetProcAddress("glColorSubTableEXT");
  749. if (pfnColorSubTableEXT == NULL)
  750. return FALSE;
  751. // Check color table size
  752. pfnGetColorTableParameterivEXT = (PFNGLGETCOLORTABLEPARAMETERIVEXTPROC)
  753. wglGetProcAddress("glGetColorTableParameterivEXT");
  754. if (pfnGetColorTableParameterivEXT == NULL)
  755. return FALSE;
  756. // For now, the only paletted textures supported in this lib are TEX_A8,
  757. // with 256 color table entries. Make sure the device supports this.
  758. pfnColorTableEXT(GL_PROXY_TEXTURE_2D, GL_RGBA, 256,
  759. GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL );
  760. pfnGetColorTableParameterivEXT( GL_PROXY_TEXTURE_2D,
  761. GL_COLOR_TABLE_WIDTH_EXT, &size );
  762. if( size != 256 )
  763. // The device does not support a color table size of 256, so we don't
  764. // enable paletted textures in general.
  765. return FALSE;
  766. return TRUE;
  767. }
  768. /******************************Public*Routine******************************\
  769. *
  770. * ss_VerifyTextureFile
  771. *
  772. * Validates texture bmp or rgb file, by checking for valid pathname and
  773. * correct format.
  774. *
  775. * History
  776. * Apr. 28, 95 : [marcfo]
  777. * - Wrote it
  778. *
  779. * Jul. 25, 95 : [marcfo]
  780. * - Suppress warning dialog box in child preview mode, as it will
  781. * be continuously brought up.
  782. *
  783. * Dec. 12, 95 : [marcfo]
  784. * - Support .rgb files as well
  785. *
  786. * Dec. 14, 95 : [marcfo]
  787. * - Change to have it only check the file path
  788. *
  789. \**************************************************************************/
  790. //mf: this can become a standard file function
  791. BOOL
  792. mtk_VerifyTextureFilePath( TEXFILE *ptf )
  793. {
  794. // Make sure the selected texture file is OK.
  795. ISIZE size;
  796. TCHAR szFileName[MAX_PATH];
  797. PTSTR pszString;
  798. TCHAR szString[MAX_PATH];
  799. lstrcpy(szFileName, ptf->szPathName);
  800. if ( SearchPath(NULL, szFileName, NULL, MAX_PATH,
  801. ptf->szPathName, &pszString)
  802. )
  803. {
  804. ptf->nOffset = pszString - ptf->szPathName;
  805. return TRUE;
  806. }
  807. else
  808. {
  809. lstrcpy(ptf->szPathName, szFileName); // restore
  810. return FALSE;
  811. }
  812. }
  813. /******************************Public*Routine******************************\
  814. *
  815. * VerifyTextureFile
  816. *
  817. * Verify that a bitmap or rgb file is valid
  818. *
  819. * Returns:
  820. * File type (RGB or BMP) if valid file; otherwise, 0.
  821. *
  822. * History
  823. * Dec. 12, 95 : [marcfo]
  824. * - Creation
  825. *
  826. \**************************************************************************/
  827. int
  828. mtk_VerifyTextureFileData( TEXFILE *pTexFile )
  829. {
  830. int type;
  831. ISIZE size;
  832. BOOL bValid;
  833. TCHAR szString[2 * MAX_PATH]; // May contain a pathname
  834. // check for 0 offset and null strings
  835. if( (pTexFile->nOffset == 0) || (*pTexFile->szPathName == 0) )
  836. return 0;
  837. type = GetTexFileType( pTexFile );
  838. switch( type ) {
  839. case TEX_BMP:
  840. bValid = bVerifyDIB( pTexFile->szPathName, &size );
  841. break;
  842. case TEX_RGB:
  843. bValid = bVerifyRGB( pTexFile->szPathName, &size );
  844. break;
  845. case TEX_UNKNOWN:
  846. default:
  847. bValid = FALSE;
  848. }
  849. if( !bValid ) {
  850. return 0;
  851. }
  852. // Check size ?
  853. if ( (size.width > TEX_WIDTH_MAX) ||
  854. (size.height > TEX_HEIGHT_MAX) )
  855. {
  856. return 0;
  857. }
  858. return type;
  859. }
  860. /******************************Public*Routine******************************\
  861. *
  862. * ss_InitAutoTexture
  863. *
  864. * Generate texture coordinates automatically.
  865. * If pTexRep is not NULL, use it to set the repetition of the generated
  866. * texture.
  867. *
  868. \**************************************************************************/
  869. void
  870. mtk_InitAutoTexture( TEX_POINT2D *pTexRep )
  871. {
  872. GLfloat sgenparams[] = {1.0f, 0.0f, 0.0f, 0.0f};
  873. GLfloat tgenparams[] = {0.0f, 1.0f, 0.0f, 0.0f};
  874. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
  875. if( pTexRep )
  876. sgenparams[0] = pTexRep->s;
  877. glTexGenfv(GL_S, GL_OBJECT_PLANE, sgenparams );
  878. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
  879. if( pTexRep )
  880. tgenparams[0] = pTexRep->t;
  881. glTexGenfv(GL_T, GL_OBJECT_PLANE, tgenparams );
  882. glEnable(GL_TEXTURE_GEN_S);
  883. glEnable(GL_TEXTURE_GEN_T);
  884. glEnable( GL_TEXTURE_2D );
  885. }
  886. /******************************Public*Routine******************************\
  887. *
  888. * GetTexFileType
  889. *
  890. * Determine if a texture file is rgb or bmp, based on extension. This is
  891. * good enough, as the open texture dialog only shows files with these
  892. * extensions.
  893. *
  894. \**************************************************************************/
  895. static int
  896. GetTexFileType( TEXFILE *pTexFile )
  897. {
  898. LPTSTR pszStr;
  899. #ifdef UNICODE
  900. pszStr = wcsrchr( pTexFile->szPathName + pTexFile->nOffset,
  901. (USHORT) L'.' );
  902. #else
  903. pszStr = strrchr( pTexFile->szPathName + pTexFile->nOffset,
  904. (USHORT) L'.' );
  905. #endif
  906. if( !pszStr || (lstrlen(++pszStr) == 0) )
  907. return TEX_UNKNOWN;
  908. if( !lstrcmpi( pszStr, TEXT("bmp") ) )
  909. return TEX_BMP;
  910. else if( !lstrcmpi( pszStr, TEXT("rgb") ) )
  911. return TEX_RGB;
  912. else
  913. return TEX_UNKNOWN;
  914. }