texture.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "texture.h"
  2. #if defined(_WIN32)
  3. #include <crtdbg.h>
  4. #include <windows.h>
  5. #else
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <sys/mman.h>
  10. #endif
  11. #include <string.h>
  12. #include <assert.h>
  13. #include <math.h>
  14. #include <fcntl.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #ifndef _ASSERT
  18. #define _ASSERT(x)
  19. #endif
  20. #define MAX(x,y) ((x)>(y) ? (x) : (y))
  21. const void *lockFile(const char *filename, MemoryChunk *chunk)
  22. {
  23. _ASSERT(filename);
  24. _ASSERT(chunk);
  25. memset(chunk, 0, sizeof(MemoryChunk));
  26. #if defined(_WIN32) && !defined(__SYMBIAN32__)
  27. wchar_t wideFileName[MAX_PATH];
  28. mbstowcs(wideFileName, filename, ARRAYSIZE(wideFileName));
  29. HANDLE fd=CreateFile(wideFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  30. if(fd==INVALID_HANDLE_VALUE) return 0;
  31. chunk->fd=fd;
  32. LARGE_INTEGER size;
  33. GetFileSizeEx(fd, &size);
  34. chunk->size=size.LowPart;
  35. chunk->mapping=CreateFileMapping(fd, NULL, PAGE_READONLY, size.HighPart, size.LowPart, NULL);
  36. chunk->ptr=MapViewOfFile(chunk->mapping, FILE_MAP_READ, 0, 0, 0);
  37. return chunk->ptr;
  38. #else
  39. //#error TODO
  40. struct stat s;
  41. int fd=open(filename, O_RDONLY);
  42. if(fd==-1) return NULL;
  43. if(fstat(fd, &s)!=0 || s.st_size==0)
  44. {
  45. close(fd);
  46. return NULL;
  47. }
  48. void *ptr=mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
  49. if(ptr!=(void*)-1)
  50. {
  51. chunk->ptr=ptr;
  52. chunk->fd=fd;
  53. chunk->size=s.st_size;
  54. return chunk->ptr;
  55. }
  56. else
  57. {
  58. ptr=malloc(s.st_size);
  59. if(read(fd, ptr, s.st_size)!=-1)
  60. {
  61. chunk->ptr=ptr;
  62. chunk->fd=fd;
  63. chunk->size=s.st_size;
  64. return chunk->ptr;
  65. }
  66. }
  67. #endif
  68. return NULL;
  69. }
  70. void unlockFile(MemoryChunk *chunk)
  71. {
  72. _ASSERT(chunk);
  73. #if defined(_WIN32) && !defined(__SYMBIAN32__)
  74. CloseHandle(chunk->mapping);
  75. CloseHandle(chunk->fd);
  76. #else
  77. //#error TODO
  78. munmap((void*)chunk->ptr, chunk->size);
  79. close(chunk->fd);
  80. #endif
  81. memset(chunk, 0, sizeof(MemoryChunk));
  82. }
  83. void pvrTexImage2D(const PVR_Texture_Header *pvr)
  84. {
  85. const unsigned char *tex=((const unsigned char *)pvr)+pvr->dwHeaderSize;
  86. GLuint textureFormat;
  87. const bool alpha=(pvr->dwAlphaBitMask!=0);
  88. for(unsigned int level=0;level<=pvr->dwMipMapCount;level++)
  89. {
  90. GLsizei size;
  91. GLsizei width=pvr->dwWidth>>level;
  92. GLsizei height=pvr->dwHeight>>level;
  93. switch(pvr->dwpfFlags & PVRTEX_PIXELTYPE)
  94. {
  95. case OGL_PVRTC2:
  96. textureFormat = alpha ? GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  97. size = ( MAX(width, 16) * MAX(height, 8) * 2 + 7) / 8;
  98. glCompressedTexImage2D(GL_TEXTURE_2D, level, textureFormat, width, height, 0, size, tex);
  99. break;
  100. case OGL_PVRTC4:
  101. textureFormat = alpha ? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  102. size = ( MAX(width, 8) * MAX(height, 8) * 4 + 7) / 8;
  103. glCompressedTexImage2D(GL_TEXTURE_2D, level, textureFormat, width, height, 0, size, tex);
  104. break;
  105. case OGL_RGBA_4444:
  106. size=width*height*2;
  107. glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, tex);
  108. break;
  109. case OGL_RGBA_8888:
  110. size=width*height*4;
  111. glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);
  112. break;
  113. default:
  114. break;
  115. }
  116. tex += size;
  117. }
  118. }
  119. GLuint loadTexture(const PVR_Texture_Header *pvr)
  120. {
  121. GLuint texName;
  122. glGenTextures(1, &texName);
  123. glBindTexture(GL_TEXTURE_2D, texName);
  124. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  125. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  126. // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  127. // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  128. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  129. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  130. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  131. pvrTexImage2D(pvr);
  132. return texName;
  133. }
  134. GLuint loadTexture(const char *filename)
  135. {
  136. printf("loading '%s'\n", filename);
  137. MemoryChunk m;
  138. const void *ptr=lockFile(filename, &m);
  139. if(!ptr) return 0;
  140. GLuint texName;
  141. unsigned int off=0;
  142. while(off<m.size)
  143. {
  144. PVR_Texture_Header *pvr=(PVR_Texture_Header*)((const char*)m.ptr+off);
  145. GLuint tn=loadTexture(pvr);
  146. if(off==0) texName=tn;
  147. off+=pvr->dwHeaderSize;
  148. off+=pvr->dwTextureDataSize;
  149. }
  150. unlockFile(&m);
  151. return texName;
  152. }