diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp | 1926 |
1 files changed, 963 insertions, 963 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp index 3cc41c0..b259071 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp | |||
@@ -1,963 +1,963 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "IrrCompileConfig.h" | 5 | #include "IrrCompileConfig.h" |
6 | 6 | ||
7 | #ifdef _IRR_COMPILE_WITH_OPENGL_ | 7 | #ifdef _IRR_COMPILE_WITH_OPENGL_ |
8 | 8 | ||
9 | #include "irrTypes.h" | 9 | #include "irrTypes.h" |
10 | #include "COpenGLTexture.h" | 10 | #include "COpenGLTexture.h" |
11 | #include "COpenGLDriver.h" | 11 | #include "COpenGLDriver.h" |
12 | #include "os.h" | 12 | #include "os.h" |
13 | #include "CColorConverter.h" | 13 | #include "CColorConverter.h" |
14 | 14 | ||
15 | #include "irrString.h" | 15 | #include "irrString.h" |
16 | 16 | ||
17 | namespace irr | 17 | namespace irr |
18 | { | 18 | { |
19 | namespace video | 19 | namespace video |
20 | { | 20 | { |
21 | 21 | ||
22 | //! constructor for usual textures | 22 | //! constructor for usual textures |
23 | COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) | 23 | COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) |
24 | : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), | 24 | : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), |
25 | TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), | 25 | TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), |
26 | PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true), | 26 | PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true), |
27 | IsRenderTarget(false), AutomaticMipmapUpdate(false), | 27 | IsRenderTarget(false), AutomaticMipmapUpdate(false), |
28 | ReadOnlyLock(false), KeepImage(true) | 28 | ReadOnlyLock(false), KeepImage(true) |
29 | { | 29 | { |
30 | #ifdef _DEBUG | 30 | #ifdef _DEBUG |
31 | setDebugName("COpenGLTexture"); | 31 | setDebugName("COpenGLTexture"); |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); | 34 | HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); |
35 | getImageValues(origImage); | 35 | getImageValues(origImage); |
36 | 36 | ||
37 | glGenTextures(1, &TextureName); | 37 | glGenTextures(1, &TextureName); |
38 | 38 | ||
39 | if (ImageSize==TextureSize) | 39 | if (ImageSize==TextureSize) |
40 | { | 40 | { |
41 | Image = Driver->createImage(ColorFormat, ImageSize); | 41 | Image = Driver->createImage(ColorFormat, ImageSize); |
42 | origImage->copyTo(Image); | 42 | origImage->copyTo(Image); |
43 | } | 43 | } |
44 | else | 44 | else |
45 | { | 45 | { |
46 | Image = Driver->createImage(ColorFormat, TextureSize); | 46 | Image = Driver->createImage(ColorFormat, TextureSize); |
47 | // scale texture | 47 | // scale texture |
48 | origImage->copyToScaling(Image); | 48 | origImage->copyToScaling(Image); |
49 | } | 49 | } |
50 | uploadTexture(true, mipmapData); | 50 | uploadTexture(true, mipmapData); |
51 | if (!KeepImage) | 51 | if (!KeepImage) |
52 | { | 52 | { |
53 | Image->drop(); | 53 | Image->drop(); |
54 | Image=0; | 54 | Image=0; |
55 | } | 55 | } |
56 | } | 56 | } |
57 | 57 | ||
58 | 58 | ||
59 | //! constructor for basic setup (only for derived classes) | 59 | //! constructor for basic setup (only for derived classes) |
60 | COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) | 60 | COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) |
61 | : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), | 61 | : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), |
62 | TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), | 62 | TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), |
63 | PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true), | 63 | PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true), |
64 | MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), | 64 | MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), |
65 | ReadOnlyLock(false), KeepImage(true) | 65 | ReadOnlyLock(false), KeepImage(true) |
66 | { | 66 | { |
67 | #ifdef _DEBUG | 67 | #ifdef _DEBUG |
68 | setDebugName("COpenGLTexture"); | 68 | setDebugName("COpenGLTexture"); |
69 | #endif | 69 | #endif |
70 | } | 70 | } |
71 | 71 | ||
72 | 72 | ||
73 | //! destructor | 73 | //! destructor |
74 | COpenGLTexture::~COpenGLTexture() | 74 | COpenGLTexture::~COpenGLTexture() |
75 | { | 75 | { |
76 | if (TextureName) | 76 | if (TextureName) |
77 | glDeleteTextures(1, &TextureName); | 77 | glDeleteTextures(1, &TextureName); |
78 | if (Image) | 78 | if (Image) |
79 | Image->drop(); | 79 | Image->drop(); |
80 | } | 80 | } |
81 | 81 | ||
82 | 82 | ||
83 | //! Choose best matching color format, based on texture creation flags | 83 | //! Choose best matching color format, based on texture creation flags |
84 | ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) | 84 | ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) |
85 | { | 85 | { |
86 | ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; | 86 | ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; |
87 | switch (format) | 87 | switch (format) |
88 | { | 88 | { |
89 | case ECF_A1R5G5B5: | 89 | case ECF_A1R5G5B5: |
90 | if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) | 90 | if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) |
91 | destFormat = ECF_A1R5G5B5; | 91 | destFormat = ECF_A1R5G5B5; |
92 | break; | 92 | break; |
93 | case ECF_R5G6B5: | 93 | case ECF_R5G6B5: |
94 | if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) | 94 | if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) |
95 | destFormat = ECF_A1R5G5B5; | 95 | destFormat = ECF_A1R5G5B5; |
96 | break; | 96 | break; |
97 | case ECF_A8R8G8B8: | 97 | case ECF_A8R8G8B8: |
98 | if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || | 98 | if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || |
99 | Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) | 99 | Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) |
100 | destFormat = ECF_A1R5G5B5; | 100 | destFormat = ECF_A1R5G5B5; |
101 | break; | 101 | break; |
102 | case ECF_R8G8B8: | 102 | case ECF_R8G8B8: |
103 | if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || | 103 | if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || |
104 | Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) | 104 | Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) |
105 | destFormat = ECF_A1R5G5B5; | 105 | destFormat = ECF_A1R5G5B5; |
106 | default: | 106 | default: |
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL)) | 109 | if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL)) |
110 | { | 110 | { |
111 | switch (destFormat) | 111 | switch (destFormat) |
112 | { | 112 | { |
113 | case ECF_A1R5G5B5: | 113 | case ECF_A1R5G5B5: |
114 | destFormat = ECF_R5G6B5; | 114 | destFormat = ECF_R5G6B5; |
115 | break; | 115 | break; |
116 | case ECF_A8R8G8B8: | 116 | case ECF_A8R8G8B8: |
117 | destFormat = ECF_R8G8B8; | 117 | destFormat = ECF_R8G8B8; |
118 | break; | 118 | break; |
119 | default: | 119 | default: |
120 | break; | 120 | break; |
121 | } | 121 | } |
122 | } | 122 | } |
123 | return destFormat; | 123 | return destFormat; |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | //! Get opengl values for the GPU texture storage | 127 | //! Get opengl values for the GPU texture storage |
128 | GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, | 128 | GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, |
129 | GLint& filtering, | 129 | GLint& filtering, |
130 | GLenum& colorformat, | 130 | GLenum& colorformat, |
131 | GLenum& type) | 131 | GLenum& type) |
132 | { | 132 | { |
133 | // default | 133 | // default |
134 | filtering = GL_LINEAR; | 134 | filtering = GL_LINEAR; |
135 | colorformat = GL_RGBA; | 135 | colorformat = GL_RGBA; |
136 | type = GL_UNSIGNED_BYTE; | 136 | type = GL_UNSIGNED_BYTE; |
137 | GLenum internalformat = GL_RGBA; | 137 | GLenum internalformat = GL_RGBA; |
138 | 138 | ||
139 | switch(format) | 139 | switch(format) |
140 | { | 140 | { |
141 | case ECF_A1R5G5B5: | 141 | case ECF_A1R5G5B5: |
142 | colorformat=GL_BGRA_EXT; | 142 | colorformat=GL_BGRA_EXT; |
143 | type=GL_UNSIGNED_SHORT_1_5_5_5_REV; | 143 | type=GL_UNSIGNED_SHORT_1_5_5_5_REV; |
144 | internalformat = GL_RGBA; | 144 | internalformat = GL_RGBA; |
145 | break; | 145 | break; |
146 | case ECF_R5G6B5: | 146 | case ECF_R5G6B5: |
147 | colorformat=GL_RGB; | 147 | colorformat=GL_RGB; |
148 | type=GL_UNSIGNED_SHORT_5_6_5; | 148 | type=GL_UNSIGNED_SHORT_5_6_5; |
149 | internalformat = GL_RGB; | 149 | internalformat = GL_RGB; |
150 | break; | 150 | break; |
151 | case ECF_R8G8B8: | 151 | case ECF_R8G8B8: |
152 | colorformat=GL_BGR; | 152 | colorformat=GL_BGR; |
153 | type=GL_UNSIGNED_BYTE; | 153 | type=GL_UNSIGNED_BYTE; |
154 | internalformat = GL_RGB; | 154 | internalformat = GL_RGB; |
155 | break; | 155 | break; |
156 | case ECF_A8R8G8B8: | 156 | case ECF_A8R8G8B8: |
157 | colorformat=GL_BGRA_EXT; | 157 | colorformat=GL_BGRA_EXT; |
158 | if (Driver->Version > 101) | 158 | if (Driver->Version > 101) |
159 | type=GL_UNSIGNED_INT_8_8_8_8_REV; | 159 | type=GL_UNSIGNED_INT_8_8_8_8_REV; |
160 | internalformat = GL_RGBA; | 160 | internalformat = GL_RGBA; |
161 | break; | 161 | break; |
162 | // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. | 162 | // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. |
163 | case ECF_R16F: | 163 | case ECF_R16F: |
164 | { | 164 | { |
165 | #ifdef GL_ARB_texture_rg | 165 | #ifdef GL_ARB_texture_rg |
166 | filtering = GL_NEAREST; | 166 | filtering = GL_NEAREST; |
167 | colorformat = GL_RED; | 167 | colorformat = GL_RED; |
168 | type = GL_FLOAT; | 168 | type = GL_FLOAT; |
169 | 169 | ||
170 | internalformat = GL_R16F; | 170 | internalformat = GL_R16F; |
171 | #else | 171 | #else |
172 | ColorFormat = ECF_A8R8G8B8; | 172 | ColorFormat = ECF_A8R8G8B8; |
173 | internalformat = GL_RGB8; | 173 | internalformat = GL_RGB8; |
174 | #endif | 174 | #endif |
175 | } | 175 | } |
176 | break; | 176 | break; |
177 | case ECF_G16R16F: | 177 | case ECF_G16R16F: |
178 | { | 178 | { |
179 | #ifdef GL_ARB_texture_rg | 179 | #ifdef GL_ARB_texture_rg |
180 | filtering = GL_NEAREST; | 180 | filtering = GL_NEAREST; |
181 | colorformat = GL_RG; | 181 | colorformat = GL_RG; |
182 | type = GL_FLOAT; | 182 | type = GL_FLOAT; |
183 | 183 | ||
184 | internalformat = GL_RG16F; | 184 | internalformat = GL_RG16F; |
185 | #else | 185 | #else |
186 | ColorFormat = ECF_A8R8G8B8; | 186 | ColorFormat = ECF_A8R8G8B8; |
187 | internalformat = GL_RGB8; | 187 | internalformat = GL_RGB8; |
188 | #endif | 188 | #endif |
189 | } | 189 | } |
190 | break; | 190 | break; |
191 | case ECF_A16B16G16R16F: | 191 | case ECF_A16B16G16R16F: |
192 | { | 192 | { |
193 | #ifdef GL_ARB_texture_rg | 193 | #ifdef GL_ARB_texture_rg |
194 | filtering = GL_NEAREST; | 194 | filtering = GL_NEAREST; |
195 | colorformat = GL_RGBA; | 195 | colorformat = GL_RGBA; |
196 | type = GL_FLOAT; | 196 | type = GL_FLOAT; |
197 | 197 | ||
198 | internalformat = GL_RGBA16F_ARB; | 198 | internalformat = GL_RGBA16F_ARB; |
199 | #else | 199 | #else |
200 | ColorFormat = ECF_A8R8G8B8; | 200 | ColorFormat = ECF_A8R8G8B8; |
201 | internalformat = GL_RGBA8; | 201 | internalformat = GL_RGBA8; |
202 | #endif | 202 | #endif |
203 | } | 203 | } |
204 | break; | 204 | break; |
205 | case ECF_R32F: | 205 | case ECF_R32F: |
206 | { | 206 | { |
207 | #ifdef GL_ARB_texture_rg | 207 | #ifdef GL_ARB_texture_rg |
208 | filtering = GL_NEAREST; | 208 | filtering = GL_NEAREST; |
209 | colorformat = GL_RED; | 209 | colorformat = GL_RED; |
210 | type = GL_FLOAT; | 210 | type = GL_FLOAT; |
211 | 211 | ||
212 | internalformat = GL_R32F; | 212 | internalformat = GL_R32F; |
213 | #else | 213 | #else |
214 | ColorFormat = ECF_A8R8G8B8; | 214 | ColorFormat = ECF_A8R8G8B8; |
215 | internalformat = GL_RGB8; | 215 | internalformat = GL_RGB8; |
216 | #endif | 216 | #endif |
217 | } | 217 | } |
218 | break; | 218 | break; |
219 | case ECF_G32R32F: | 219 | case ECF_G32R32F: |
220 | { | 220 | { |
221 | #ifdef GL_ARB_texture_rg | 221 | #ifdef GL_ARB_texture_rg |
222 | filtering = GL_NEAREST; | 222 | filtering = GL_NEAREST; |
223 | colorformat = GL_RG; | 223 | colorformat = GL_RG; |
224 | type = GL_FLOAT; | 224 | type = GL_FLOAT; |
225 | 225 | ||
226 | internalformat = GL_RG32F; | 226 | internalformat = GL_RG32F; |
227 | #else | 227 | #else |
228 | ColorFormat = ECF_A8R8G8B8; | 228 | ColorFormat = ECF_A8R8G8B8; |
229 | internalformat = GL_RGB8; | 229 | internalformat = GL_RGB8; |
230 | #endif | 230 | #endif |
231 | } | 231 | } |
232 | break; | 232 | break; |
233 | case ECF_A32B32G32R32F: | 233 | case ECF_A32B32G32R32F: |
234 | { | 234 | { |
235 | #ifdef GL_ARB_texture_float | 235 | #ifdef GL_ARB_texture_float |
236 | filtering = GL_NEAREST; | 236 | filtering = GL_NEAREST; |
237 | colorformat = GL_RGBA; | 237 | colorformat = GL_RGBA; |
238 | type = GL_FLOAT; | 238 | type = GL_FLOAT; |
239 | 239 | ||
240 | internalformat = GL_RGBA32F_ARB; | 240 | internalformat = GL_RGBA32F_ARB; |
241 | #else | 241 | #else |
242 | ColorFormat = ECF_A8R8G8B8; | 242 | ColorFormat = ECF_A8R8G8B8; |
243 | internalformat = GL_RGBA8; | 243 | internalformat = GL_RGBA8; |
244 | #endif | 244 | #endif |
245 | } | 245 | } |
246 | break; | 246 | break; |
247 | default: | 247 | default: |
248 | { | 248 | { |
249 | os::Printer::log("Unsupported texture format", ELL_ERROR); | 249 | os::Printer::log("Unsupported texture format", ELL_ERROR); |
250 | internalformat = GL_RGBA8; | 250 | internalformat = GL_RGBA8; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | #if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) | 253 | #if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) |
254 | if (Driver->Params.HandleSRGB) | 254 | if (Driver->Params.HandleSRGB) |
255 | { | 255 | { |
256 | if (internalformat==GL_RGBA) | 256 | if (internalformat==GL_RGBA) |
257 | internalformat=GL_SRGB_ALPHA_EXT; | 257 | internalformat=GL_SRGB_ALPHA_EXT; |
258 | else if (internalformat==GL_RGB) | 258 | else if (internalformat==GL_RGB) |
259 | internalformat=GL_SRGB_EXT; | 259 | internalformat=GL_SRGB_EXT; |
260 | } | 260 | } |
261 | #endif | 261 | #endif |
262 | return internalformat; | 262 | return internalformat; |
263 | } | 263 | } |
264 | 264 | ||
265 | 265 | ||
266 | // prepare values ImageSize, TextureSize, and ColorFormat based on image | 266 | // prepare values ImageSize, TextureSize, and ColorFormat based on image |
267 | void COpenGLTexture::getImageValues(IImage* image) | 267 | void COpenGLTexture::getImageValues(IImage* image) |
268 | { | 268 | { |
269 | if (!image) | 269 | if (!image) |
270 | { | 270 | { |
271 | os::Printer::log("No image for OpenGL texture.", ELL_ERROR); | 271 | os::Printer::log("No image for OpenGL texture.", ELL_ERROR); |
272 | return; | 272 | return; |
273 | } | 273 | } |
274 | 274 | ||
275 | ImageSize = image->getDimension(); | 275 | ImageSize = image->getDimension(); |
276 | 276 | ||
277 | if ( !ImageSize.Width || !ImageSize.Height) | 277 | if ( !ImageSize.Width || !ImageSize.Height) |
278 | { | 278 | { |
279 | os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR); | 279 | os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR); |
280 | return; | 280 | return; |
281 | } | 281 | } |
282 | 282 | ||
283 | const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height; | 283 | const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height; |
284 | if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f)) | 284 | if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f)) |
285 | { | 285 | { |
286 | ImageSize.Width = Driver->MaxTextureSize; | 286 | ImageSize.Width = Driver->MaxTextureSize; |
287 | ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio); | 287 | ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio); |
288 | } | 288 | } |
289 | else if (ImageSize.Height>Driver->MaxTextureSize) | 289 | else if (ImageSize.Height>Driver->MaxTextureSize) |
290 | { | 290 | { |
291 | ImageSize.Height = Driver->MaxTextureSize; | 291 | ImageSize.Height = Driver->MaxTextureSize; |
292 | ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio); | 292 | ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio); |
293 | } | 293 | } |
294 | TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT)); | 294 | TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT)); |
295 | 295 | ||
296 | ColorFormat = getBestColorFormat(image->getColorFormat()); | 296 | ColorFormat = getBestColorFormat(image->getColorFormat()); |
297 | } | 297 | } |
298 | 298 | ||
299 | 299 | ||
300 | //! copies the the texture into an open gl texture. | 300 | //! copies the the texture into an open gl texture. |
301 | void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) | 301 | void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) |
302 | { | 302 | { |
303 | // check which image needs to be uploaded | 303 | // check which image needs to be uploaded |
304 | IImage* image = level?MipImage:Image; | 304 | IImage* image = level?MipImage:Image; |
305 | if (!image) | 305 | if (!image) |
306 | { | 306 | { |
307 | os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); | 307 | os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); |
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | 310 | ||
311 | // get correct opengl color data values | 311 | // get correct opengl color data values |
312 | GLenum oldInternalFormat = InternalFormat; | 312 | GLenum oldInternalFormat = InternalFormat; |
313 | GLint filtering; | 313 | GLint filtering; |
314 | InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); | 314 | InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); |
315 | // make sure we don't change the internal format of existing images | 315 | // make sure we don't change the internal format of existing images |
316 | if (!newTexture) | 316 | if (!newTexture) |
317 | InternalFormat=oldInternalFormat; | 317 | InternalFormat=oldInternalFormat; |
318 | 318 | ||
319 | Driver->setActiveTexture(0, this); | 319 | Driver->setActiveTexture(0, this); |
320 | if (Driver->testGLError()) | 320 | if (Driver->testGLError()) |
321 | os::Printer::log("Could not bind Texture", ELL_ERROR); | 321 | os::Printer::log("Could not bind Texture", ELL_ERROR); |
322 | 322 | ||
323 | // mipmap handling for main texture | 323 | // mipmap handling for main texture |
324 | if (!level && newTexture) | 324 | if (!level && newTexture) |
325 | { | 325 | { |
326 | #ifndef DISABLE_MIPMAPPING | 326 | #ifndef DISABLE_MIPMAPPING |
327 | #ifdef GL_SGIS_generate_mipmap | 327 | #ifdef GL_SGIS_generate_mipmap |
328 | // auto generate if possible and no mipmap data is given | 328 | // auto generate if possible and no mipmap data is given |
329 | if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) | 329 | if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) |
330 | { | 330 | { |
331 | if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) | 331 | if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) |
332 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); | 332 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); |
333 | else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) | 333 | else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) |
334 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); | 334 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); |
335 | else | 335 | else |
336 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE); | 336 | glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE); |
337 | 337 | ||
338 | AutomaticMipmapUpdate=true; | 338 | AutomaticMipmapUpdate=true; |
339 | 339 | ||
340 | if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT)) | 340 | if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT)) |
341 | { | 341 | { |
342 | glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); | 342 | glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); |
343 | MipmapLegacyMode=true; | 343 | MipmapLegacyMode=true; |
344 | } | 344 | } |
345 | else | 345 | else |
346 | MipmapLegacyMode=false; | 346 | MipmapLegacyMode=false; |
347 | } | 347 | } |
348 | else | 348 | else |
349 | #endif | 349 | #endif |
350 | { | 350 | { |
351 | // Either generate manually due to missing capability | 351 | // Either generate manually due to missing capability |
352 | // or use predefined mipmap data | 352 | // or use predefined mipmap data |
353 | AutomaticMipmapUpdate=false; | 353 | AutomaticMipmapUpdate=false; |
354 | regenerateMipMapLevels(mipmapData); | 354 | regenerateMipMapLevels(mipmapData); |
355 | } | 355 | } |
356 | if (HasMipMaps) // might have changed in regenerateMipMapLevels | 356 | if (HasMipMaps) // might have changed in regenerateMipMapLevels |
357 | { | 357 | { |
358 | // enable bilinear mipmap filter | 358 | // enable bilinear mipmap filter |
359 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); | 359 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); |
360 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 360 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
361 | } | 361 | } |
362 | else | 362 | else |
363 | #else | 363 | #else |
364 | HasMipMaps=false; | 364 | HasMipMaps=false; |
365 | os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); | 365 | os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); |
366 | #endif | 366 | #endif |
367 | { | 367 | { |
368 | // enable bilinear filter without mipmaps | 368 | // enable bilinear filter without mipmaps |
369 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 369 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
370 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 370 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
371 | } | 371 | } |
372 | } | 372 | } |
373 | 373 | ||
374 | // now get image data and upload to GPU | 374 | // now get image data and upload to GPU |
375 | void* source = image->lock(); | 375 | void* source = image->lock(); |
376 | if (newTexture) | 376 | if (newTexture) |
377 | glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, | 377 | glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, |
378 | image->getDimension().Height, 0, PixelFormat, PixelType, source); | 378 | image->getDimension().Height, 0, PixelFormat, PixelType, source); |
379 | else | 379 | else |
380 | glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, | 380 | glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, |
381 | image->getDimension().Height, PixelFormat, PixelType, source); | 381 | image->getDimension().Height, PixelFormat, PixelType, source); |
382 | image->unlock(); | 382 | image->unlock(); |
383 | 383 | ||
384 | if (!MipmapLegacyMode && AutomaticMipmapUpdate) | 384 | if (!MipmapLegacyMode && AutomaticMipmapUpdate) |
385 | { | 385 | { |
386 | glEnable(GL_TEXTURE_2D); | 386 | glEnable(GL_TEXTURE_2D); |
387 | Driver->extGlGenerateMipmap(GL_TEXTURE_2D); | 387 | Driver->extGlGenerateMipmap(GL_TEXTURE_2D); |
388 | } | 388 | } |
389 | 389 | ||
390 | if (Driver->testGLError()) | 390 | if (Driver->testGLError()) |
391 | os::Printer::log("Could not glTexImage2D", ELL_ERROR); | 391 | os::Printer::log("Could not glTexImage2D", ELL_ERROR); |
392 | } | 392 | } |
393 | 393 | ||
394 | 394 | ||
395 | //! lock function | 395 | //! lock function |
396 | void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) | 396 | void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) |
397 | { | 397 | { |
398 | // store info about which image is locked | 398 | // store info about which image is locked |
399 | IImage* image = (mipmapLevel==0)?Image:MipImage; | 399 | IImage* image = (mipmapLevel==0)?Image:MipImage; |
400 | ReadOnlyLock |= (mode==ETLM_READ_ONLY); | 400 | ReadOnlyLock |= (mode==ETLM_READ_ONLY); |
401 | MipLevelStored = mipmapLevel; | 401 | MipLevelStored = mipmapLevel; |
402 | if (!ReadOnlyLock && mipmapLevel) | 402 | if (!ReadOnlyLock && mipmapLevel) |
403 | { | 403 | { |
404 | #ifdef GL_SGIS_generate_mipmap | 404 | #ifdef GL_SGIS_generate_mipmap |
405 | if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) | 405 | if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) |
406 | { | 406 | { |
407 | // do not automatically generate and update mipmaps | 407 | // do not automatically generate and update mipmaps |
408 | glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); | 408 | glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); |
409 | } | 409 | } |
410 | #endif | 410 | #endif |
411 | AutomaticMipmapUpdate=false; | 411 | AutomaticMipmapUpdate=false; |
412 | } | 412 | } |
413 | 413 | ||
414 | // if data not available or might have changed on GPU download it | 414 | // if data not available or might have changed on GPU download it |
415 | if (!image || IsRenderTarget) | 415 | if (!image || IsRenderTarget) |
416 | { | 416 | { |
417 | // prepare the data storage if necessary | 417 | // prepare the data storage if necessary |
418 | if (!image) | 418 | if (!image) |
419 | { | 419 | { |
420 | if (mipmapLevel) | 420 | if (mipmapLevel) |
421 | { | 421 | { |
422 | u32 i=0; | 422 | u32 i=0; |
423 | u32 width = TextureSize.Width; | 423 | u32 width = TextureSize.Width; |
424 | u32 height = TextureSize.Height; | 424 | u32 height = TextureSize.Height; |
425 | do | 425 | do |
426 | { | 426 | { |
427 | if (width>1) | 427 | if (width>1) |
428 | width>>=1; | 428 | width>>=1; |
429 | if (height>1) | 429 | if (height>1) |
430 | height>>=1; | 430 | height>>=1; |
431 | ++i; | 431 | ++i; |
432 | } | 432 | } |
433 | while (i != mipmapLevel); | 433 | while (i != mipmapLevel); |
434 | MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height)); | 434 | MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height)); |
435 | } | 435 | } |
436 | else | 436 | else |
437 | Image = image = Driver->createImage(ECF_A8R8G8B8, ImageSize); | 437 | Image = image = Driver->createImage(ECF_A8R8G8B8, ImageSize); |
438 | ColorFormat = ECF_A8R8G8B8; | 438 | ColorFormat = ECF_A8R8G8B8; |
439 | } | 439 | } |
440 | if (!image) | 440 | if (!image) |
441 | return 0; | 441 | return 0; |
442 | 442 | ||
443 | if (mode != ETLM_WRITE_ONLY) | 443 | if (mode != ETLM_WRITE_ONLY) |
444 | { | 444 | { |
445 | u8* pixels = static_cast<u8*>(image->lock()); | 445 | u8* pixels = static_cast<u8*>(image->lock()); |
446 | if (!pixels) | 446 | if (!pixels) |
447 | return 0; | 447 | return 0; |
448 | 448 | ||
449 | // we need to keep the correct texture bound later on | 449 | // we need to keep the correct texture bound later on |
450 | GLint tmpTexture; | 450 | GLint tmpTexture; |
451 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); | 451 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); |
452 | glBindTexture(GL_TEXTURE_2D, TextureName); | 452 | glBindTexture(GL_TEXTURE_2D, TextureName); |
453 | 453 | ||
454 | // we need to flip textures vertical | 454 | // we need to flip textures vertical |
455 | // however, it seems that this does not hold for mipmap | 455 | // however, it seems that this does not hold for mipmap |
456 | // textures, for unknown reasons. | 456 | // textures, for unknown reasons. |
457 | 457 | ||
458 | // allows to read pixels in top-to-bottom order | 458 | // allows to read pixels in top-to-bottom order |
459 | #ifdef GL_MESA_pack_invert | 459 | #ifdef GL_MESA_pack_invert |
460 | if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) | 460 | if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) |
461 | glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); | 461 | glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); |
462 | #endif | 462 | #endif |
463 | 463 | ||
464 | // download GPU data as ARGB8 to pixels; | 464 | // download GPU data as ARGB8 to pixels; |
465 | glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); | 465 | glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); |
466 | 466 | ||
467 | if (!mipmapLevel) | 467 | if (!mipmapLevel) |
468 | { | 468 | { |
469 | #ifdef GL_MESA_pack_invert | 469 | #ifdef GL_MESA_pack_invert |
470 | if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) | 470 | if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) |
471 | glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); | 471 | glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); |
472 | else | 472 | else |
473 | #endif | 473 | #endif |
474 | { | 474 | { |
475 | // opengl images are horizontally flipped, so we have to fix that here. | 475 | // opengl images are horizontally flipped, so we have to fix that here. |
476 | const s32 pitch=image->getPitch(); | 476 | const s32 pitch=image->getPitch(); |
477 | u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; | 477 | u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; |
478 | u8* tmpBuffer = new u8[pitch]; | 478 | u8* tmpBuffer = new u8[pitch]; |
479 | for (u32 i=0; i < image->getDimension().Height; i += 2) | 479 | for (u32 i=0; i < image->getDimension().Height; i += 2) |
480 | { | 480 | { |
481 | memcpy(tmpBuffer, pixels, pitch); | 481 | memcpy(tmpBuffer, pixels, pitch); |
482 | memcpy(pixels, p2, pitch); | 482 | memcpy(pixels, p2, pitch); |
483 | memcpy(p2, tmpBuffer, pitch); | 483 | memcpy(p2, tmpBuffer, pitch); |
484 | pixels += pitch; | 484 | pixels += pitch; |
485 | p2 -= pitch; | 485 | p2 -= pitch; |
486 | } | 486 | } |
487 | delete [] tmpBuffer; | 487 | delete [] tmpBuffer; |
488 | } | 488 | } |
489 | } | 489 | } |
490 | image->unlock(); | 490 | image->unlock(); |
491 | 491 | ||
492 | //reset old bound texture | 492 | //reset old bound texture |
493 | glBindTexture(GL_TEXTURE_2D, tmpTexture); | 493 | glBindTexture(GL_TEXTURE_2D, tmpTexture); |
494 | } | 494 | } |
495 | } | 495 | } |
496 | return image->lock(); | 496 | return image->lock(); |
497 | } | 497 | } |
498 | 498 | ||
499 | 499 | ||
500 | //! unlock function | 500 | //! unlock function |
501 | void COpenGLTexture::unlock() | 501 | void COpenGLTexture::unlock() |
502 | { | 502 | { |
503 | // test if miplevel or main texture was locked | 503 | // test if miplevel or main texture was locked |
504 | IImage* image = MipImage?MipImage:Image; | 504 | IImage* image = MipImage?MipImage:Image; |
505 | if (!image) | 505 | if (!image) |
506 | return; | 506 | return; |
507 | // unlock image to see changes | 507 | // unlock image to see changes |
508 | image->unlock(); | 508 | image->unlock(); |
509 | // copy texture data to GPU | 509 | // copy texture data to GPU |
510 | if (!ReadOnlyLock) | 510 | if (!ReadOnlyLock) |
511 | uploadTexture(false, 0, MipLevelStored); | 511 | uploadTexture(false, 0, MipLevelStored); |
512 | ReadOnlyLock = false; | 512 | ReadOnlyLock = false; |
513 | // cleanup local image | 513 | // cleanup local image |
514 | if (MipImage) | 514 | if (MipImage) |
515 | { | 515 | { |
516 | MipImage->drop(); | 516 | MipImage->drop(); |
517 | MipImage=0; | 517 | MipImage=0; |
518 | } | 518 | } |
519 | else if (!KeepImage) | 519 | else if (!KeepImage) |
520 | { | 520 | { |
521 | Image->drop(); | 521 | Image->drop(); |
522 | Image=0; | 522 | Image=0; |
523 | } | 523 | } |
524 | // update information | 524 | // update information |
525 | if (Image) | 525 | if (Image) |
526 | ColorFormat=Image->getColorFormat(); | 526 | ColorFormat=Image->getColorFormat(); |
527 | else | 527 | else |
528 | ColorFormat=ECF_A8R8G8B8; | 528 | ColorFormat=ECF_A8R8G8B8; |
529 | } | 529 | } |
530 | 530 | ||
531 | 531 | ||
532 | //! Returns size of the original image. | 532 | //! Returns size of the original image. |
533 | const core::dimension2d<u32>& COpenGLTexture::getOriginalSize() const | 533 | const core::dimension2d<u32>& COpenGLTexture::getOriginalSize() const |
534 | { | 534 | { |
535 | return ImageSize; | 535 | return ImageSize; |
536 | } | 536 | } |
537 | 537 | ||
538 | 538 | ||
539 | //! Returns size of the texture. | 539 | //! Returns size of the texture. |
540 | const core::dimension2d<u32>& COpenGLTexture::getSize() const | 540 | const core::dimension2d<u32>& COpenGLTexture::getSize() const |
541 | { | 541 | { |
542 | return TextureSize; | 542 | return TextureSize; |
543 | } | 543 | } |
544 | 544 | ||
545 | 545 | ||
546 | //! returns driver type of texture, i.e. the driver, which created the texture | 546 | //! returns driver type of texture, i.e. the driver, which created the texture |
547 | E_DRIVER_TYPE COpenGLTexture::getDriverType() const | 547 | E_DRIVER_TYPE COpenGLTexture::getDriverType() const |
548 | { | 548 | { |
549 | return EDT_OPENGL; | 549 | return EDT_OPENGL; |
550 | } | 550 | } |
551 | 551 | ||
552 | 552 | ||
553 | //! returns color format of texture | 553 | //! returns color format of texture |
554 | ECOLOR_FORMAT COpenGLTexture::getColorFormat() const | 554 | ECOLOR_FORMAT COpenGLTexture::getColorFormat() const |
555 | { | 555 | { |
556 | return ColorFormat; | 556 | return ColorFormat; |
557 | } | 557 | } |
558 | 558 | ||
559 | 559 | ||
560 | //! returns pitch of texture (in bytes) | 560 | //! returns pitch of texture (in bytes) |
561 | u32 COpenGLTexture::getPitch() const | 561 | u32 COpenGLTexture::getPitch() const |
562 | { | 562 | { |
563 | if (Image) | 563 | if (Image) |
564 | return Image->getPitch(); | 564 | return Image->getPitch(); |
565 | else | 565 | else |
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
568 | 568 | ||
569 | 569 | ||
570 | //! return open gl texture name | 570 | //! return open gl texture name |
571 | GLuint COpenGLTexture::getOpenGLTextureName() const | 571 | GLuint COpenGLTexture::getOpenGLTextureName() const |
572 | { | 572 | { |
573 | return TextureName; | 573 | return TextureName; |
574 | } | 574 | } |
575 | 575 | ||
576 | 576 | ||
577 | //! Returns whether this texture has mipmaps | 577 | //! Returns whether this texture has mipmaps |
578 | bool COpenGLTexture::hasMipMaps() const | 578 | bool COpenGLTexture::hasMipMaps() const |
579 | { | 579 | { |
580 | return HasMipMaps; | 580 | return HasMipMaps; |
581 | } | 581 | } |
582 | 582 | ||
583 | 583 | ||
584 | //! Regenerates the mip map levels of the texture. Useful after locking and | 584 | //! Regenerates the mip map levels of the texture. Useful after locking and |
585 | //! modifying the texture | 585 | //! modifying the texture |
586 | void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) | 586 | void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) |
587 | { | 587 | { |
588 | if (AutomaticMipmapUpdate || !HasMipMaps || !Image) | 588 | if (AutomaticMipmapUpdate || !HasMipMaps || !Image) |
589 | return; | 589 | return; |
590 | if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) | 590 | if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) |
591 | return; | 591 | return; |
592 | 592 | ||
593 | // Manually create mipmaps or use prepared version | 593 | // Manually create mipmaps or use prepared version |
594 | u32 width=Image->getDimension().Width; | 594 | u32 width=Image->getDimension().Width; |
595 | u32 height=Image->getDimension().Height; | 595 | u32 height=Image->getDimension().Height; |
596 | u32 i=0; | 596 | u32 i=0; |
597 | u8* target = static_cast<u8*>(mipmapData); | 597 | u8* target = static_cast<u8*>(mipmapData); |
598 | do | 598 | do |
599 | { | 599 | { |
600 | if (width>1) | 600 | if (width>1) |
601 | width>>=1; | 601 | width>>=1; |
602 | if (height>1) | 602 | if (height>1) |
603 | height>>=1; | 603 | height>>=1; |
604 | ++i; | 604 | ++i; |
605 | if (!target) | 605 | if (!target) |
606 | target = new u8[width*height*Image->getBytesPerPixel()]; | 606 | target = new u8[width*height*Image->getBytesPerPixel()]; |
607 | // create scaled version if no mipdata available | 607 | // create scaled version if no mipdata available |
608 | if (!mipmapData) | 608 | if (!mipmapData) |
609 | Image->copyToScaling(target, width, height, Image->getColorFormat()); | 609 | Image->copyToScaling(target, width, height, Image->getColorFormat()); |
610 | glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, | 610 | glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, |
611 | 0, PixelFormat, PixelType, target); | 611 | 0, PixelFormat, PixelType, target); |
612 | // get next prepared mipmap data if available | 612 | // get next prepared mipmap data if available |
613 | if (mipmapData) | 613 | if (mipmapData) |
614 | { | 614 | { |
615 | mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel(); | 615 | mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel(); |
616 | target = static_cast<u8*>(mipmapData); | 616 | target = static_cast<u8*>(mipmapData); |
617 | } | 617 | } |
618 | } | 618 | } |
619 | while (width!=1 || height!=1); | 619 | while (width!=1 || height!=1); |
620 | // cleanup | 620 | // cleanup |
621 | if (!mipmapData) | 621 | if (!mipmapData) |
622 | delete [] target; | 622 | delete [] target; |
623 | } | 623 | } |
624 | 624 | ||
625 | 625 | ||
626 | bool COpenGLTexture::isRenderTarget() const | 626 | bool COpenGLTexture::isRenderTarget() const |
627 | { | 627 | { |
628 | return IsRenderTarget; | 628 | return IsRenderTarget; |
629 | } | 629 | } |
630 | 630 | ||
631 | 631 | ||
632 | void COpenGLTexture::setIsRenderTarget(bool isTarget) | 632 | void COpenGLTexture::setIsRenderTarget(bool isTarget) |
633 | { | 633 | { |
634 | IsRenderTarget = isTarget; | 634 | IsRenderTarget = isTarget; |
635 | } | 635 | } |
636 | 636 | ||
637 | 637 | ||
638 | bool COpenGLTexture::isFrameBufferObject() const | 638 | bool COpenGLTexture::isFrameBufferObject() const |
639 | { | 639 | { |
640 | return false; | 640 | return false; |
641 | } | 641 | } |
642 | 642 | ||
643 | 643 | ||
644 | //! Bind Render Target Texture | 644 | //! Bind Render Target Texture |
645 | void COpenGLTexture::bindRTT() | 645 | void COpenGLTexture::bindRTT() |
646 | { | 646 | { |
647 | } | 647 | } |
648 | 648 | ||
649 | 649 | ||
650 | //! Unbind Render Target Texture | 650 | //! Unbind Render Target Texture |
651 | void COpenGLTexture::unbindRTT() | 651 | void COpenGLTexture::unbindRTT() |
652 | { | 652 | { |
653 | Driver->setActiveTexture(0, this); | 653 | Driver->setActiveTexture(0, this); |
654 | 654 | ||
655 | // Copy Our ViewPort To The Texture | 655 | // Copy Our ViewPort To The Texture |
656 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height); | 656 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height); |
657 | } | 657 | } |
658 | 658 | ||
659 | 659 | ||
660 | /* FBO Textures */ | 660 | /* FBO Textures */ |
661 | 661 | ||
662 | // helper function for render to texture | 662 | // helper function for render to texture |
663 | static bool checkFBOStatus(COpenGLDriver* Driver); | 663 | static bool checkFBOStatus(COpenGLDriver* Driver); |
664 | 664 | ||
665 | //! RTT ColorFrameBuffer constructor | 665 | //! RTT ColorFrameBuffer constructor |
666 | COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size, | 666 | COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size, |
667 | const io::path& name, COpenGLDriver* driver, | 667 | const io::path& name, COpenGLDriver* driver, |
668 | ECOLOR_FORMAT format) | 668 | ECOLOR_FORMAT format) |
669 | : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) | 669 | : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) |
670 | { | 670 | { |
671 | #ifdef _DEBUG | 671 | #ifdef _DEBUG |
672 | setDebugName("COpenGLTexture_FBO"); | 672 | setDebugName("COpenGLTexture_FBO"); |
673 | #endif | 673 | #endif |
674 | 674 | ||
675 | ImageSize = size; | 675 | ImageSize = size; |
676 | TextureSize = size; | 676 | TextureSize = size; |
677 | 677 | ||
678 | if (ECF_UNKNOWN == format) | 678 | if (ECF_UNKNOWN == format) |
679 | format = getBestColorFormat(driver->getColorFormat()); | 679 | format = getBestColorFormat(driver->getColorFormat()); |
680 | 680 | ||
681 | ColorFormat = format; | 681 | ColorFormat = format; |
682 | 682 | ||
683 | GLint FilteringType; | 683 | GLint FilteringType; |
684 | InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType); | 684 | InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType); |
685 | 685 | ||
686 | HasMipMaps = false; | 686 | HasMipMaps = false; |
687 | IsRenderTarget = true; | 687 | IsRenderTarget = true; |
688 | 688 | ||
689 | #ifdef GL_EXT_framebuffer_object | 689 | #ifdef GL_EXT_framebuffer_object |
690 | // generate frame buffer | 690 | // generate frame buffer |
691 | Driver->extGlGenFramebuffers(1, &ColorFrameBuffer); | 691 | Driver->extGlGenFramebuffers(1, &ColorFrameBuffer); |
692 | bindRTT(); | 692 | bindRTT(); |
693 | 693 | ||
694 | // generate color texture | 694 | // generate color texture |
695 | glGenTextures(1, &TextureName); | 695 | glGenTextures(1, &TextureName); |
696 | Driver->setActiveTexture(0, this); | 696 | Driver->setActiveTexture(0, this); |
697 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType); | 697 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType); |
698 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 698 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
699 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 699 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
700 | glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, | 700 | glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, |
701 | ImageSize.Height, 0, PixelFormat, PixelType, 0); | 701 | ImageSize.Height, 0, PixelFormat, PixelType, 0); |
702 | #ifdef _DEBUG | 702 | #ifdef _DEBUG |
703 | driver->testGLError(); | 703 | driver->testGLError(); |
704 | #endif | 704 | #endif |
705 | 705 | ||
706 | // attach color texture to frame buffer | 706 | // attach color texture to frame buffer |
707 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, | 707 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, |
708 | GL_COLOR_ATTACHMENT0_EXT, | 708 | GL_COLOR_ATTACHMENT0_EXT, |
709 | GL_TEXTURE_2D, | 709 | GL_TEXTURE_2D, |
710 | TextureName, | 710 | TextureName, |
711 | 0); | 711 | 0); |
712 | #ifdef _DEBUG | 712 | #ifdef _DEBUG |
713 | checkFBOStatus(Driver); | 713 | checkFBOStatus(Driver); |
714 | #endif | 714 | #endif |
715 | 715 | ||
716 | #endif | 716 | #endif |
717 | unbindRTT(); | 717 | unbindRTT(); |
718 | } | 718 | } |
719 | 719 | ||
720 | 720 | ||
721 | //! destructor | 721 | //! destructor |
722 | COpenGLFBOTexture::~COpenGLFBOTexture() | 722 | COpenGLFBOTexture::~COpenGLFBOTexture() |
723 | { | 723 | { |
724 | if (DepthTexture) | 724 | if (DepthTexture) |
725 | if (DepthTexture->drop()) | 725 | if (DepthTexture->drop()) |
726 | Driver->removeDepthTexture(DepthTexture); | 726 | Driver->removeDepthTexture(DepthTexture); |
727 | if (ColorFrameBuffer) | 727 | if (ColorFrameBuffer) |
728 | Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer); | 728 | Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer); |
729 | } | 729 | } |
730 | 730 | ||
731 | 731 | ||
732 | bool COpenGLFBOTexture::isFrameBufferObject() const | 732 | bool COpenGLFBOTexture::isFrameBufferObject() const |
733 | { | 733 | { |
734 | return true; | 734 | return true; |
735 | } | 735 | } |
736 | 736 | ||
737 | 737 | ||
738 | //! Bind Render Target Texture | 738 | //! Bind Render Target Texture |
739 | void COpenGLFBOTexture::bindRTT() | 739 | void COpenGLFBOTexture::bindRTT() |
740 | { | 740 | { |
741 | #ifdef GL_EXT_framebuffer_object | 741 | #ifdef GL_EXT_framebuffer_object |
742 | if (ColorFrameBuffer != 0) | 742 | if (ColorFrameBuffer != 0) |
743 | Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer); | 743 | Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer); |
744 | glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); | 744 | glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); |
745 | #endif | 745 | #endif |
746 | } | 746 | } |
747 | 747 | ||
748 | 748 | ||
749 | //! Unbind Render Target Texture | 749 | //! Unbind Render Target Texture |
750 | void COpenGLFBOTexture::unbindRTT() | 750 | void COpenGLFBOTexture::unbindRTT() |
751 | { | 751 | { |
752 | #ifdef GL_EXT_framebuffer_object | 752 | #ifdef GL_EXT_framebuffer_object |
753 | if (ColorFrameBuffer != 0) | 753 | if (ColorFrameBuffer != 0) |
754 | Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); | 754 | Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); |
755 | #endif | 755 | #endif |
756 | } | 756 | } |
757 | 757 | ||
758 | 758 | ||
759 | /* FBO Depth Textures */ | 759 | /* FBO Depth Textures */ |
760 | 760 | ||
761 | //! RTT DepthBuffer constructor | 761 | //! RTT DepthBuffer constructor |
762 | COpenGLFBODepthTexture::COpenGLFBODepthTexture( | 762 | COpenGLFBODepthTexture::COpenGLFBODepthTexture( |
763 | const core::dimension2d<u32>& size, | 763 | const core::dimension2d<u32>& size, |
764 | const io::path& name, | 764 | const io::path& name, |
765 | COpenGLDriver* driver, | 765 | COpenGLDriver* driver, |
766 | bool useStencil) | 766 | bool useStencil) |
767 | : COpenGLTexture(name, driver), DepthRenderBuffer(0), | 767 | : COpenGLTexture(name, driver), DepthRenderBuffer(0), |
768 | StencilRenderBuffer(0), UseStencil(useStencil) | 768 | StencilRenderBuffer(0), UseStencil(useStencil) |
769 | { | 769 | { |
770 | #ifdef _DEBUG | 770 | #ifdef _DEBUG |
771 | setDebugName("COpenGLTextureFBO_Depth"); | 771 | setDebugName("COpenGLTextureFBO_Depth"); |
772 | #endif | 772 | #endif |
773 | 773 | ||
774 | ImageSize = size; | 774 | ImageSize = size; |
775 | TextureSize = size; | 775 | TextureSize = size; |
776 | InternalFormat = GL_RGBA; | 776 | InternalFormat = GL_RGBA; |
777 | PixelFormat = GL_RGBA; | 777 | PixelFormat = GL_RGBA; |
778 | PixelType = GL_UNSIGNED_BYTE; | 778 | PixelType = GL_UNSIGNED_BYTE; |
779 | HasMipMaps = false; | 779 | HasMipMaps = false; |
780 | 780 | ||
781 | if (useStencil) | 781 | if (useStencil) |
782 | { | 782 | { |
783 | glGenTextures(1, &DepthRenderBuffer); | 783 | glGenTextures(1, &DepthRenderBuffer); |
784 | glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer); | 784 | glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer); |
785 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 785 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
786 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 786 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
787 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 787 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
788 | #ifdef GL_EXT_packed_depth_stencil | 788 | #ifdef GL_EXT_packed_depth_stencil |
789 | if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil)) | 789 | if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil)) |
790 | { | 790 | { |
791 | // generate packed depth stencil texture | 791 | // generate packed depth stencil texture |
792 | glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width, | 792 | glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width, |
793 | ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0); | 793 | ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0); |
794 | StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth | 794 | StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth |
795 | } | 795 | } |
796 | else // generate separate stencil and depth textures | 796 | else // generate separate stencil and depth textures |
797 | #endif | 797 | #endif |
798 | { | 798 | { |
799 | // generate depth texture | 799 | // generate depth texture |
800 | glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width, | 800 | glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width, |
801 | ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); | 801 | ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); |
802 | 802 | ||
803 | // generate stencil texture | 803 | // generate stencil texture |
804 | glGenTextures(1, &StencilRenderBuffer); | 804 | glGenTextures(1, &StencilRenderBuffer); |
805 | glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer); | 805 | glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer); |
806 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 806 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
807 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 807 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
808 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 808 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
809 | glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width, | 809 | glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width, |
810 | ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0); | 810 | ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0); |
811 | } | 811 | } |
812 | } | 812 | } |
813 | #ifdef GL_EXT_framebuffer_object | 813 | #ifdef GL_EXT_framebuffer_object |
814 | else | 814 | else |
815 | { | 815 | { |
816 | // generate depth buffer | 816 | // generate depth buffer |
817 | Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer); | 817 | Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer); |
818 | Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer); | 818 | Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer); |
819 | Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, | 819 | Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, |
820 | Driver->getZBufferBits(), ImageSize.Width, | 820 | Driver->getZBufferBits(), ImageSize.Width, |
821 | ImageSize.Height); | 821 | ImageSize.Height); |
822 | } | 822 | } |
823 | #endif | 823 | #endif |
824 | } | 824 | } |
825 | 825 | ||
826 | 826 | ||
827 | //! destructor | 827 | //! destructor |
828 | COpenGLFBODepthTexture::~COpenGLFBODepthTexture() | 828 | COpenGLFBODepthTexture::~COpenGLFBODepthTexture() |
829 | { | 829 | { |
830 | if (DepthRenderBuffer && UseStencil) | 830 | if (DepthRenderBuffer && UseStencil) |
831 | glDeleteTextures(1, &DepthRenderBuffer); | 831 | glDeleteTextures(1, &DepthRenderBuffer); |
832 | else | 832 | else |
833 | Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer); | 833 | Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer); |
834 | if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer) | 834 | if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer) |
835 | glDeleteTextures(1, &StencilRenderBuffer); | 835 | glDeleteTextures(1, &StencilRenderBuffer); |
836 | } | 836 | } |
837 | 837 | ||
838 | 838 | ||
839 | //combine depth texture and rtt | 839 | //combine depth texture and rtt |
840 | bool COpenGLFBODepthTexture::attach(ITexture* renderTex) | 840 | bool COpenGLFBODepthTexture::attach(ITexture* renderTex) |
841 | { | 841 | { |
842 | if (!renderTex) | 842 | if (!renderTex) |
843 | return false; | 843 | return false; |
844 | video::COpenGLFBOTexture* rtt = static_cast<video::COpenGLFBOTexture*>(renderTex); | 844 | video::COpenGLFBOTexture* rtt = static_cast<video::COpenGLFBOTexture*>(renderTex); |
845 | rtt->bindRTT(); | 845 | rtt->bindRTT(); |
846 | #ifdef GL_EXT_framebuffer_object | 846 | #ifdef GL_EXT_framebuffer_object |
847 | if (UseStencil) | 847 | if (UseStencil) |
848 | { | 848 | { |
849 | // attach stencil texture to stencil buffer | 849 | // attach stencil texture to stencil buffer |
850 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, | 850 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, |
851 | GL_STENCIL_ATTACHMENT_EXT, | 851 | GL_STENCIL_ATTACHMENT_EXT, |
852 | GL_TEXTURE_2D, | 852 | GL_TEXTURE_2D, |
853 | StencilRenderBuffer, | 853 | StencilRenderBuffer, |
854 | 0); | 854 | 0); |
855 | 855 | ||
856 | // attach depth texture to depth buffer | 856 | // attach depth texture to depth buffer |
857 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, | 857 | Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, |
858 | GL_DEPTH_ATTACHMENT_EXT, | 858 | GL_DEPTH_ATTACHMENT_EXT, |
859 | GL_TEXTURE_2D, | 859 | GL_TEXTURE_2D, |
860 | DepthRenderBuffer, | 860 | DepthRenderBuffer, |
861 | 0); | 861 | 0); |
862 | } | 862 | } |
863 | else | 863 | else |
864 | { | 864 | { |
865 | // attach depth renderbuffer to depth buffer | 865 | // attach depth renderbuffer to depth buffer |
866 | Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, | 866 | Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, |
867 | GL_DEPTH_ATTACHMENT_EXT, | 867 | GL_DEPTH_ATTACHMENT_EXT, |
868 | GL_RENDERBUFFER_EXT, | 868 | GL_RENDERBUFFER_EXT, |
869 | DepthRenderBuffer); | 869 | DepthRenderBuffer); |
870 | } | 870 | } |
871 | #endif | 871 | #endif |
872 | // check the status | 872 | // check the status |
873 | if (!checkFBOStatus(Driver)) | 873 | if (!checkFBOStatus(Driver)) |
874 | { | 874 | { |
875 | os::Printer::log("FBO incomplete"); | 875 | os::Printer::log("FBO incomplete"); |
876 | return false; | 876 | return false; |
877 | } | 877 | } |
878 | rtt->DepthTexture=this; | 878 | rtt->DepthTexture=this; |
879 | grab(); // grab the depth buffer, not the RTT | 879 | grab(); // grab the depth buffer, not the RTT |
880 | rtt->unbindRTT(); | 880 | rtt->unbindRTT(); |
881 | return true; | 881 | return true; |
882 | } | 882 | } |
883 | 883 | ||
884 | 884 | ||
885 | //! Bind Render Target Texture | 885 | //! Bind Render Target Texture |
886 | void COpenGLFBODepthTexture::bindRTT() | 886 | void COpenGLFBODepthTexture::bindRTT() |
887 | { | 887 | { |
888 | } | 888 | } |
889 | 889 | ||
890 | 890 | ||
891 | //! Unbind Render Target Texture | 891 | //! Unbind Render Target Texture |
892 | void COpenGLFBODepthTexture::unbindRTT() | 892 | void COpenGLFBODepthTexture::unbindRTT() |
893 | { | 893 | { |
894 | } | 894 | } |
895 | 895 | ||
896 | 896 | ||
897 | bool checkFBOStatus(COpenGLDriver* Driver) | 897 | bool checkFBOStatus(COpenGLDriver* Driver) |
898 | { | 898 | { |
899 | #ifdef GL_EXT_framebuffer_object | 899 | #ifdef GL_EXT_framebuffer_object |
900 | GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); | 900 | GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); |
901 | 901 | ||
902 | switch (status) | 902 | switch (status) |
903 | { | 903 | { |
904 | //Our FBO is perfect, return true | 904 | //Our FBO is perfect, return true |
905 | case GL_FRAMEBUFFER_COMPLETE_EXT: | 905 | case GL_FRAMEBUFFER_COMPLETE_EXT: |
906 | return true; | 906 | return true; |
907 | 907 | ||
908 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: | 908 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: |
909 | os::Printer::log("FBO has invalid read buffer", ELL_ERROR); | 909 | os::Printer::log("FBO has invalid read buffer", ELL_ERROR); |
910 | break; | 910 | break; |
911 | 911 | ||
912 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: | 912 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: |
913 | os::Printer::log("FBO has invalid draw buffer", ELL_ERROR); | 913 | os::Printer::log("FBO has invalid draw buffer", ELL_ERROR); |
914 | break; | 914 | break; |
915 | 915 | ||
916 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: | 916 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: |
917 | os::Printer::log("FBO has one or several incomplete image attachments", ELL_ERROR); | 917 | os::Printer::log("FBO has one or several incomplete image attachments", ELL_ERROR); |
918 | break; | 918 | break; |
919 | 919 | ||
920 | case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: | 920 | case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: |
921 | os::Printer::log("FBO has one or several image attachments with different internal formats", ELL_ERROR); | 921 | os::Printer::log("FBO has one or several image attachments with different internal formats", ELL_ERROR); |
922 | break; | 922 | break; |
923 | 923 | ||
924 | case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: | 924 | case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: |
925 | os::Printer::log("FBO has one or several image attachments with different dimensions", ELL_ERROR); | 925 | os::Printer::log("FBO has one or several image attachments with different dimensions", ELL_ERROR); |
926 | break; | 926 | break; |
927 | 927 | ||
928 | // not part of fbo_object anymore, but won't harm as it is just a return value | 928 | // not part of fbo_object anymore, but won't harm as it is just a return value |
929 | #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT | 929 | #ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT |
930 | case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: | 930 | case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: |
931 | os::Printer::log("FBO has a duplicate image attachment", ELL_ERROR); | 931 | os::Printer::log("FBO has a duplicate image attachment", ELL_ERROR); |
932 | break; | 932 | break; |
933 | #endif | 933 | #endif |
934 | 934 | ||
935 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: | 935 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: |
936 | os::Printer::log("FBO missing an image attachment", ELL_ERROR); | 936 | os::Printer::log("FBO missing an image attachment", ELL_ERROR); |
937 | break; | 937 | break; |
938 | 938 | ||
939 | #ifdef GL_EXT_framebuffer_multisample | 939 | #ifdef GL_EXT_framebuffer_multisample |
940 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: | 940 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: |
941 | os::Printer::log("FBO wrong multisample setup", ELL_ERROR); | 941 | os::Printer::log("FBO wrong multisample setup", ELL_ERROR); |
942 | break; | 942 | break; |
943 | #endif | 943 | #endif |
944 | 944 | ||
945 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: | 945 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: |
946 | os::Printer::log("FBO format unsupported", ELL_ERROR); | 946 | os::Printer::log("FBO format unsupported", ELL_ERROR); |
947 | break; | 947 | break; |
948 | 948 | ||
949 | default: | 949 | default: |
950 | break; | 950 | break; |
951 | } | 951 | } |
952 | #endif | 952 | #endif |
953 | os::Printer::log("FBO error", ELL_ERROR); | 953 | os::Printer::log("FBO error", ELL_ERROR); |
954 | // _IRR_DEBUG_BREAK_IF(true); | 954 | // _IRR_DEBUG_BREAK_IF(true); |
955 | return false; | 955 | return false; |
956 | } | 956 | } |
957 | 957 | ||
958 | 958 | ||
959 | } // end namespace video | 959 | } // end namespace video |
960 | } // end namespace irr | 960 | } // end namespace irr |
961 | 961 | ||
962 | #endif // _IRR_COMPILE_WITH_OPENGL_ | 962 | #endif // _IRR_COMPILE_WITH_OPENGL_ |
963 | 963 | ||