d07c171f |
1 | /* |
2 | Copyright (C) 2003 Rice1964 |
3 | |
4 | This program is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU General Public License |
6 | as published by the Free Software Foundation; either version 2 |
7 | of the License, or (at your option) any later version. |
8 | |
9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ |
18 | |
19 | #include <stdlib.h> |
20 | |
21 | #include "Config.h" |
22 | #include "Debugger.h" |
23 | #include "OGLDebug.h" |
24 | #include "OGLGraphicsContext.h" |
25 | #include "OGLTexture.h" |
26 | #include "TextureManager.h" |
27 | |
28 | #ifdef HAVE_GLES |
29 | #define GL_RGBA4 0x8056 |
30 | #endif |
31 | |
32 | COGLTexture::COGLTexture(uint32 dwWidth, uint32 dwHeight, TextureUsage usage) : |
33 | CTexture(dwWidth,dwHeight,usage), |
34 | m_glFmt(GL_RGBA) |
35 | { |
36 | // FIXME: If usage is AS_RENDER_TARGET, we need to create pbuffer instead of regular texture |
37 | |
38 | m_dwTextureFmt = TEXTURE_FMT_A8R8G8B8; // Always use 32bit to load texture |
39 | glGenTextures( 1, &m_dwTextureName ); |
40 | OPENGL_CHECK_ERRORS; |
41 | |
42 | // Make the width and height be the power of 2 |
43 | uint32 w; |
44 | for (w = 1; w < dwWidth; w <<= 1); |
45 | m_dwCreatedTextureWidth = w; |
46 | for (w = 1; w < dwHeight; w <<= 1); |
47 | m_dwCreatedTextureHeight = w; |
48 | |
49 | if (dwWidth*dwHeight > 256*256) |
50 | TRACE4("Large texture: (%d x %d), created as (%d x %d)", |
51 | dwWidth, dwHeight,m_dwCreatedTextureWidth,m_dwCreatedTextureHeight); |
52 | |
53 | m_fYScale = (float)m_dwCreatedTextureHeight/(float)m_dwHeight; |
54 | m_fXScale = (float)m_dwCreatedTextureWidth/(float)m_dwWidth; |
55 | |
56 | m_pTexture = malloc(m_dwCreatedTextureWidth * m_dwCreatedTextureHeight * GetPixelSize()); |
57 | //#ifndef HAVE_GLES |
58 | |
59 | switch( options.textureQuality ) |
60 | { |
61 | case TXT_QUALITY_DEFAULT: |
62 | if( options.colorQuality == TEXTURE_FMT_A4R4G4B4 ) |
63 | m_glFmt = GL_RGBA4; |
64 | break; |
65 | case TXT_QUALITY_32BIT: |
66 | break; |
67 | case TXT_QUALITY_16BIT: |
68 | m_glFmt = GL_RGBA4; |
69 | break; |
70 | }; |
71 | |
72 | //#endif |
73 | LOG_TEXTURE(TRACE2("New texture: (%d, %d)", dwWidth, dwHeight)); |
74 | } |
75 | |
76 | COGLTexture::~COGLTexture() |
77 | { |
78 | // FIXME: If usage is AS_RENDER_TARGET, we need to destroy the pbuffer |
79 | |
80 | glDeleteTextures(1, &m_dwTextureName ); |
81 | OPENGL_CHECK_ERRORS; |
82 | free(m_pTexture); |
83 | m_pTexture = NULL; |
84 | m_dwWidth = 0; |
85 | m_dwHeight = 0; |
86 | } |
87 | |
88 | bool COGLTexture::StartUpdate(DrawInfo *di) |
89 | { |
90 | if (m_pTexture == NULL) |
91 | return false; |
92 | |
93 | di->dwHeight = (uint16)m_dwHeight; |
94 | di->dwWidth = (uint16)m_dwWidth; |
95 | di->dwCreatedHeight = m_dwCreatedTextureHeight; |
96 | di->dwCreatedWidth = m_dwCreatedTextureWidth; |
97 | di->lpSurface = m_pTexture; |
98 | di->lPitch = GetPixelSize()*m_dwCreatedTextureWidth; |
99 | |
100 | return true; |
101 | } |
102 | |
103 | void COGLTexture::EndUpdate(DrawInfo *di) |
104 | { |
105 | COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext); // we need this to check if the GL extension is avaible |
106 | |
107 | glBindTexture(GL_TEXTURE_2D, m_dwTextureName); |
108 | OPENGL_CHECK_ERRORS; |
109 | |
110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
111 | OPENGL_CHECK_ERRORS; |
112 | |
113 | // mipmap support |
114 | if(options.mipmapping) |
115 | { |
116 | int m_maximumAnistropy = pcontext->getMaxAnisotropicFiltering(); //if getMaxAnisotropicFiltering() return more than 0, so aniso is supported and maxAnisotropicFiltering is set |
117 | |
118 | // Set Anisotropic filtering (mipmapping have to be activated, aniso filtering is not effective without) |
119 | if( m_maximumAnistropy ) |
120 | { |
121 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_maximumAnistropy); |
122 | OPENGL_CHECK_ERRORS; |
123 | } |
124 | |
125 | // Set Mipmap |
126 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); |
127 | OPENGL_CHECK_ERRORS; |
128 | |
129 | #if SDL_VIDEO_OPENGL |
130 | // Tell to hardware to generate mipmap (himself) when glTexImage2D is called |
131 | glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); |
132 | #elif SDL_VIDEO_OPENGL_ES2 |
133 | glGenerateMipmap(GL_TEXTURE_2D); |
134 | #endif |
135 | OPENGL_CHECK_ERRORS; |
136 | } |
137 | else |
138 | { |
139 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
140 | OPENGL_CHECK_ERRORS; |
141 | } |
142 | |
143 | // Copy the image data from main memory to video card texture memory |
144 | #if SDL_VIDEO_OPENGL |
145 | #ifdef HAVE_GLES |
146 | // first change format BGRA->RGBA and reduce bit if needed |
147 | unsigned char* m_glesTex; |
148 | if (m_glFmt == GL_RGBA4) { |
149 | m_glesTex = (unsigned char*)malloc(m_dwCreatedTextureHeight*m_dwCreatedTextureWidth*2); |
150 | unsigned short *p = (unsigned short*)m_glesTex; |
151 | unsigned char *f = (unsigned char*)m_pTexture; |
152 | for (int j=0; j<m_dwCreatedTextureHeight; j++) |
153 | for (int i=0; i<m_dwCreatedTextureWidth; i++) { |
154 | // *f = B, *(f+1) = G, *(f+2) = R, *(f+3) = A |
155 | // RRRR GGGG BBBB AAAA |
156 | *(p++)= ((*(f+2))&0xf0)>>4 | ((*(f+1))&0xf0) | (((*f))&0xf0)<<4 | ((*(f+3))&0xf0)<<8; |
157 | f+=4; |
158 | } |
159 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, m_glesTex); |
160 | } else { |
161 | m_glesTex = (unsigned char*)malloc(m_dwCreatedTextureHeight*m_dwCreatedTextureWidth*4); |
162 | unsigned int *p = (unsigned int*)m_glesTex; |
163 | unsigned char *f = (unsigned char*)m_pTexture; |
164 | for (int j=0; j<m_dwCreatedTextureHeight; j++) |
165 | for (int i=0; i<m_dwCreatedTextureWidth; i++) { |
166 | // *f = B, *(f+1) = G, *(f+2) = R, *(f+3) = A |
167 | // AAAAAAAA BBBBBBBB GGGGGGGG RRRRRRRR |
168 | *(p++)= ((*(f+2))) | ((*(f+1)))<<8 | ((*f))<<16 | ((*(f+3)))<<24; |
169 | f+=4; |
170 | } |
171 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_glesTex); |
172 | } |
173 | free(m_glesTex); |
174 | #else |
175 | glTexImage2D(GL_TEXTURE_2D, 0, m_glFmt, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_pTexture); |
176 | #endif |
177 | #elif SDL_VIDEO_OPENGL_ES2 |
178 | //GL_BGRA_IMG works on adreno but not inside profiler. |
179 | glTexImage2D(GL_TEXTURE_2D, 0, m_glFmt, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pTexture); |
180 | #endif |
181 | OPENGL_CHECK_ERRORS; |
182 | } |
183 | |
184 | |
185 | // Keep in mind that the real texture is not scaled to fix the created opengl texture yet. |
186 | // when the image is need to be scaled, ScaleImageToSurface in CTexure will be called to |
187 | // scale the image automatically |
188 | |