blob: d24089ea1fdbc2615e13f34c2cb010c1ea5c0bb4 [file] [log] [blame]
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +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 "libGLESv2/Texture.h"
12
13#include <d3dx9tex.h>
14
15#include <algorithm>
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +000016#include <intrin.h>
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000017
18#include "common/debug.h"
19
jbauman@chromium.orgae345802011-03-30 22:04:25 +000020#include "libEGL/Display.h"
21
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000022#include "libGLESv2/main.h"
23#include "libGLESv2/mathutil.h"
24#include "libGLESv2/utilities.h"
25#include "libGLESv2/Blit.h"
26#include "libGLESv2/Framebuffer.h"
27
28namespace gl
29{
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +000030unsigned int Texture::mCurrentSerial = 1;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000031
daniel@transgaming.comde631782011-11-09 17:45:04 +000032Image::Image()
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000033 : mWidth(0), mHeight(0), mDirty(false), mSurface(NULL), mFormat(GL_NONE), mType(GL_UNSIGNED_BYTE)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000034{
35}
36
daniel@transgaming.comde631782011-11-09 17:45:04 +000037Image::~Image()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000038{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000039 if (mSurface)
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +000040 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000041 mSurface->Release();
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +000042 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +000043}
44
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000045void Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type)
46{
daniel@transgaming.com4c0a7712011-11-09 17:45:19 +000047 if (mWidth != width ||
48 mHeight != height ||
49 mFormat != format ||
50 mType != type)
51 {
52 if (mSurface)
53 {
54 mSurface->Release();
55 mSurface = NULL;
56 }
57 }
58
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000059 mWidth = width;
60 mHeight = height;
61 mFormat = format;
62 mType = type;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000063}
64
65void Image::createSurface()
66{
67 if(mSurface)
68 {
69 return;
70 }
71
72 IDirect3DTexture9 *newTexture = NULL;
73 IDirect3DSurface9 *newSurface = NULL;
74
75 if (mWidth != 0 && mHeight != 0)
76 {
77 int levelToFetch = 0;
78 GLsizei requestWidth = mWidth;
79 GLsizei requestHeight = mHeight;
80 if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
81 {
82 bool isMult4 = false;
83 int upsampleCount = 0;
84 while (!isMult4)
85 {
86 requestWidth <<= 1;
87 requestHeight <<= 1;
88 upsampleCount++;
89 if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
90 {
91 isMult4 = true;
92 }
93 }
94 levelToFetch = upsampleCount;
95 }
96
97 HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, getD3DFormat(),
98 D3DPOOL_SYSTEMMEM, &newTexture, NULL);
99
100 if (FAILED(result))
101 {
102 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com73de05a2011-11-09 17:45:24 +0000103 ERR("Creating image surface failed.");
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000104 return error(GL_OUT_OF_MEMORY);
105 }
106
107 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
108 newTexture->Release();
109 }
110
111 mSurface = newSurface;
112}
113
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +0000114HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
115{
116 createSurface();
117
118 HRESULT result = D3DERR_INVALIDCALL;
119
120 if (mSurface)
121 {
122 result = mSurface->LockRect(lockedRect, rect, 0);
123 ASSERT(SUCCEEDED(result));
124
125 mDirty = true;
126 }
127
128 return result;
129}
130
131void Image::unlock()
132{
133 if (mSurface)
134 {
135 HRESULT result = mSurface->UnlockRect();
136 ASSERT(SUCCEEDED(result));
137 }
138}
139
daniel@transgaming.comde631782011-11-09 17:45:04 +0000140bool Image::isRenderable() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000141{
142 switch(getD3DFormat())
143 {
144 case D3DFMT_L8:
145 case D3DFMT_A8L8:
146 case D3DFMT_DXT1:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000147 case D3DFMT_DXT3:
148 case D3DFMT_DXT5:
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000149 return false;
150 case D3DFMT_A8R8G8B8:
151 case D3DFMT_X8R8G8B8:
152 case D3DFMT_A16B16G16R16F:
153 case D3DFMT_A32B32G32R32F:
154 return true;
155 default:
156 UNREACHABLE();
157 }
158
159 return false;
160}
161
daniel@transgaming.comde631782011-11-09 17:45:04 +0000162D3DFORMAT Image::getD3DFormat() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000163{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000164 if (mFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
165 mFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000166 {
167 return D3DFMT_DXT1;
168 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000169 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000170 {
171 return D3DFMT_DXT3;
172 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000173 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000174 {
175 return D3DFMT_DXT5;
176 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000177 else if (mType == GL_FLOAT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000178 {
179 return D3DFMT_A32B32G32R32F;
180 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000181 else if (mType == GL_HALF_FLOAT_OES)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000182 {
183 return D3DFMT_A16B16G16R16F;
184 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000185 else if (mType == GL_UNSIGNED_BYTE)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000186 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000187 if (mFormat == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000188 {
189 return D3DFMT_L8;
190 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000191 else if (mFormat == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000192 {
193 return D3DFMT_A8L8;
194 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000195 else if (mFormat == GL_RGB)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000196 {
197 return D3DFMT_X8R8G8B8;
198 }
199
200 return D3DFMT_A8R8G8B8;
201 }
202
203 return D3DFMT_A8R8G8B8;
204}
205
daniel@transgaming.com73de05a2011-11-09 17:45:24 +0000206IDirect3DSurface9 *Image::getSurface()
207{
208 createSurface();
209
210 return mSurface;
211}
212
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +0000213Texture::Texture(GLuint id) : RefCountObject(id), mSerial(issueSerial())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000214{
215 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
216 mMagFilter = GL_LINEAR;
217 mWrapS = GL_REPEAT;
218 mWrapT = GL_REPEAT;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000219 mDirtyParameters = true;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +0000220
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000221 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +0000222
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000223 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000224}
225
226Texture::~Texture()
227{
228}
229
230Blit *Texture::getBlitter()
231{
232 Context *context = getContext();
233 return context->getBlitter();
234}
235
236// Returns true on successful filter state update (valid enum parameter)
237bool Texture::setMinFilter(GLenum filter)
238{
239 switch (filter)
240 {
241 case GL_NEAREST:
242 case GL_LINEAR:
243 case GL_NEAREST_MIPMAP_NEAREST:
244 case GL_LINEAR_MIPMAP_NEAREST:
245 case GL_NEAREST_MIPMAP_LINEAR:
246 case GL_LINEAR_MIPMAP_LINEAR:
247 {
248 if (mMinFilter != filter)
249 {
250 mMinFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000251 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000252 }
253 return true;
254 }
255 default:
256 return false;
257 }
258}
259
260// Returns true on successful filter state update (valid enum parameter)
261bool Texture::setMagFilter(GLenum filter)
262{
263 switch (filter)
264 {
265 case GL_NEAREST:
266 case GL_LINEAR:
267 {
268 if (mMagFilter != filter)
269 {
270 mMagFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000271 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000272 }
273 return true;
274 }
275 default:
276 return false;
277 }
278}
279
280// Returns true on successful wrap state update (valid enum parameter)
281bool Texture::setWrapS(GLenum wrap)
282{
283 switch (wrap)
284 {
285 case GL_REPEAT:
286 case GL_CLAMP_TO_EDGE:
287 case GL_MIRRORED_REPEAT:
288 {
289 if (mWrapS != wrap)
290 {
291 mWrapS = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000292 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000293 }
294 return true;
295 }
296 default:
297 return false;
298 }
299}
300
301// Returns true on successful wrap state update (valid enum parameter)
302bool Texture::setWrapT(GLenum wrap)
303{
304 switch (wrap)
305 {
306 case GL_REPEAT:
307 case GL_CLAMP_TO_EDGE:
308 case GL_MIRRORED_REPEAT:
309 {
310 if (mWrapT != wrap)
311 {
312 mWrapT = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000313 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000314 }
315 return true;
316 }
317 default:
318 return false;
319 }
320}
321
322GLenum Texture::getMinFilter() const
323{
324 return mMinFilter;
325}
326
327GLenum Texture::getMagFilter() const
328{
329 return mMagFilter;
330}
331
332GLenum Texture::getWrapS() const
333{
334 return mWrapS;
335}
336
337GLenum Texture::getWrapT() const
338{
339 return mWrapT;
340}
341
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000342// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
343// into the target pixel rectangle at output with outputPitch bytes in between each line.
344void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
daniel@transgaming.com6e4b1212011-11-09 17:45:28 +0000345 GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DFORMAT targetFormat) const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000346{
347 GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment);
348 input = ((char*)input) - inputPitch * (height - 1);
349
350 switch (type)
351 {
352 case GL_UNSIGNED_BYTE:
353 switch (format)
354 {
355 case GL_ALPHA:
356 loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
357 break;
358 case GL_LUMINANCE:
daniel@transgaming.com6e4b1212011-11-09 17:45:28 +0000359 loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, targetFormat == D3DFMT_L8);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000360 break;
361 case GL_LUMINANCE_ALPHA:
daniel@transgaming.com6e4b1212011-11-09 17:45:28 +0000362 loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, targetFormat == D3DFMT_A8L8);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000363 break;
364 case GL_RGB:
365 loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
366 break;
367 case GL_RGBA:
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000368 if (supportsSSE2())
369 {
370 loadRGBAUByteImageDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
371 }
372 else
373 {
374 loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
375 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000376 break;
377 case GL_BGRA_EXT:
378 loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
379 break;
380 default: UNREACHABLE();
381 }
382 break;
383 case GL_UNSIGNED_SHORT_5_6_5:
384 switch (format)
385 {
386 case GL_RGB:
387 loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
388 break;
389 default: UNREACHABLE();
390 }
391 break;
392 case GL_UNSIGNED_SHORT_4_4_4_4:
393 switch (format)
394 {
395 case GL_RGBA:
396 loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
397 break;
398 default: UNREACHABLE();
399 }
400 break;
401 case GL_UNSIGNED_SHORT_5_5_5_1:
402 switch (format)
403 {
404 case GL_RGBA:
405 loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
406 break;
407 default: UNREACHABLE();
408 }
409 break;
410 case GL_FLOAT:
411 switch (format)
412 {
413 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
414 case GL_ALPHA:
415 loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
416 break;
417 case GL_LUMINANCE:
418 loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
419 break;
420 case GL_LUMINANCE_ALPHA:
421 loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
422 break;
423 case GL_RGB:
424 loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
425 break;
426 case GL_RGBA:
427 loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
428 break;
429 default: UNREACHABLE();
430 }
431 break;
432 case GL_HALF_FLOAT_OES:
433 switch (format)
434 {
435 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
436 case GL_ALPHA:
437 loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
438 break;
439 case GL_LUMINANCE:
440 loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
441 break;
442 case GL_LUMINANCE_ALPHA:
443 loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
444 break;
445 case GL_RGB:
446 loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
447 break;
448 case GL_RGBA:
449 loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
450 break;
451 default: UNREACHABLE();
452 }
453 break;
454 default: UNREACHABLE();
455 }
456}
457
458void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
459 int inputPitch, const void *input, size_t outputPitch, void *output) const
460{
461 const unsigned char *source = NULL;
462 unsigned char *dest = NULL;
463
464 for (int y = 0; y < height; y++)
465 {
466 source = static_cast<const unsigned char*>(input) + y * inputPitch;
467 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
468 for (int x = 0; x < width; x++)
469 {
470 dest[4 * x + 0] = 0;
471 dest[4 * x + 1] = 0;
472 dest[4 * x + 2] = 0;
473 dest[4 * x + 3] = source[x];
474 }
475 }
476}
477
478void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
479 int inputPitch, const void *input, size_t outputPitch, void *output) const
480{
481 const float *source = NULL;
482 float *dest = NULL;
483
484 for (int y = 0; y < height; y++)
485 {
486 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
487 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
488 for (int x = 0; x < width; x++)
489 {
490 dest[4 * x + 0] = 0;
491 dest[4 * x + 1] = 0;
492 dest[4 * x + 2] = 0;
493 dest[4 * x + 3] = source[x];
494 }
495 }
496}
497
498void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
499 int inputPitch, const void *input, size_t outputPitch, void *output) const
500{
501 const unsigned short *source = NULL;
502 unsigned short *dest = NULL;
503
504 for (int y = 0; y < height; y++)
505 {
506 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
507 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
508 for (int x = 0; x < width; x++)
509 {
510 dest[4 * x + 0] = 0;
511 dest[4 * x + 1] = 0;
512 dest[4 * x + 2] = 0;
513 dest[4 * x + 3] = source[x];
514 }
515 }
516}
517
518void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
519 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
520{
521 const int destBytesPerPixel = native? 1: 4;
522 const unsigned char *source = NULL;
523 unsigned char *dest = NULL;
524
525 for (int y = 0; y < height; y++)
526 {
527 source = static_cast<const unsigned char*>(input) + y * inputPitch;
528 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
529
530 if (!native) // BGRA8 destination format
531 {
532 for (int x = 0; x < width; x++)
533 {
534 dest[4 * x + 0] = source[x];
535 dest[4 * x + 1] = source[x];
536 dest[4 * x + 2] = source[x];
537 dest[4 * x + 3] = 0xFF;
538 }
539 }
540 else // L8 destination format
541 {
542 memcpy(dest, source, width);
543 }
544 }
545}
546
547void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
548 int inputPitch, const void *input, size_t outputPitch, void *output) const
549{
550 const float *source = NULL;
551 float *dest = NULL;
552
553 for (int y = 0; y < height; y++)
554 {
555 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
556 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
557 for (int x = 0; x < width; x++)
558 {
559 dest[4 * x + 0] = source[x];
560 dest[4 * x + 1] = source[x];
561 dest[4 * x + 2] = source[x];
562 dest[4 * x + 3] = 1.0f;
563 }
564 }
565}
566
567void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
568 int inputPitch, const void *input, size_t outputPitch, void *output) const
569{
570 const unsigned short *source = NULL;
571 unsigned short *dest = NULL;
572
573 for (int y = 0; y < height; y++)
574 {
575 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
576 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
577 for (int x = 0; x < width; x++)
578 {
579 dest[4 * x + 0] = source[x];
580 dest[4 * x + 1] = source[x];
581 dest[4 * x + 2] = source[x];
582 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
583 }
584 }
585}
586
587void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
588 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
589{
590 const int destBytesPerPixel = native? 2: 4;
591 const unsigned char *source = NULL;
592 unsigned char *dest = NULL;
593
594 for (int y = 0; y < height; y++)
595 {
596 source = static_cast<const unsigned char*>(input) + y * inputPitch;
597 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
598
599 if (!native) // BGRA8 destination format
600 {
601 for (int x = 0; x < width; x++)
602 {
603 dest[4 * x + 0] = source[2*x+0];
604 dest[4 * x + 1] = source[2*x+0];
605 dest[4 * x + 2] = source[2*x+0];
606 dest[4 * x + 3] = source[2*x+1];
607 }
608 }
609 else
610 {
611 memcpy(dest, source, width * 2);
612 }
613 }
614}
615
616void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
617 int inputPitch, const void *input, size_t outputPitch, void *output) const
618{
619 const float *source = NULL;
620 float *dest = NULL;
621
622 for (int y = 0; y < height; y++)
623 {
624 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
625 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
626 for (int x = 0; x < width; x++)
627 {
628 dest[4 * x + 0] = source[2*x+0];
629 dest[4 * x + 1] = source[2*x+0];
630 dest[4 * x + 2] = source[2*x+0];
631 dest[4 * x + 3] = source[2*x+1];
632 }
633 }
634}
635
636void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
637 int inputPitch, const void *input, size_t outputPitch, void *output) const
638{
639 const unsigned short *source = NULL;
640 unsigned short *dest = NULL;
641
642 for (int y = 0; y < height; y++)
643 {
644 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
645 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
646 for (int x = 0; x < width; x++)
647 {
648 dest[4 * x + 0] = source[2*x+0];
649 dest[4 * x + 1] = source[2*x+0];
650 dest[4 * x + 2] = source[2*x+0];
651 dest[4 * x + 3] = source[2*x+1];
652 }
653 }
654}
655
656void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
657 int inputPitch, const void *input, size_t outputPitch, void *output) const
658{
659 const unsigned char *source = NULL;
660 unsigned char *dest = NULL;
661
662 for (int y = 0; y < height; y++)
663 {
664 source = static_cast<const unsigned char*>(input) + y * inputPitch;
665 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
666 for (int x = 0; x < width; x++)
667 {
668 dest[4 * x + 0] = source[x * 3 + 2];
669 dest[4 * x + 1] = source[x * 3 + 1];
670 dest[4 * x + 2] = source[x * 3 + 0];
671 dest[4 * x + 3] = 0xFF;
672 }
673 }
674}
675
676void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
677 int inputPitch, const void *input, size_t outputPitch, void *output) const
678{
679 const unsigned short *source = NULL;
680 unsigned char *dest = NULL;
681
682 for (int y = 0; y < height; y++)
683 {
684 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
685 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
686 for (int x = 0; x < width; x++)
687 {
688 unsigned short rgba = source[x];
689 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
690 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
691 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
692 dest[4 * x + 3] = 0xFF;
693 }
694 }
695}
696
697void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
698 int inputPitch, const void *input, size_t outputPitch, void *output) const
699{
700 const float *source = NULL;
701 float *dest = NULL;
702
703 for (int y = 0; y < height; y++)
704 {
705 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
706 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
707 for (int x = 0; x < width; x++)
708 {
709 dest[4 * x + 0] = source[x * 3 + 0];
710 dest[4 * x + 1] = source[x * 3 + 1];
711 dest[4 * x + 2] = source[x * 3 + 2];
712 dest[4 * x + 3] = 1.0f;
713 }
714 }
715}
716
717void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
718 int inputPitch, const void *input, size_t outputPitch, void *output) const
719{
720 const unsigned short *source = NULL;
721 unsigned short *dest = NULL;
722
723 for (int y = 0; y < height; y++)
724 {
725 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
726 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
727 for (int x = 0; x < width; x++)
728 {
729 dest[4 * x + 0] = source[x * 3 + 0];
730 dest[4 * x + 1] = source[x * 3 + 1];
731 dest[4 * x + 2] = source[x * 3 + 2];
732 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
733 }
734 }
735}
736
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000737void Texture::loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
738 int inputPitch, const void *input, size_t outputPitch, void *output) const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000739{
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000740 const unsigned int *source = NULL;
741 unsigned int *dest = NULL;
742 __m128i brMask = _mm_set1_epi32(0x00ff00ff);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000743
744 for (int y = 0; y < height; y++)
745 {
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000746 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
747 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
748 int x = 0;
749
750 // Make output writes aligned
751 for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
752 {
753 unsigned int rgba = source[x];
754 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
755 }
756
757 for (; x + 3 < width; x += 4)
758 {
759 __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
760 // Mask out g and a, which don't change
761 __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
762 // Mask out b and r
763 __m128i brComponents = _mm_and_si128(sourceData, brMask);
764 // Swap b and r
765 __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
766 __m128i result = _mm_or_si128(gaComponents, brSwapped);
767 _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
768 }
769
770 // Perform leftover writes
771 for (; x < width; x++)
772 {
773 unsigned int rgba = source[x];
774 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
775 }
776 }
777}
778
779void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
780 int inputPitch, const void *input, size_t outputPitch, void *output) const
781{
782 const unsigned int *source = NULL;
783 unsigned int *dest = NULL;
784 for (int y = 0; y < height; y++)
785 {
786 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
787 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
788
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000789 for (int x = 0; x < width; x++)
790 {
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000791 unsigned int rgba = source[x];
792 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000793 }
794 }
795}
796
797void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
798 int inputPitch, const void *input, size_t outputPitch, void *output) const
799{
800 const unsigned short *source = NULL;
801 unsigned char *dest = NULL;
802
803 for (int y = 0; y < height; y++)
804 {
805 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
806 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
807 for (int x = 0; x < width; x++)
808 {
809 unsigned short rgba = source[x];
810 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
811 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
812 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
813 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
814 }
815 }
816}
817
818void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
819 int inputPitch, const void *input, size_t outputPitch, void *output) const
820{
821 const unsigned short *source = NULL;
822 unsigned char *dest = NULL;
823
824 for (int y = 0; y < height; y++)
825 {
826 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
827 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
828 for (int x = 0; x < width; x++)
829 {
830 unsigned short rgba = source[x];
831 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
832 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
833 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
834 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
835 }
836 }
837}
838
839void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
840 int inputPitch, const void *input, size_t outputPitch, void *output) const
841{
842 const float *source = NULL;
843 float *dest = NULL;
844
845 for (int y = 0; y < height; y++)
846 {
847 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
848 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
849 memcpy(dest, source, width * 16);
850 }
851}
852
853void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
854 int inputPitch, const void *input, size_t outputPitch, void *output) const
855{
856 const unsigned char *source = NULL;
857 unsigned char *dest = NULL;
858
859 for (int y = 0; y < height; y++)
860 {
861 source = static_cast<const unsigned char*>(input) + y * inputPitch;
862 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8;
863 memcpy(dest, source, width * 8);
864 }
865}
866
867void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
868 int inputPitch, const void *input, size_t outputPitch, void *output) const
869{
870 const unsigned char *source = NULL;
871 unsigned char *dest = NULL;
872
873 for (int y = 0; y < height; y++)
874 {
875 source = static_cast<const unsigned char*>(input) + y * inputPitch;
876 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
877 memcpy(dest, source, width*4);
878 }
879}
880
881void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
gman@chromium.org50c526d2011-08-10 05:19:44 +0000882 int inputPitch, const void *input, size_t outputPitch, void *output) const {
883 switch (getD3DFormat())
884 {
885 case D3DFMT_DXT1:
886 loadDXT1ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
887 break;
888 case D3DFMT_DXT3:
889 loadDXT3ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
890 break;
891 case D3DFMT_DXT5:
892 loadDXT5ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
893 break;
894 }
895}
896
897static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
898 // A DXT1 block layout is:
899 // [0-1] color0.
900 // [2-3] color1.
901 // [4-7] color bitmap, 2 bits per pixel.
902 // So each of the 4-7 bytes represents one line, flipping a block is just
903 // flipping those bytes.
904
905 // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
906 dest[0] = source[0];
907
908 // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
909 dest[1] = (source[1] >> 24) |
910 ((source[1] << 8) & 0x00FF0000) |
911 ((source[1] >> 8) & 0x0000FF00) |
912 (source[1] << 24);
913}
914
915// Flips the first 2 lines of a DXT1 block in the y direction.
916static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
917 // See layout above.
918 dest[0] = source[0];
919 dest[1] = ((source[1] << 8) & 0x0000FF00) |
920 ((source[1] >> 8) & 0x000000FF);
921}
922
923// Flips a full DXT3 block in the y direction.
924static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
925 // A DXT3 block layout is:
926 // [0-7] alpha bitmap, 4 bits per pixel.
927 // [8-15] a DXT1 block.
928
929 // First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
930 dest[0] = (source[1] >> 16) | (source[1] << 16);
931 dest[1] = (source[0] >> 16) | (source[0] << 16);
932
933 // And flip the DXT1 block using the above function.
934 FlipCopyDXT1BlockFull(source + 2, dest + 2);
935}
936
937// Flips the first 2 lines of a DXT3 block in the y direction.
938static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
939 // See layout above.
940 dest[0] = (source[1] >> 16) | (source[1] << 16);
941 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
942}
943
944// Flips a full DXT5 block in the y direction.
945static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
946 // A DXT5 block layout is:
947 // [0] alpha0.
948 // [1] alpha1.
949 // [2-7] alpha bitmap, 3 bits per pixel.
950 // [8-15] a DXT1 block.
951
952 // The alpha bitmap doesn't easily map lines to bytes, so we have to
953 // interpret it correctly. Extracted from
954 // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
955 //
956 // The 6 "bits" bytes of the block are decoded into one 48-bit integer:
957 //
958 // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
959 // 256 * (bits_4 + 256 * bits_5))))
960 //
961 // bits is a 48-bit unsigned integer, from which a three-bit control code
962 // is extracted for a texel at location (x,y) in the block using:
963 //
964 // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
965 //
966 // where bit 47 is the most significant and bit 0 is the least
967 // significant bit.
968 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
969 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
970 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
971 unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
972 // swap lines 0 and 1 in line_0_1.
973 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
974 ((line_0_1 & 0xfff000) >> 12);
975 // swap lines 2 and 3 in line_2_3.
976 unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
977 ((line_2_3 & 0xfff000) >> 12);
978 destBytes[0] = sourceBytes[0];
979 destBytes[1] = sourceBytes[1];
980 destBytes[2] = line_3_2 & 0xff;
981 destBytes[3] = (line_3_2 & 0xff00) >> 8;
gman@chromium.org2ac3e732011-08-10 07:59:47 +0000982 destBytes[4] = (line_3_2 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000983 destBytes[5] = line_1_0 & 0xff;
984 destBytes[6] = (line_1_0 & 0xff00) >> 8;
gman@chromium.org2ac3e732011-08-10 07:59:47 +0000985 destBytes[7] = (line_1_0 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000986
987 // And flip the DXT1 block using the above function.
988 FlipCopyDXT1BlockFull(source + 2, dest + 2);
989}
990
991// Flips the first 2 lines of a DXT5 block in the y direction.
992static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
993 // See layout above.
994 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
995 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
996 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
997 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
998 ((line_0_1 & 0xfff000) >> 12);
999 destBytes[0] = sourceBytes[0];
1000 destBytes[1] = sourceBytes[1];
1001 destBytes[2] = line_1_0 & 0xff;
1002 destBytes[3] = (line_1_0 & 0xff00) >> 8;
gman@chromium.org25c5cf62011-08-10 08:07:54 +00001003 destBytes[4] = (line_1_0 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +00001004 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
1005}
1006
1007void Texture::loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001008 int inputPitch, const void *input, size_t outputPitch, void *output) const
1009{
1010 ASSERT(xoffset % 4 == 0);
1011 ASSERT(yoffset % 4 == 0);
1012 ASSERT(width % 4 == 0 || width == 2 || width == 1);
1013 ASSERT(inputPitch % 8 == 0);
1014 ASSERT(outputPitch % 8 == 0);
1015
1016 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
1017 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
1018
gman@chromium.org50c526d2011-08-10 05:19:44 +00001019 // Round width up in case it is less than 4.
1020 int blocksAcross = (width + 3) / 4;
1021 int intsAcross = blocksAcross * 2;
1022
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001023 switch (height)
1024 {
1025 case 1:
gman@chromium.org50c526d2011-08-10 05:19:44 +00001026 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001027 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001028 // just copy the block
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001029 dest[x] = source[x];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001030 dest[x + 1] = source[x + 1];
1031 }
1032 break;
1033 case 2:
gman@chromium.org50c526d2011-08-10 05:19:44 +00001034 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001035 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001036 FlipCopyDXT1BlockHalf(source + x, dest + x);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001037 }
1038 break;
1039 default:
1040 ASSERT(height % 4 == 0);
1041 for (int y = 0; y < height / 4; ++y)
1042 {
1043 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1044 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
1045
gman@chromium.org50c526d2011-08-10 05:19:44 +00001046 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001047 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001048 FlipCopyDXT1BlockFull(source + x, dest + x);
1049 }
1050 }
1051 break;
1052 }
1053}
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001054
gman@chromium.org50c526d2011-08-10 05:19:44 +00001055void Texture::loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
1056 int inputPitch, const void *input, size_t outputPitch, void *output) const
1057{
1058 ASSERT(xoffset % 4 == 0);
1059 ASSERT(yoffset % 4 == 0);
1060 ASSERT(width % 4 == 0 || width == 2 || width == 1);
1061 ASSERT(inputPitch % 16 == 0);
1062 ASSERT(outputPitch % 16 == 0);
1063
1064 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
1065 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
1066
1067 // Round width up in case it is less than 4.
1068 int blocksAcross = (width + 3) / 4;
1069 int intsAcross = blocksAcross * 4;
1070
1071 switch (height)
1072 {
1073 case 1:
1074 for (int x = 0; x < intsAcross; x += 4)
1075 {
1076 // just copy the block
1077 dest[x] = source[x];
1078 dest[x + 1] = source[x + 1];
1079 dest[x + 2] = source[x + 2];
1080 dest[x + 3] = source[x + 3];
1081 }
1082 break;
1083 case 2:
1084 for (int x = 0; x < intsAcross; x += 4)
1085 {
1086 FlipCopyDXT3BlockHalf(source + x, dest + x);
1087 }
1088 break;
1089 default:
1090 ASSERT(height % 4 == 0);
1091 for (int y = 0; y < height / 4; ++y)
1092 {
1093 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1094 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
1095
1096 for (int x = 0; x < intsAcross; x += 4)
1097 {
1098 FlipCopyDXT3BlockFull(source + x, dest + x);
1099 }
1100 }
1101 break;
1102 }
1103}
1104
1105void Texture::loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
1106 int inputPitch, const void *input, size_t outputPitch, void *output) const
1107{
1108 ASSERT(xoffset % 4 == 0);
1109 ASSERT(yoffset % 4 == 0);
1110 ASSERT(width % 4 == 0 || width == 2 || width == 1);
1111 ASSERT(inputPitch % 16 == 0);
1112 ASSERT(outputPitch % 16 == 0);
1113
1114 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
1115 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
1116
1117 // Round width up in case it is less than 4.
1118 int blocksAcross = (width + 3) / 4;
1119 int intsAcross = blocksAcross * 4;
1120
1121 switch (height)
1122 {
1123 case 1:
1124 for (int x = 0; x < intsAcross; x += 4)
1125 {
1126 // just copy the block
1127 dest[x] = source[x];
1128 dest[x + 1] = source[x + 1];
1129 dest[x + 2] = source[x + 2];
1130 dest[x + 3] = source[x + 3];
1131 }
1132 break;
1133 case 2:
1134 for (int x = 0; x < intsAcross; x += 4)
1135 {
1136 FlipCopyDXT5BlockHalf(source + x, dest + x);
1137 }
1138 break;
1139 default:
1140 ASSERT(height % 4 == 0);
gman@chromium.org2ac3e732011-08-10 07:59:47 +00001141 for (int y = 0; y < height / 4; ++y)
gman@chromium.org50c526d2011-08-10 05:19:44 +00001142 {
1143 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1144 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
1145
1146 for (int x = 0; x < intsAcross; x += 4)
1147 {
1148 FlipCopyDXT5BlockFull(source + x, dest + x);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001149 }
1150 }
1151 break;
1152 }
1153}
1154
daniel@transgaming.com61208202011-03-21 16:38:50 +00001155void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001156{
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001157 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001158 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001159 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001160 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001161
1162 if (SUCCEEDED(result))
1163 {
daniel@transgaming.com6e4b1212011-11-09 17:45:28 +00001164 loadImageData(0, 0, image->getWidth(), image->getHeight(), image->getFormat(), image->getType(), unpackAlignment, pixels, locked.Pitch, locked.pBits, image->getD3DFormat());
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001165 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001166 }
1167
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001168 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001169 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001170 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001171}
1172
daniel@transgaming.com61208202011-03-21 16:38:50 +00001173void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001174{
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001175 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001176 {
1177 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001178 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001179
1180 if (SUCCEEDED(result))
1181 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001182 int inputPitch = ComputeCompressedPitch(image->getWidth(), image->getFormat());
1183 int inputSize = ComputeCompressedSize(image->getWidth(), image->getHeight(), image->getFormat());
1184 loadCompressedImageData(0, 0, image->getWidth(), image->getHeight(), -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001185 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001186 }
1187
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001188 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001189 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001190 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001191}
1192
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001193bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001194{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001195 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001196 {
1197 error(GL_INVALID_VALUE);
1198 return false;
1199 }
1200
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001201 if (IsCompressed(image->getFormat()))
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001202 {
1203 error(GL_INVALID_OPERATION);
1204 return false;
1205 }
1206
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001207 if (format != image->getFormat())
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001208 {
1209 error(GL_INVALID_OPERATION);
1210 return false;
1211 }
1212
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001213 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001214 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001215 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001216 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001217
1218 if (SUCCEEDED(result))
1219 {
daniel@transgaming.com6e4b1212011-11-09 17:45:28 +00001220 loadImageData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, image->getD3DFormat());
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001221 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001222 }
1223
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001224 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001225 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001226 }
1227
1228 return true;
1229}
1230
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001231bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001232{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001233 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001234 {
1235 error(GL_INVALID_VALUE);
1236 return false;
1237 }
1238
1239 if (format != getInternalFormat())
1240 {
1241 error(GL_INVALID_OPERATION);
1242 return false;
1243 }
1244
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001245 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001246 {
1247 RECT updateRegion;
1248 updateRegion.left = xoffset;
1249 updateRegion.right = xoffset + width;
1250 updateRegion.bottom = yoffset + height;
1251 updateRegion.top = yoffset;
1252
1253 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001254 HRESULT result = image->lock(&locked, &updateRegion);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001255
1256 if (SUCCEEDED(result))
1257 {
1258 int inputPitch = ComputeCompressedPitch(width, format);
1259 int inputSize = ComputeCompressedSize(width, height, format);
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001260 loadCompressedImageData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001261 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001262 }
1263
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001264 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001265 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001266 }
1267
1268 return true;
1269}
1270
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001271// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
1272void Texture::copyToImage(Image *image, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001273{
1274 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001275 IDirect3DSurface9 *renderTargetData = NULL;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001276 D3DSURFACE_DESC description;
1277 renderTarget->GetDesc(&description);
1278
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001279 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001280
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001281 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001282 {
1283 ERR("Could not create matching destination surface.");
1284 return error(GL_OUT_OF_MEMORY);
1285 }
1286
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001287 result = device->GetRenderTargetData(renderTarget, renderTargetData);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001288
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001289 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001290 {
1291 ERR("GetRenderTargetData unexpectedly failed.");
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001292 renderTargetData->Release();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001293 return error(GL_OUT_OF_MEMORY);
1294 }
1295
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001296 RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001297 int destYOffset = transformPixelYOffset(yoffset, height, image->getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001298 RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001299
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001300 if (image->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001301 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001302 result = D3DXLoadSurfaceFromSurface(image->getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001303
1304 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001305 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001306 ERR("Copying surfaces unexpectedly failed.");
1307 renderTargetData->Release();
1308 return error(GL_OUT_OF_MEMORY);
1309 }
1310 }
1311 else
1312 {
1313 D3DLOCKED_RECT sourceLock = {0};
1314 result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001315
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001316 if (FAILED(result))
1317 {
1318 ERR("Failed to lock the source surface (rectangle might be invalid).");
1319 renderTargetData->Release();
1320 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001321 }
1322
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001323 D3DLOCKED_RECT destLock = {0};
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001324 result = image->lock(&destLock, &destRect);
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001325
1326 if (FAILED(result))
1327 {
1328 ERR("Failed to lock the destination surface (rectangle might be invalid).");
1329 renderTargetData->UnlockRect();
1330 renderTargetData->Release();
1331 return error(GL_OUT_OF_MEMORY);
1332 }
1333
1334 if (destLock.pBits && sourceLock.pBits)
1335 {
1336 unsigned char *source = (unsigned char*)sourceLock.pBits;
1337 unsigned char *dest = (unsigned char*)destLock.pBits;
1338
1339 switch (description.Format)
1340 {
1341 case D3DFMT_X8R8G8B8:
1342 case D3DFMT_A8R8G8B8:
1343 switch(image->getD3DFormat())
1344 {
1345 case D3DFMT_L8:
1346 for(int y = 0; y < height; y++)
1347 {
1348 for(int x = 0; x < width; x++)
1349 {
1350 dest[x] = source[x * 4 + 2];
1351 }
1352
1353 source += sourceLock.Pitch;
1354 dest += destLock.Pitch;
1355 }
1356 break;
1357 case D3DFMT_A8L8:
1358 for(int y = 0; y < height; y++)
1359 {
1360 for(int x = 0; x < width; x++)
1361 {
1362 dest[x * 2 + 0] = source[x * 4 + 2];
1363 dest[x * 2 + 1] = source[x * 4 + 3];
1364 }
1365
1366 source += sourceLock.Pitch;
1367 dest += destLock.Pitch;
1368 }
1369 break;
1370 default:
1371 UNREACHABLE();
1372 }
1373 break;
1374 case D3DFMT_R5G6B5:
1375 switch(image->getD3DFormat())
1376 {
1377 case D3DFMT_L8:
1378 for(int y = 0; y < height; y++)
1379 {
1380 for(int x = 0; x < width; x++)
1381 {
1382 unsigned char red = source[x * 2 + 1] & 0xF8;
1383 dest[x] = red | (red >> 5);
1384 }
1385
1386 source += sourceLock.Pitch;
1387 dest += destLock.Pitch;
1388 }
1389 break;
1390 default:
1391 UNREACHABLE();
1392 }
1393 break;
1394 case D3DFMT_A1R5G5B5:
1395 switch(image->getD3DFormat())
1396 {
1397 case D3DFMT_L8:
1398 for(int y = 0; y < height; y++)
1399 {
1400 for(int x = 0; x < width; x++)
1401 {
1402 unsigned char red = source[x * 2 + 1] & 0x7C;
1403 dest[x] = (red << 1) | (red >> 4);
1404 }
1405
1406 source += sourceLock.Pitch;
1407 dest += destLock.Pitch;
1408 }
1409 break;
1410 case D3DFMT_A8L8:
1411 for(int y = 0; y < height; y++)
1412 {
1413 for(int x = 0; x < width; x++)
1414 {
1415 unsigned char red = source[x * 2 + 1] & 0x7C;
1416 dest[x * 2 + 0] = (red << 1) | (red >> 4);
1417 dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
1418 }
1419
1420 source += sourceLock.Pitch;
1421 dest += destLock.Pitch;
1422 }
1423 break;
1424 default:
1425 UNREACHABLE();
1426 }
1427 break;
1428 default:
1429 UNREACHABLE();
1430 }
1431 }
1432
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001433 image->unlock();
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001434 renderTargetData->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001435 }
1436
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001437 renderTargetData->Release();
1438
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001439 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001440 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001441}
1442
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001443IDirect3DBaseTexture9 *Texture::getTexture()
1444{
1445 if (!isComplete())
1446 {
1447 return NULL;
1448 }
1449
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001450 if (!getBaseTexture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001451 {
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001452 createTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001453 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001454
daniel@transgaming.comc50edcb2011-03-21 16:38:40 +00001455 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001456
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001457 return getBaseTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001458}
1459
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001460bool Texture::hasDirtyParameters() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001461{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001462 return mDirtyParameters;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001463}
1464
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001465bool Texture::hasDirtyImages() const
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001466{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001467 return mDirtyImages;
daniel@transgaming.com38e76e52011-03-21 16:39:10 +00001468}
1469
1470void Texture::resetDirty()
1471{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001472 mDirtyParameters = false;
1473 mDirtyImages = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001474}
1475
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001476unsigned int Texture::getSerial() const
1477{
1478 return mSerial;
1479}
1480
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001481GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
1482{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001483 if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001484 {
1485 return maxlevel;
1486 }
1487 else
1488 {
1489 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1490 return 1;
1491 }
1492}
1493
1494GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
1495{
1496 return creationLevels(size, size, maxlevel);
1497}
1498
1499int Texture::levelCount() const
1500{
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001501 return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001502}
1503
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001504unsigned int Texture::issueSerial()
1505{
1506 return mCurrentSerial++;
1507}
1508
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001509Texture2D::Texture2D(GLuint id) : Texture(id)
1510{
1511 mTexture = NULL;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001512 mSurface = NULL;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001513}
1514
1515Texture2D::~Texture2D()
1516{
1517 mColorbufferProxy.set(NULL);
1518
1519 if (mTexture)
1520 {
1521 mTexture->Release();
1522 mTexture = NULL;
1523 }
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001524
1525 if (mSurface)
1526 {
1527 mSurface->setBoundTexture(NULL);
1528 mSurface = NULL;
1529 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001530}
1531
1532GLenum Texture2D::getTarget() const
1533{
1534 return GL_TEXTURE_2D;
1535}
1536
daniel@transgaming.com61208202011-03-21 16:38:50 +00001537GLsizei Texture2D::getWidth() const
1538{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001539 return mImageArray[0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001540}
1541
1542GLsizei Texture2D::getHeight() const
1543{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001544 return mImageArray[0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001545}
1546
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001547GLenum Texture2D::getInternalFormat() const
1548{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001549 return mImageArray[0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001550}
1551
daniel@transgaming.com61208202011-03-21 16:38:50 +00001552GLenum Texture2D::getType() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001553{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001554 return mImageArray[0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001555}
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001556
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001557D3DFORMAT Texture2D::getD3DFormat() const
1558{
1559 return mImageArray[0].getD3DFormat();
1560}
1561
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001562void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRedefine)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001563{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001564 GLsizei textureWidth = mImageArray[0].getWidth();
1565 GLsizei textureHeight = mImageArray[0].getHeight();
1566 GLenum textureFormat = mImageArray[0].getFormat();
1567 GLenum textureType = mImageArray[0].getType();
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00001568
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001569 mImageArray[level].redefine(format, width, height, type);
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00001570
daniel@transgaming.com61208202011-03-21 16:38:50 +00001571 if (!mTexture)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001572 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001573 return;
1574 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001575
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00001576 bool widthOkay = (textureWidth >> level == width) || (textureWidth >> level == 0 && width == 1);
1577 bool heightOkay = (textureHeight >> level == height) || (textureHeight >> level == 0 && height == 1);
1578 bool textureOkay = (widthOkay && heightOkay && textureFormat == format && textureType == type);
daniel@transgaming.com61208202011-03-21 16:38:50 +00001579
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00001580 if (!textureOkay || forceRedefine || mSurface)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001581 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001582 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1583 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001584 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001585 }
1586
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001587 mTexture->Release();
1588 mTexture = NULL;
1589 mDirtyImages = true;
1590 mIsRenderable = false;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001591
1592 if (mSurface)
1593 {
1594 mSurface->setBoundTexture(NULL);
1595 mSurface = NULL;
1596 }
apatrick@chromium.org57a2cd62011-06-08 00:04:07 +00001597
1598 mColorbufferProxy.set(NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001599 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001600}
1601
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001602void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001603{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001604 redefineImage(level, format, width, height, type, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001605
daniel@transgaming.com61208202011-03-21 16:38:50 +00001606 Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001607}
1608
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001609void Texture2D::bindTexImage(egl::Surface *surface)
1610{
1611 GLenum format;
1612
1613 switch(surface->getFormat())
1614 {
1615 case D3DFMT_A8R8G8B8:
1616 format = GL_RGBA;
1617 break;
1618 case D3DFMT_X8R8G8B8:
1619 format = GL_RGB;
1620 break;
1621 default:
1622 UNIMPLEMENTED();
1623 return;
1624 }
1625
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001626 redefineImage(0, format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001627
1628 IDirect3DTexture9 *texture = surface->getOffscreenTexture();
1629
1630 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001631 mDirtyImages = true;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001632 mIsRenderable = true;
1633 mSurface = surface;
1634 mSurface->setBoundTexture(this);
1635}
1636
1637void Texture2D::releaseTexImage()
1638{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001639 redefineImage(0, GL_RGB, 0, 0, GL_UNSIGNED_BYTE, true);
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001640}
1641
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001642void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001643{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001644 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001645
daniel@transgaming.com61208202011-03-21 16:38:50 +00001646 Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001647}
1648
1649void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1650{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001651 ASSERT(mImageArray[level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001652
1653 if (level < levelCount())
1654 {
1655 IDirect3DSurface9 *destLevel = NULL;
1656 HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
1657
1658 ASSERT(SUCCEEDED(result));
1659
1660 if (SUCCEEDED(result))
1661 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001662 Image *image = &mImageArray[level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001663
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001664 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());;
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001665 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001666
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001667 result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001668 ASSERT(SUCCEEDED(result));
1669
1670 destLevel->Release();
1671
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001672 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001673 }
1674 }
1675}
1676
1677void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
1678{
1679 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1680 {
1681 commitRect(level, xoffset, yoffset, width, height);
1682 }
1683}
1684
1685void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1686{
1687 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1688 {
1689 commitRect(level, xoffset, yoffset, width, height);
1690 }
1691}
1692
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001693void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001694{
1695 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1696
1697 if (!renderTarget)
1698 {
1699 ERR("Failed to retrieve the render target.");
1700 return error(GL_OUT_OF_MEMORY);
1701 }
1702
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001703 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001704
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001705 if (!mImageArray[level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001706 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001707 copyToImage(&mImageArray[level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001708 }
1709 else
1710 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001711 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001712 {
1713 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001714 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00001715
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001716 mImageArray[level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001717
1718 if (width != 0 && height != 0 && level < levelCount())
1719 {
1720 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1721 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1722 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1723 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1724 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001725
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001726 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001727
1728 IDirect3DSurface9 *dest;
1729 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
1730
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001731 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001732 dest->Release();
1733 }
1734 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001735}
1736
1737void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1738{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001739 if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001740 {
1741 return error(GL_INVALID_VALUE);
1742 }
1743
1744 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1745
1746 if (!renderTarget)
1747 {
1748 ERR("Failed to retrieve the render target.");
1749 return error(GL_OUT_OF_MEMORY);
1750 }
1751
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001752 if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001753 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001754 copyToImage(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001755 }
1756 else
1757 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001758 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001759 {
1760 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001761 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00001762
1763 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001764
1765 if (level < levelCount())
1766 {
1767 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1768 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1769 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1770 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1771 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
1772
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001773 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001774
1775 IDirect3DSurface9 *dest;
1776 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
1777
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001778 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001779 dest->Release();
1780 }
1781 }
1782}
1783
1784// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1785bool Texture2D::isComplete() const
1786{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001787 GLsizei width = mImageArray[0].getWidth();
1788 GLsizei height = mImageArray[0].getHeight();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001789
1790 if (width <= 0 || height <= 0)
1791 {
1792 return false;
1793 }
1794
1795 bool mipmapping = false;
1796
1797 switch (mMinFilter)
1798 {
1799 case GL_NEAREST:
1800 case GL_LINEAR:
1801 mipmapping = false;
1802 break;
1803 case GL_NEAREST_MIPMAP_NEAREST:
1804 case GL_LINEAR_MIPMAP_NEAREST:
1805 case GL_NEAREST_MIPMAP_LINEAR:
1806 case GL_LINEAR_MIPMAP_LINEAR:
1807 mipmapping = true;
1808 break;
1809 default: UNREACHABLE();
1810 }
1811
1812 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1813 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1814 {
1815 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1816 {
1817 return false;
1818 }
1819 }
1820
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001821 bool npot = getContext()->supportsNonPower2Texture();
1822
1823 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001824 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001825 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
1826 (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1827 {
1828 return false;
1829 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001830 }
1831
1832 if (mipmapping)
1833 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001834 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001835 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001836 if (!isPow2(width) || !isPow2(height))
1837 {
1838 return false;
1839 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001840 }
1841
1842 int q = log2(std::max(width, height));
1843
1844 for (int level = 1; level <= q; level++)
1845 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001846 if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001847 {
1848 return false;
1849 }
1850
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001851 if (mImageArray[level].getType() != mImageArray[0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00001852 {
1853 return false;
1854 }
1855
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001856 if (mImageArray[level].getWidth() != std::max(1, width >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001857 {
1858 return false;
1859 }
1860
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001861 if (mImageArray[level].getHeight() != std::max(1, height >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001862 {
1863 return false;
1864 }
1865 }
1866 }
1867
1868 return true;
1869}
1870
1871bool Texture2D::isCompressed() const
1872{
1873 return IsCompressed(getInternalFormat());
1874}
1875
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001876IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
1877{
1878 return mTexture;
1879}
1880
1881// Constructs a Direct3D 9 texture resource from the texture images
1882void Texture2D::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001883{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001884 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001885 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001886 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001887
daniel@transgaming.com61208202011-03-21 16:38:50 +00001888 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001889 HRESULT result = device->CreateTexture(mImageArray[0].getWidth(), mImageArray[0].getHeight(), levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001890
1891 if (FAILED(result))
1892 {
1893 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001894 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001895 }
1896
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001897 if (mTexture)
1898 {
1899 mTexture->Release();
1900 }
1901
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001902 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001903 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001904 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001905}
1906
1907void Texture2D::updateTexture()
1908{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001909 int levels = levelCount();
1910
1911 for (int level = 0; level < levels; level++)
1912 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001913 Image *image = &mImageArray[level];
1914
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001915 if (image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001916 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001917 commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001918 }
1919 }
1920}
1921
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001922void Texture2D::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001923{
1924 IDirect3DTexture9 *texture = NULL;
1925
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001926 if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001927 {
1928 egl::Display *display = getDisplay();
1929 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001930 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001931 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001932
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001933 HRESULT result = device->CreateTexture(mImageArray[0].getWidth(), mImageArray[0].getHeight(), levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001934
1935 if (FAILED(result))
1936 {
1937 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001938 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001939 }
1940
1941 if (mTexture != NULL)
1942 {
1943 int levels = levelCount();
1944 for (int i = 0; i < levels; i++)
1945 {
1946 IDirect3DSurface9 *source;
1947 result = mTexture->GetSurfaceLevel(i, &source);
1948
1949 if (FAILED(result))
1950 {
1951 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1952
1953 texture->Release();
1954
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001955 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001956 }
1957
1958 IDirect3DSurface9 *dest;
1959 result = texture->GetSurfaceLevel(i, &dest);
1960
1961 if (FAILED(result))
1962 {
1963 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1964
1965 texture->Release();
1966 source->Release();
1967
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001968 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001969 }
1970
1971 display->endScene();
1972 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1973
1974 if (FAILED(result))
1975 {
1976 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1977
1978 texture->Release();
1979 source->Release();
1980 dest->Release();
1981
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001982 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001983 }
1984
1985 source->Release();
1986 dest->Release();
1987 }
1988 }
1989 }
1990
1991 if (mTexture != NULL)
1992 {
1993 mTexture->Release();
1994 }
1995
1996 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001997 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001998 mIsRenderable = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001999}
2000
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002001void Texture2D::generateMipmaps()
2002{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002003 if (!getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002004 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002005 if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002006 {
2007 return error(GL_INVALID_OPERATION);
2008 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002009 }
2010
2011 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002012 unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002013 for (unsigned int i = 1; i <= q; i++)
2014 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002015 mImageArray[i].redefine(mImageArray[0].getFormat(),
2016 std::max(mImageArray[0].getWidth() >> i, 1),
2017 std::max(mImageArray[0].getHeight() >> i, 1),
2018 mImageArray[0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002019 }
2020
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002021 if (mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002022 {
2023 if (mTexture == NULL)
2024 {
2025 ERR(" failed because mTexture was null.");
2026 return;
2027 }
2028
2029 for (unsigned int i = 1; i <= q; i++)
2030 {
2031 IDirect3DSurface9 *upper = NULL;
2032 IDirect3DSurface9 *lower = NULL;
2033
2034 mTexture->GetSurfaceLevel(i-1, &upper);
2035 mTexture->GetSurfaceLevel(i, &lower);
2036
2037 if (upper != NULL && lower != NULL)
2038 {
2039 getBlitter()->boxFilter(upper, lower);
2040 }
2041
2042 if (upper != NULL) upper->Release();
2043 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002044
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002045 mImageArray[i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002046 }
2047 }
2048 else
2049 {
2050 for (unsigned int i = 1; i <= q; i++)
2051 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002052 if (mImageArray[i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002053 {
2054 return error(GL_OUT_OF_MEMORY);
2055 }
2056
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002057 if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].getSurface(), NULL, NULL, mImageArray[i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002058 {
2059 ERR(" failed to load filter %d to %d.", i - 1, i);
2060 }
2061
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002062 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002063 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002064 }
2065}
2066
2067Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
2068{
2069 if (target != GL_TEXTURE_2D)
2070 {
2071 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2072 }
2073
2074 if (mColorbufferProxy.get() == NULL)
2075 {
2076 mColorbufferProxy.set(new Renderbuffer(id(), new Colorbuffer(this, target)));
2077 }
2078
2079 return mColorbufferProxy.get();
2080}
2081
2082IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
2083{
2084 ASSERT(target == GL_TEXTURE_2D);
2085
daniel@transgaming.com61208202011-03-21 16:38:50 +00002086 if (!mIsRenderable)
2087 {
2088 convertToRenderTarget();
2089 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002090
2091 if (mTexture == NULL)
2092 {
2093 return NULL;
2094 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002095
2096 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002097
2098 IDirect3DSurface9 *renderTarget = NULL;
2099 mTexture->GetSurfaceLevel(0, &renderTarget);
2100
2101 return renderTarget;
2102}
2103
2104TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
2105{
2106 mTexture = NULL;
2107}
2108
2109TextureCubeMap::~TextureCubeMap()
2110{
2111 for (int i = 0; i < 6; i++)
2112 {
2113 mFaceProxies[i].set(NULL);
2114 }
2115
2116 if (mTexture)
2117 {
2118 mTexture->Release();
2119 mTexture = NULL;
2120 }
2121}
2122
2123GLenum TextureCubeMap::getTarget() const
2124{
2125 return GL_TEXTURE_CUBE_MAP;
2126}
2127
daniel@transgaming.com61208202011-03-21 16:38:50 +00002128GLsizei TextureCubeMap::getWidth() const
2129{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002130 return mImageArray[0][0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002131}
2132
2133GLsizei TextureCubeMap::getHeight() const
2134{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002135 return mImageArray[0][0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002136}
2137
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002138GLenum TextureCubeMap::getInternalFormat() const
2139{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002140 return mImageArray[0][0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002141}
2142
daniel@transgaming.com61208202011-03-21 16:38:50 +00002143GLenum TextureCubeMap::getType() const
2144{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002145 return mImageArray[0][0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002146}
2147
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002148D3DFORMAT TextureCubeMap::getD3DFormat() const
2149{
2150 return mImageArray[0][0].getD3DFormat();
2151}
2152
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002153void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002154{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002155 setImage(0, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002156}
2157
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002158void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002159{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002160 setImage(1, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002161}
2162
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002163void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002164{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002165 setImage(2, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002166}
2167
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002168void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002169{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002170 setImage(3, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002171}
2172
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002173void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002174{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002175 setImage(4, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002176}
2177
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002178void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002179{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002180 setImage(5, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002181}
2182
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002183void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002184{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002185 redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002186
daniel@transgaming.com61208202011-03-21 16:38:50 +00002187 Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002188}
2189
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002190void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002191{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002192 ASSERT(mImageArray[face][level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002193
2194 if (level < levelCount())
2195 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002196 IDirect3DSurface9 *destLevel = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002197 ASSERT(destLevel != NULL);
2198
2199 if (destLevel != NULL)
2200 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002201 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002202
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002203 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());;
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002204 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002205
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002206 HRESULT result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002207 ASSERT(SUCCEEDED(result));
2208
2209 destLevel->Release();
2210
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002211 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002212 }
2213 }
2214}
2215
2216void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2217{
2218 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
2219 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002220 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002221 }
2222}
2223
2224void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
2225{
2226 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
2227 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002228 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002229 }
2230}
2231
2232// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
2233bool TextureCubeMap::isComplete() const
2234{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002235 int size = mImageArray[0][0].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002236
2237 if (size <= 0)
2238 {
2239 return false;
2240 }
2241
2242 bool mipmapping;
2243
2244 switch (mMinFilter)
2245 {
2246 case GL_NEAREST:
2247 case GL_LINEAR:
2248 mipmapping = false;
2249 break;
2250 case GL_NEAREST_MIPMAP_NEAREST:
2251 case GL_LINEAR_MIPMAP_NEAREST:
2252 case GL_NEAREST_MIPMAP_LINEAR:
2253 case GL_LINEAR_MIPMAP_LINEAR:
2254 mipmapping = true;
2255 break;
2256 default: UNREACHABLE();
2257 }
2258
2259 for (int face = 0; face < 6; face++)
2260 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002261 if (mImageArray[face][0].getWidth() != size || mImageArray[face][0].getHeight() != size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002262 {
2263 return false;
2264 }
2265 }
2266
2267 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
2268 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
2269 {
2270 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
2271 {
2272 return false;
2273 }
2274 }
2275
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002276 bool npot = getContext()->supportsNonPower2Texture();
2277
2278 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002279 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002280 if ((getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE) && !isPow2(size))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002281 {
2282 return false;
2283 }
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002284 }
2285
2286 if (mipmapping)
2287 {
2288 if (!npot)
2289 {
2290 if (!isPow2(size))
2291 {
2292 return false;
2293 }
2294 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002295
2296 int q = log2(size);
2297
2298 for (int face = 0; face < 6; face++)
2299 {
2300 for (int level = 1; level <= q; level++)
2301 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002302 if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002303 {
2304 return false;
2305 }
2306
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002307 if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00002308 {
2309 return false;
2310 }
2311
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002312 if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002313 {
2314 return false;
2315 }
2316
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002317 ASSERT(mImageArray[face][level].getHeight() == mImageArray[face][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002318 }
2319 }
2320 }
2321
2322 return true;
2323}
2324
2325bool TextureCubeMap::isCompressed() const
2326{
2327 return IsCompressed(getInternalFormat());
2328}
2329
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002330IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
2331{
2332 return mTexture;
2333}
2334
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002335// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002336void TextureCubeMap::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002337{
2338 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002339 D3DFORMAT format = mImageArray[0][0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002340 GLint levels = creationLevels(mImageArray[0][0].getWidth(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002341
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00002342 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002343 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002344
2345 if (FAILED(result))
2346 {
2347 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002348 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002349 }
2350
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002351 if (mTexture)
2352 {
2353 mTexture->Release();
2354 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002355
2356 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002357 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00002358 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002359}
2360
2361void TextureCubeMap::updateTexture()
2362{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002363 for (int face = 0; face < 6; face++)
2364 {
2365 int levels = levelCount();
2366 for (int level = 0; level < levels; level++)
2367 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002368 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002369
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00002370 if (image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002371 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002372 commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002373 }
2374 }
2375 }
2376}
2377
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002378void TextureCubeMap::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002379{
2380 IDirect3DCubeTexture9 *texture = NULL;
2381
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002382 if (mImageArray[0][0].getWidth() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002383 {
2384 egl::Display *display = getDisplay();
2385 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002386 D3DFORMAT format = mImageArray[0][0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002387 GLint levels = creationLevels(mImageArray[0][0].getWidth(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002388
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002389 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002390
2391 if (FAILED(result))
2392 {
2393 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002394 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002395 }
2396
2397 if (mTexture != NULL)
2398 {
2399 int levels = levelCount();
2400 for (int f = 0; f < 6; f++)
2401 {
2402 for (int i = 0; i < levels; i++)
2403 {
2404 IDirect3DSurface9 *source;
2405 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
2406
2407 if (FAILED(result))
2408 {
2409 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2410
2411 texture->Release();
2412
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002413 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002414 }
2415
2416 IDirect3DSurface9 *dest;
2417 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
2418
2419 if (FAILED(result))
2420 {
2421 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2422
2423 texture->Release();
2424 source->Release();
2425
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002426 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002427 }
2428
2429 display->endScene();
2430 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
2431
2432 if (FAILED(result))
2433 {
2434 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2435
2436 texture->Release();
2437 source->Release();
2438 dest->Release();
2439
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002440 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002441 }
daniel@transgaming.coma1a86202011-08-09 13:41:08 +00002442
2443 source->Release();
2444 dest->Release();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002445 }
2446 }
2447 }
2448 }
2449
2450 if (mTexture != NULL)
2451 {
2452 mTexture->Release();
2453 }
2454
2455 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002456 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00002457 mIsRenderable = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002458}
2459
daniel@transgaming.com61208202011-03-21 16:38:50 +00002460void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002461{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002462 redefineImage(faceIndex, level, format, width, height, type);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002463
daniel@transgaming.com61208202011-03-21 16:38:50 +00002464 Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002465}
2466
2467unsigned int TextureCubeMap::faceIndex(GLenum face)
2468{
2469 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2470 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2471 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2472 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2473 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2474
2475 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2476}
2477
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002478void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002479{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002480 GLsizei textureWidth = mImageArray[0][0].getWidth();
2481 GLsizei textureHeight = mImageArray[0][0].getHeight();
2482 GLenum textureFormat = mImageArray[0][0].getFormat();
2483 GLenum textureType = mImageArray[0][0].getType();
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00002484
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002485 mImageArray[face][level].redefine(format, width, height, type);
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00002486
daniel@transgaming.com61208202011-03-21 16:38:50 +00002487 if (!mTexture)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002488 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002489 return;
2490 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002491
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00002492 bool sizeOkay = (textureWidth >> level == width);
2493 bool textureOkay = (sizeOkay && textureFormat == format && textureType == type);
daniel@transgaming.com61208202011-03-21 16:38:50 +00002494
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00002495 if (!textureOkay)
daniel@transgaming.com61208202011-03-21 16:38:50 +00002496 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002497 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2498 {
2499 for (int f = 0; f < 6; f++)
2500 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002501 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002502 }
2503 }
2504
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002505 mTexture->Release();
2506 mTexture = NULL;
2507 mDirtyImages = true;
2508 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002509 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002510}
2511
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002512void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002513{
2514 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2515
2516 if (!renderTarget)
2517 {
2518 ERR("Failed to retrieve the render target.");
2519 return error(GL_OUT_OF_MEMORY);
2520 }
2521
2522 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002523 redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002524
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002525 if (!mImageArray[faceindex][level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002526 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00002527 copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002528 }
2529 else
2530 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002531 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002532 {
2533 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002534 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00002535
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002536 mImageArray[faceindex][level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002537
2538 ASSERT(width == height);
2539
2540 if (width > 0 && level < levelCount())
2541 {
2542 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2543 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2544 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2545 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2546 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2547
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002548 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002549
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002550 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2551
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002552 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002553 dest->Release();
2554 }
2555 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002556}
2557
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002558IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(GLenum target, unsigned int level)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002559{
2560 if (mTexture == NULL)
2561 {
2562 UNREACHABLE();
2563 return NULL;
2564 }
2565
2566 IDirect3DSurface9 *surface = NULL;
2567
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002568 HRESULT hr = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), level, &surface);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002569
2570 return (SUCCEEDED(hr)) ? surface : NULL;
2571}
2572
2573void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
2574{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002575 GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002576
2577 if (xoffset + width > size || yoffset + height > size)
2578 {
2579 return error(GL_INVALID_VALUE);
2580 }
2581
2582 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2583
2584 if (!renderTarget)
2585 {
2586 ERR("Failed to retrieve the render target.");
2587 return error(GL_OUT_OF_MEMORY);
2588 }
2589
2590 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com01dae852011-11-09 17:44:53 +00002591
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002592 if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002593 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00002594 copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002595 }
2596 else
2597 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002598 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002599 {
2600 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002601 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002602
2603 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002604
2605 if (level < levelCount())
2606 {
2607 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2608 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2609 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2610 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2611 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2612
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002613 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002614
2615 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2616
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002617 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002618 dest->Release();
2619 }
2620 }
2621}
2622
2623bool TextureCubeMap::isCubeComplete() const
2624{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002625 if (mImageArray[0][0].getWidth() == 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002626 {
2627 return false;
2628 }
2629
2630 for (unsigned int f = 1; f < 6; f++)
2631 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002632 if (mImageArray[f][0].getWidth() != mImageArray[0][0].getWidth()
2633 || mImageArray[f][0].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002634 {
2635 return false;
2636 }
2637 }
2638
2639 return true;
2640}
2641
2642void TextureCubeMap::generateMipmaps()
2643{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002644 if (!isCubeComplete())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002645 {
2646 return error(GL_INVALID_OPERATION);
2647 }
2648
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002649 if (!getContext()->supportsNonPower2Texture())
2650 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002651 if (!isPow2(mImageArray[0][0].getWidth()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002652 {
2653 return error(GL_INVALID_OPERATION);
2654 }
2655 }
2656
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002657 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002658 unsigned int q = log2(mImageArray[0][0].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002659 for (unsigned int f = 0; f < 6; f++)
2660 {
2661 for (unsigned int i = 1; i <= q; i++)
2662 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002663 mImageArray[f][i].redefine(mImageArray[f][0].getFormat(),
2664 std::max(mImageArray[f][0].getWidth() >> i, 1),
2665 std::max(mImageArray[f][0].getWidth() >> i, 1),
2666 mImageArray[f][0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002667 }
2668 }
2669
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002670 if (mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002671 {
2672 if (mTexture == NULL)
2673 {
2674 return;
2675 }
2676
2677 for (unsigned int f = 0; f < 6; f++)
2678 {
2679 for (unsigned int i = 1; i <= q; i++)
2680 {
2681 IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
2682 IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2683
2684 if (upper != NULL && lower != NULL)
2685 {
2686 getBlitter()->boxFilter(upper, lower);
2687 }
2688
2689 if (upper != NULL) upper->Release();
2690 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002691
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002692 mImageArray[f][i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002693 }
2694 }
2695 }
2696 else
2697 {
2698 for (unsigned int f = 0; f < 6; f++)
2699 {
2700 for (unsigned int i = 1; i <= q; i++)
2701 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002702 if (mImageArray[f][i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002703 {
2704 return error(GL_OUT_OF_MEMORY);
2705 }
2706
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002707 if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].getSurface(), NULL, NULL, mImageArray[f][i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002708 {
2709 ERR(" failed to load filter %d to %d.", i - 1, i);
2710 }
2711
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002712 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002713 }
2714 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002715 }
2716}
2717
2718Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
2719{
2720 if (!IsCubemapTextureTarget(target))
2721 {
2722 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2723 }
2724
2725 unsigned int face = faceIndex(target);
2726
2727 if (mFaceProxies[face].get() == NULL)
2728 {
2729 mFaceProxies[face].set(new Renderbuffer(id(), new Colorbuffer(this, target)));
2730 }
2731
2732 return mFaceProxies[face].get();
2733}
2734
2735IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2736{
2737 ASSERT(IsCubemapTextureTarget(target));
2738
daniel@transgaming.com61208202011-03-21 16:38:50 +00002739 if (!mIsRenderable)
2740 {
2741 convertToRenderTarget();
2742 }
2743
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002744 if (mTexture == NULL)
2745 {
2746 return NULL;
2747 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002748
2749 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002750
2751 IDirect3DSurface9 *renderTarget = NULL;
2752 mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget);
2753
2754 return renderTarget;
2755}
2756
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002757}