blob: dcea3c0d82538233326bdd6a8b1f964c420e92a3 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Texture.cpp: Implements the gl::Texture class and its derived classes
8// Texture2D and TextureCubeMap. Implements GL texture objects and related
9// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
10
11#include "Texture.h"
12
daniel@transgaming.com16973022010-03-11 19:22:19 +000013#include <algorithm>
14
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015#include "main.h"
16#include "mathutil.h"
17#include "debug.h"
18
19namespace gl
20{
21Texture::Texture() : Colorbuffer(0)
22{
23 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
24 mMagFilter = GL_LINEAR;
25 mWrapS = GL_REPEAT;
26 mWrapT = GL_REPEAT;
daniel@transgaming.com29d27002010-03-11 19:41:22 +000027
28 mDirtyImageData = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029}
30
31Texture::~Texture()
32{
33}
34
35// Returns true on successful filter state update (valid enum parameter)
36bool Texture::setMinFilter(GLenum filter)
37{
38 switch (filter)
39 {
40 case GL_NEAREST:
41 case GL_LINEAR:
42 case GL_NEAREST_MIPMAP_NEAREST:
43 case GL_LINEAR_MIPMAP_NEAREST:
44 case GL_NEAREST_MIPMAP_LINEAR:
45 case GL_LINEAR_MIPMAP_LINEAR:
46 mMinFilter = filter;
47 return true;
48 default:
49 return false;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000050 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051}
52
53// Returns true on successful filter state update (valid enum parameter)
54bool Texture::setMagFilter(GLenum filter)
55{
56 switch (filter)
57 {
58 case GL_NEAREST:
59 case GL_LINEAR:
60 mMagFilter = filter;
61 return true;
62 default:
63 return false;
64 }
65}
66
67// Returns true on successful wrap state update (valid enum parameter)
68bool Texture::setWrapS(GLenum wrap)
69{
70 switch (wrap)
71 {
72 case GL_REPEAT:
73 case GL_CLAMP_TO_EDGE:
74 case GL_MIRRORED_REPEAT:
75 mWrapS = wrap;
76 return true;
77 default:
78 return false;
79 }
80}
81
82// Returns true on successful wrap state update (valid enum parameter)
83bool Texture::setWrapT(GLenum wrap)
84{
85 switch (wrap)
86 {
87 case GL_REPEAT:
88 case GL_CLAMP_TO_EDGE:
89 case GL_MIRRORED_REPEAT:
90 mWrapT = wrap;
91 return true;
92 default:
93 return false;
94 }
95}
96
97GLenum Texture::getMinFilter()
98{
99 return mMinFilter;
100}
101
102GLenum Texture::getMagFilter()
103{
104 return mMagFilter;
105}
106
107GLenum Texture::getWrapS()
108{
109 return mWrapS;
110}
111
112GLenum Texture::getWrapT()
113{
114 return mWrapT;
115}
116
117// Copies an Image into an already locked Direct3D 9 surface, performing format conversions as necessary
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000118void Texture::copyImage(const D3DLOCKED_RECT &lock, D3DFORMAT format, Image *image)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119{
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000120 if (lock.pBits && !image->pixels.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000122 for (int y = 0; y < image->height; y++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000124 unsigned char *source = &image->pixels[0] + y * image->width * pixelSize(*image);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125 unsigned short *source16 = (unsigned short*)source;
126 unsigned char *dest = (unsigned char*)lock.pBits + y * lock.Pitch;
127
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000128 for (int x = 0; x < image->width; x++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129 {
130 unsigned char r;
131 unsigned char g;
132 unsigned char b;
133 unsigned char a;
134
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000135 switch (image->format)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 {
137 case GL_ALPHA:
138 UNIMPLEMENTED();
139 break;
140 case GL_LUMINANCE:
141 UNIMPLEMENTED();
142 break;
143 case GL_LUMINANCE_ALPHA:
144 UNIMPLEMENTED();
145 break;
146 case GL_RGB:
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000147 switch (image->type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148 {
149 case GL_UNSIGNED_BYTE: UNIMPLEMENTED(); break;
150 case GL_UNSIGNED_SHORT_5_6_5:
151 {
152 unsigned short rgba = source16[x];
153
154 a = 0xFF;
155 b = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
156 g = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
157 r = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
158 }
159 break;
160 default: UNREACHABLE();
161 }
162 break;
163 case GL_RGBA:
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000164 switch (image->type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165 {
166 case GL_UNSIGNED_BYTE:
167 r = source[x * 4 + 0];
168 g = source[x * 4 + 1];
169 b = source[x * 4 + 2];
170 a = source[x * 4 + 3];
171 break;
172 case GL_UNSIGNED_SHORT_4_4_4_4:
173 {
174 unsigned short rgba = source16[x];
175
176 a = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
177 b = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
178 g = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
179 r = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
180 }
181 break;
182 case GL_UNSIGNED_SHORT_5_5_5_1: UNIMPLEMENTED(); break;
183 default: UNREACHABLE();
184 }
185 break;
186 default: UNREACHABLE();
187 }
188
189 switch (format)
190 {
191 case D3DFMT_A8R8G8B8:
192 dest[4 * x + 0] = b;
193 dest[4 * x + 1] = g;
194 dest[4 * x + 2] = r;
195 dest[4 * x + 3] = a;
196 break;
197 default: UNREACHABLE();
198 }
199 }
200 }
201 }
202}
203
204// Selects an internal Direct3D 9 format for storing an Image
205D3DFORMAT Texture::selectFormat(const Image &image)
206{
207 switch (image.format)
208 {
209 case GL_ALPHA:
210 UNIMPLEMENTED();
211 break;
212 case GL_LUMINANCE:
213 UNIMPLEMENTED();
214 break;
215 case GL_LUMINANCE_ALPHA:
216 UNIMPLEMENTED();
217 break;
218 case GL_RGB:
219 switch (image.type)
220 {
221 case GL_UNSIGNED_BYTE: UNIMPLEMENTED();
222 case GL_UNSIGNED_SHORT_5_6_5: return D3DFMT_A8R8G8B8;
223 default: UNREACHABLE();
224 }
225 break;
226 case GL_RGBA:
227 switch (image.type)
228 {
229 case GL_UNSIGNED_BYTE: return D3DFMT_A8R8G8B8;
230 case GL_UNSIGNED_SHORT_4_4_4_4: return D3DFMT_A8R8G8B8;
231 case GL_UNSIGNED_SHORT_5_5_5_1: UNIMPLEMENTED();
232 default: UNREACHABLE();
233 }
234 break;
235 default: UNREACHABLE();
236 }
237
238 return D3DFMT_UNKNOWN;
239}
240
241// Returns the size, in bytes, of a single texel in an Image
242int Texture::pixelSize(const Image &image)
243{
244 switch (image.type)
245 {
246 case GL_UNSIGNED_BYTE:
247 switch (image.format)
248 {
249 case GL_ALPHA: return sizeof(unsigned char);
250 case GL_LUMINANCE: return sizeof(unsigned char);
251 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
252 case GL_RGB: return sizeof(unsigned char) * 3;
253 case GL_RGBA: return sizeof(unsigned char) * 4;
254 default: UNREACHABLE();
255 }
256 break;
257 case GL_UNSIGNED_SHORT_4_4_4_4:
258 case GL_UNSIGNED_SHORT_5_5_5_1:
259 case GL_UNSIGNED_SHORT_5_6_5:
260 return sizeof(unsigned short);
261 default: UNREACHABLE();
262 }
263
264 return 0;
265}
266
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000267void Texture::setImage(GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels, Image *img)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268{
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000269 mDirtyImageData = true;
270
271 img->internalFormat = internalFormat;
272 img->width = width;
273 img->height = height;
274 img->format = format;
275 img->type = type;
276
277 size_t imageSize = pixelSize(*img) * width * height;
278
279 std::vector<unsigned char> storage(imageSize);
280
281 if (pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000283 memcpy(&storage[0], pixels, imageSize);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284 }
285
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000286 img->pixels.swap(storage);
287}
288
289IDirect3DBaseTexture9 *Texture::getTexture()
290{
291 if (!isComplete())
292 {
293 return NULL;
294 }
295
296 if (mDirtyImageData)
297 {
298 mBaseTexture = createTexture();
299
300 mDirtyImageData = false;
301 }
302
303 return mBaseTexture;
304}
305
306Texture2D::Texture2D()
307{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308 mTexture = NULL;
309}
310
311Texture2D::~Texture2D()
312{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313 if (mTexture)
314 {
315 mTexture->Release();
316 mTexture = NULL;
317 }
318}
319
320GLenum Texture2D::getTarget() const
321{
322 return GL_TEXTURE_2D;
323}
324
325void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
326{
327 if (level < 0 || level >= MAX_TEXTURE_LEVELS)
328 {
329 return;
330 }
331
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000332 Texture::setImage(internalFormat, width, height, format, type, pixels, &mImageArray[level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333
334 if (level == 0)
335 {
336 mWidth = width;
337 mHeight = height;
338 }
339}
340
341// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
342bool Texture2D::isComplete()
343{
344 if (mWidth <= 0 || mHeight <= 0)
345 {
346 return false;
347 }
348
349 bool mipmapping;
350
351 switch (mMagFilter)
352 {
353 case GL_NEAREST:
354 case GL_LINEAR:
355 mipmapping = false;
356 break;
357 case GL_NEAREST_MIPMAP_NEAREST:
358 case GL_LINEAR_MIPMAP_NEAREST:
359 case GL_NEAREST_MIPMAP_LINEAR:
360 case GL_LINEAR_MIPMAP_LINEAR:
361 mipmapping = true;
362 break;
363 default: UNREACHABLE();
364 }
365
366 if (mipmapping)
367 {
daniel@transgaming.com16973022010-03-11 19:22:19 +0000368 int q = log2(std::max(mWidth, mHeight));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369
370 for (int level = 1; level <= q; level++)
371 {
372 if (mImageArray[level].format != mImageArray[0].format)
373 {
374 return false;
375 }
376
377 if (mImageArray[level].internalFormat != mImageArray[0].internalFormat)
378 {
379 return false;
380 }
381
382 if (mImageArray[level].type != mImageArray[0].type)
383 {
384 return false;
385 }
386
387 if (mImageArray[level].width != (mImageArray[level - 1].width + 1) / 2)
388 {
389 return false;
390 }
391
392 if (mImageArray[level].height != (mImageArray[level - 1].height + 1) / 2)
393 {
394 return false;
395 }
396 }
397 }
398
399 return true;
400}
401
402// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000403IDirect3DBaseTexture9 *Texture2D::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404{
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000405 IDirect3DTexture9 *texture;
406
407 IDirect3DDevice9 *device = getDevice();
408 D3DFORMAT format = selectFormat(mImageArray[0]);
409
410 HRESULT result = device->CreateTexture(mWidth, mHeight, 0, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
411
412 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000413 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000414 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415 }
416
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000417 ASSERT(SUCCEEDED(result));
418
419 IDirect3DTexture9 *lockableTexture;
420 result = device->CreateTexture(mWidth, mHeight, 0, D3DUSAGE_DYNAMIC, format, D3DPOOL_SYSTEMMEM, &lockableTexture, NULL);
421
422 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000424 texture->Release();
425 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000426 }
427
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000428 ASSERT(SUCCEEDED(result));
429
430 int levelCount = texture->GetLevelCount();
431
432 for (int level = 0; level < levelCount; level++)
433 {
434 D3DLOCKED_RECT lock = {0};
435 lockableTexture->LockRect(level, &lock, NULL, 0);
436
437 copyImage(lock, format, &mImageArray[level]);
438
439 lockableTexture->UnlockRect(level);
440 }
441
442 device->UpdateTexture(lockableTexture, texture);
443 lockableTexture->Release();
444
445 if (mTexture) mTexture->Release();
446 mTexture = texture;
447 return texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448}
449
450// Returns the top-level texture surface as a render target
451IDirect3DSurface9 *Texture2D::getRenderTarget()
452{
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000453 if (mDirtyImageData && mRenderTarget)
454 {
455 mRenderTarget->Release();
456 mRenderTarget = NULL;
457 }
458
459 if (!mRenderTarget && getTexture()) // FIXME: getTexture fails for incomplete textures. Check spec.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000461 mTexture->GetSurfaceLevel(0, &mRenderTarget);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462 }
463
464 return mRenderTarget;
465}
466
467TextureCubeMap::TextureCubeMap()
468{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469 mTexture = NULL;
470}
471
472TextureCubeMap::~TextureCubeMap()
473{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474 if (mTexture)
475 {
476 mTexture->Release();
477 mTexture = NULL;
478 }
479}
480
481GLenum TextureCubeMap::getTarget() const
482{
483 return GL_TEXTURE_CUBE_MAP;
484}
485
486void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
487{
488 setImage(0, level, internalFormat, width, height, format, type, pixels);
489}
490
491void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
492{
493 setImage(1, level, internalFormat, width, height, format, type, pixels);
494}
495
496void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
497{
498 setImage(2, level, internalFormat, width, height, format, type, pixels);
499}
500
501void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
502{
503 setImage(3, level, internalFormat, width, height, format, type, pixels);
504}
505
506void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
507{
508 setImage(4, level, internalFormat, width, height, format, type, pixels);
509}
510
511void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
512{
513 setImage(5, level, internalFormat, width, height, format, type, pixels);
514}
515
516// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
517bool TextureCubeMap::isComplete()
518{
519 if (mWidth <= 0 || mHeight <= 0 || mWidth != mHeight)
520 {
521 return false;
522 }
523
524 bool mipmapping;
525
526 switch (mMagFilter)
527 {
528 case GL_NEAREST:
529 case GL_LINEAR:
530 mipmapping = false;
531 break;
532 case GL_NEAREST_MIPMAP_NEAREST:
533 case GL_LINEAR_MIPMAP_NEAREST:
534 case GL_NEAREST_MIPMAP_LINEAR:
535 case GL_LINEAR_MIPMAP_LINEAR:
536 mipmapping = true;
537 break;
538 default: UNREACHABLE();
539 }
540
541 for (int face = 0; face < 6; face++)
542 {
543 if (mImageArray[face][0].width != mWidth || mImageArray[face][0].height != mHeight)
544 {
545 return false;
546 }
547 }
548
549 if (mipmapping)
550 {
551 int q = log2(mWidth);
552
553 for (int face = 0; face < 6; face++)
554 {
555 for (int level = 1; level <= q; level++)
556 {
557 if (mImageArray[face][level].format != mImageArray[0][0].format)
558 {
559 return false;
560 }
561
562 if (mImageArray[face][level].internalFormat != mImageArray[0][0].internalFormat)
563 {
564 return false;
565 }
566
567 if (mImageArray[face][level].type != mImageArray[0][0].type)
568 {
569 return false;
570 }
571
572 if (mImageArray[face][level].width != (mImageArray[0][level - 1].width + 1) / 2)
573 {
574 return false;
575 }
576
577 if (mImageArray[face][level].height != (mImageArray[0][level - 1].height + 1) / 2)
578 {
579 return false;
580 }
581 }
582 }
583 }
584
585 return true;
586}
587
588// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000589IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590{
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000591 IDirect3DDevice9 *device = getDevice();
592 D3DFORMAT format = selectFormat(mImageArray[0][0]);
593
594 IDirect3DCubeTexture9 *texture;
595
596 HRESULT result = device->CreateCubeTexture(mWidth, 0, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
597
598 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000600 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601 }
602
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000603 ASSERT(SUCCEEDED(result));
604
605 IDirect3DCubeTexture9 *lockableTexture;
606 result = device->CreateCubeTexture(mWidth, 0, D3DUSAGE_DYNAMIC, format, D3DPOOL_SYSTEMMEM, &lockableTexture, NULL);
607
608 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000609 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000610 texture->Release();
611 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
612 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000614 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000615
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000616 for (int face = 0; face < 6; face++)
617 {
618 for (int level = 0; level < MAX_TEXTURE_LEVELS; level++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619 {
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000620 D3DLOCKED_RECT lock = {0};
621 lockableTexture->LockRect((D3DCUBEMAP_FACES)face, level, &lock, NULL, 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000622
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000623 copyImage(lock, format, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000624
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000625 lockableTexture->UnlockRect((D3DCUBEMAP_FACES)face, level);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626 }
627 }
628
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000629 device->UpdateTexture(lockableTexture, texture);
630 lockableTexture->Release();
631
632 if (mTexture) mTexture->Release();
633
634 mTexture = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635 return mTexture;
636}
637
638void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
639{
640 if (level < 0 || level >= MAX_TEXTURE_LEVELS)
641 {
642 return;
643 }
644
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000645 Texture::setImage(internalFormat, width, height, format, type, pixels, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646
647 if (face == 0 && level == 0)
648 {
649 mWidth = width;
650 mHeight = height;
651 }
652}
653}