blob: 8d63a9e4b346b91db7fc1375c5fccdcf43d368e0 [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{
47 mWidth = width;
48 mHeight = height;
49 mFormat = format;
50 mType = type;
51
52 if (mSurface)
53 {
54 mSurface->Release();
55 mSurface = NULL;
56 mDirty = true;
57 }
58
59 createSurface();
60}
61
62void Image::createSurface()
63{
64 if(mSurface)
65 {
66 return;
67 }
68
69 IDirect3DTexture9 *newTexture = NULL;
70 IDirect3DSurface9 *newSurface = NULL;
71
72 if (mWidth != 0 && mHeight != 0)
73 {
74 int levelToFetch = 0;
75 GLsizei requestWidth = mWidth;
76 GLsizei requestHeight = mHeight;
77 if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
78 {
79 bool isMult4 = false;
80 int upsampleCount = 0;
81 while (!isMult4)
82 {
83 requestWidth <<= 1;
84 requestHeight <<= 1;
85 upsampleCount++;
86 if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
87 {
88 isMult4 = true;
89 }
90 }
91 levelToFetch = upsampleCount;
92 }
93
94 HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, getD3DFormat(),
95 D3DPOOL_SYSTEMMEM, &newTexture, NULL);
96
97 if (FAILED(result))
98 {
99 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
100 return error(GL_OUT_OF_MEMORY);
101 }
102
103 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
104 newTexture->Release();
105 }
106
107 mSurface = newSurface;
108}
109
daniel@transgaming.comde631782011-11-09 17:45:04 +0000110bool Image::isRenderable() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000111{
112 switch(getD3DFormat())
113 {
114 case D3DFMT_L8:
115 case D3DFMT_A8L8:
116 case D3DFMT_DXT1:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000117 case D3DFMT_DXT3:
118 case D3DFMT_DXT5:
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000119 return false;
120 case D3DFMT_A8R8G8B8:
121 case D3DFMT_X8R8G8B8:
122 case D3DFMT_A16B16G16R16F:
123 case D3DFMT_A32B32G32R32F:
124 return true;
125 default:
126 UNREACHABLE();
127 }
128
129 return false;
130}
131
daniel@transgaming.comde631782011-11-09 17:45:04 +0000132D3DFORMAT Image::getD3DFormat() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000133{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000134 if (mFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
135 mFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000136 {
137 return D3DFMT_DXT1;
138 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000139 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000140 {
141 return D3DFMT_DXT3;
142 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000143 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000144 {
145 return D3DFMT_DXT5;
146 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000147 else if (mType == GL_FLOAT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000148 {
149 return D3DFMT_A32B32G32R32F;
150 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000151 else if (mType == GL_HALF_FLOAT_OES)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000152 {
153 return D3DFMT_A16B16G16R16F;
154 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000155 else if (mType == GL_UNSIGNED_BYTE)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000156 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000157 if (mFormat == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000158 {
159 return D3DFMT_L8;
160 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000161 else if (mFormat == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000162 {
163 return D3DFMT_A8L8;
164 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000165 else if (mFormat == GL_RGB)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000166 {
167 return D3DFMT_X8R8G8B8;
168 }
169
170 return D3DFMT_A8R8G8B8;
171 }
172
173 return D3DFMT_A8R8G8B8;
174}
175
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +0000176Texture::Texture(GLuint id) : RefCountObject(id), mSerial(issueSerial())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000177{
178 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
179 mMagFilter = GL_LINEAR;
180 mWrapS = GL_REPEAT;
181 mWrapT = GL_REPEAT;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000182 mDirtyParameters = true;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +0000183
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000184 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +0000185
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000186 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000187}
188
189Texture::~Texture()
190{
191}
192
193Blit *Texture::getBlitter()
194{
195 Context *context = getContext();
196 return context->getBlitter();
197}
198
199// Returns true on successful filter state update (valid enum parameter)
200bool Texture::setMinFilter(GLenum filter)
201{
202 switch (filter)
203 {
204 case GL_NEAREST:
205 case GL_LINEAR:
206 case GL_NEAREST_MIPMAP_NEAREST:
207 case GL_LINEAR_MIPMAP_NEAREST:
208 case GL_NEAREST_MIPMAP_LINEAR:
209 case GL_LINEAR_MIPMAP_LINEAR:
210 {
211 if (mMinFilter != filter)
212 {
213 mMinFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000214 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000215 }
216 return true;
217 }
218 default:
219 return false;
220 }
221}
222
223// Returns true on successful filter state update (valid enum parameter)
224bool Texture::setMagFilter(GLenum filter)
225{
226 switch (filter)
227 {
228 case GL_NEAREST:
229 case GL_LINEAR:
230 {
231 if (mMagFilter != filter)
232 {
233 mMagFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000234 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000235 }
236 return true;
237 }
238 default:
239 return false;
240 }
241}
242
243// Returns true on successful wrap state update (valid enum parameter)
244bool Texture::setWrapS(GLenum wrap)
245{
246 switch (wrap)
247 {
248 case GL_REPEAT:
249 case GL_CLAMP_TO_EDGE:
250 case GL_MIRRORED_REPEAT:
251 {
252 if (mWrapS != wrap)
253 {
254 mWrapS = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000255 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000256 }
257 return true;
258 }
259 default:
260 return false;
261 }
262}
263
264// Returns true on successful wrap state update (valid enum parameter)
265bool Texture::setWrapT(GLenum wrap)
266{
267 switch (wrap)
268 {
269 case GL_REPEAT:
270 case GL_CLAMP_TO_EDGE:
271 case GL_MIRRORED_REPEAT:
272 {
273 if (mWrapT != wrap)
274 {
275 mWrapT = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +0000276 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000277 }
278 return true;
279 }
280 default:
281 return false;
282 }
283}
284
285GLenum Texture::getMinFilter() const
286{
287 return mMinFilter;
288}
289
290GLenum Texture::getMagFilter() const
291{
292 return mMagFilter;
293}
294
295GLenum Texture::getWrapS() const
296{
297 return mWrapS;
298}
299
300GLenum Texture::getWrapT() const
301{
302 return mWrapT;
303}
304
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000305// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
306// into the target pixel rectangle at output with outputPitch bytes in between each line.
307void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
308 GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
309{
310 GLsizei inputPitch = -ComputePitch(width, format, type, unpackAlignment);
311 input = ((char*)input) - inputPitch * (height - 1);
312
313 switch (type)
314 {
315 case GL_UNSIGNED_BYTE:
316 switch (format)
317 {
318 case GL_ALPHA:
319 loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
320 break;
321 case GL_LUMINANCE:
322 loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_L8);
323 break;
324 case GL_LUMINANCE_ALPHA:
325 loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
326 break;
327 case GL_RGB:
328 loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
329 break;
330 case GL_RGBA:
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000331 if (supportsSSE2())
332 {
333 loadRGBAUByteImageDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
334 }
335 else
336 {
337 loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
338 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000339 break;
340 case GL_BGRA_EXT:
341 loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
342 break;
343 default: UNREACHABLE();
344 }
345 break;
346 case GL_UNSIGNED_SHORT_5_6_5:
347 switch (format)
348 {
349 case GL_RGB:
350 loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
351 break;
352 default: UNREACHABLE();
353 }
354 break;
355 case GL_UNSIGNED_SHORT_4_4_4_4:
356 switch (format)
357 {
358 case GL_RGBA:
359 loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
360 break;
361 default: UNREACHABLE();
362 }
363 break;
364 case GL_UNSIGNED_SHORT_5_5_5_1:
365 switch (format)
366 {
367 case GL_RGBA:
368 loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
369 break;
370 default: UNREACHABLE();
371 }
372 break;
373 case GL_FLOAT:
374 switch (format)
375 {
376 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
377 case GL_ALPHA:
378 loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
379 break;
380 case GL_LUMINANCE:
381 loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
382 break;
383 case GL_LUMINANCE_ALPHA:
384 loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
385 break;
386 case GL_RGB:
387 loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
388 break;
389 case GL_RGBA:
390 loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
391 break;
392 default: UNREACHABLE();
393 }
394 break;
395 case GL_HALF_FLOAT_OES:
396 switch (format)
397 {
398 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
399 case GL_ALPHA:
400 loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
401 break;
402 case GL_LUMINANCE:
403 loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
404 break;
405 case GL_LUMINANCE_ALPHA:
406 loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
407 break;
408 case GL_RGB:
409 loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
410 break;
411 case GL_RGBA:
412 loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
413 break;
414 default: UNREACHABLE();
415 }
416 break;
417 default: UNREACHABLE();
418 }
419}
420
421void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
422 int inputPitch, const void *input, size_t outputPitch, void *output) const
423{
424 const unsigned char *source = NULL;
425 unsigned char *dest = NULL;
426
427 for (int y = 0; y < height; y++)
428 {
429 source = static_cast<const unsigned char*>(input) + y * inputPitch;
430 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
431 for (int x = 0; x < width; x++)
432 {
433 dest[4 * x + 0] = 0;
434 dest[4 * x + 1] = 0;
435 dest[4 * x + 2] = 0;
436 dest[4 * x + 3] = source[x];
437 }
438 }
439}
440
441void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
442 int inputPitch, const void *input, size_t outputPitch, void *output) const
443{
444 const float *source = NULL;
445 float *dest = NULL;
446
447 for (int y = 0; y < height; y++)
448 {
449 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
450 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
451 for (int x = 0; x < width; x++)
452 {
453 dest[4 * x + 0] = 0;
454 dest[4 * x + 1] = 0;
455 dest[4 * x + 2] = 0;
456 dest[4 * x + 3] = source[x];
457 }
458 }
459}
460
461void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
462 int inputPitch, const void *input, size_t outputPitch, void *output) const
463{
464 const unsigned short *source = NULL;
465 unsigned short *dest = NULL;
466
467 for (int y = 0; y < height; y++)
468 {
469 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
470 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
471 for (int x = 0; x < width; x++)
472 {
473 dest[4 * x + 0] = 0;
474 dest[4 * x + 1] = 0;
475 dest[4 * x + 2] = 0;
476 dest[4 * x + 3] = source[x];
477 }
478 }
479}
480
481void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
482 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
483{
484 const int destBytesPerPixel = native? 1: 4;
485 const unsigned char *source = NULL;
486 unsigned char *dest = NULL;
487
488 for (int y = 0; y < height; y++)
489 {
490 source = static_cast<const unsigned char*>(input) + y * inputPitch;
491 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
492
493 if (!native) // BGRA8 destination format
494 {
495 for (int x = 0; x < width; x++)
496 {
497 dest[4 * x + 0] = source[x];
498 dest[4 * x + 1] = source[x];
499 dest[4 * x + 2] = source[x];
500 dest[4 * x + 3] = 0xFF;
501 }
502 }
503 else // L8 destination format
504 {
505 memcpy(dest, source, width);
506 }
507 }
508}
509
510void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
511 int inputPitch, const void *input, size_t outputPitch, void *output) const
512{
513 const float *source = NULL;
514 float *dest = NULL;
515
516 for (int y = 0; y < height; y++)
517 {
518 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
519 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
520 for (int x = 0; x < width; x++)
521 {
522 dest[4 * x + 0] = source[x];
523 dest[4 * x + 1] = source[x];
524 dest[4 * x + 2] = source[x];
525 dest[4 * x + 3] = 1.0f;
526 }
527 }
528}
529
530void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
531 int inputPitch, const void *input, size_t outputPitch, void *output) const
532{
533 const unsigned short *source = NULL;
534 unsigned short *dest = NULL;
535
536 for (int y = 0; y < height; y++)
537 {
538 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
539 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
540 for (int x = 0; x < width; x++)
541 {
542 dest[4 * x + 0] = source[x];
543 dest[4 * x + 1] = source[x];
544 dest[4 * x + 2] = source[x];
545 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
546 }
547 }
548}
549
550void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
551 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
552{
553 const int destBytesPerPixel = native? 2: 4;
554 const unsigned char *source = NULL;
555 unsigned char *dest = NULL;
556
557 for (int y = 0; y < height; y++)
558 {
559 source = static_cast<const unsigned char*>(input) + y * inputPitch;
560 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
561
562 if (!native) // BGRA8 destination format
563 {
564 for (int x = 0; x < width; x++)
565 {
566 dest[4 * x + 0] = source[2*x+0];
567 dest[4 * x + 1] = source[2*x+0];
568 dest[4 * x + 2] = source[2*x+0];
569 dest[4 * x + 3] = source[2*x+1];
570 }
571 }
572 else
573 {
574 memcpy(dest, source, width * 2);
575 }
576 }
577}
578
579void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
580 int inputPitch, const void *input, size_t outputPitch, void *output) const
581{
582 const float *source = NULL;
583 float *dest = NULL;
584
585 for (int y = 0; y < height; y++)
586 {
587 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
588 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
589 for (int x = 0; x < width; x++)
590 {
591 dest[4 * x + 0] = source[2*x+0];
592 dest[4 * x + 1] = source[2*x+0];
593 dest[4 * x + 2] = source[2*x+0];
594 dest[4 * x + 3] = source[2*x+1];
595 }
596 }
597}
598
599void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
600 int inputPitch, const void *input, size_t outputPitch, void *output) const
601{
602 const unsigned short *source = NULL;
603 unsigned short *dest = NULL;
604
605 for (int y = 0; y < height; y++)
606 {
607 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
608 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
609 for (int x = 0; x < width; x++)
610 {
611 dest[4 * x + 0] = source[2*x+0];
612 dest[4 * x + 1] = source[2*x+0];
613 dest[4 * x + 2] = source[2*x+0];
614 dest[4 * x + 3] = source[2*x+1];
615 }
616 }
617}
618
619void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
620 int inputPitch, const void *input, size_t outputPitch, void *output) const
621{
622 const unsigned char *source = NULL;
623 unsigned char *dest = NULL;
624
625 for (int y = 0; y < height; y++)
626 {
627 source = static_cast<const unsigned char*>(input) + y * inputPitch;
628 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
629 for (int x = 0; x < width; x++)
630 {
631 dest[4 * x + 0] = source[x * 3 + 2];
632 dest[4 * x + 1] = source[x * 3 + 1];
633 dest[4 * x + 2] = source[x * 3 + 0];
634 dest[4 * x + 3] = 0xFF;
635 }
636 }
637}
638
639void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
640 int inputPitch, const void *input, size_t outputPitch, void *output) const
641{
642 const unsigned short *source = NULL;
643 unsigned char *dest = NULL;
644
645 for (int y = 0; y < height; y++)
646 {
647 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
648 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
649 for (int x = 0; x < width; x++)
650 {
651 unsigned short rgba = source[x];
652 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
653 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
654 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
655 dest[4 * x + 3] = 0xFF;
656 }
657 }
658}
659
660void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
661 int inputPitch, const void *input, size_t outputPitch, void *output) const
662{
663 const float *source = NULL;
664 float *dest = NULL;
665
666 for (int y = 0; y < height; y++)
667 {
668 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
669 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
670 for (int x = 0; x < width; x++)
671 {
672 dest[4 * x + 0] = source[x * 3 + 0];
673 dest[4 * x + 1] = source[x * 3 + 1];
674 dest[4 * x + 2] = source[x * 3 + 2];
675 dest[4 * x + 3] = 1.0f;
676 }
677 }
678}
679
680void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
681 int inputPitch, const void *input, size_t outputPitch, void *output) const
682{
683 const unsigned short *source = NULL;
684 unsigned short *dest = NULL;
685
686 for (int y = 0; y < height; y++)
687 {
688 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
689 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
690 for (int x = 0; x < width; x++)
691 {
692 dest[4 * x + 0] = source[x * 3 + 0];
693 dest[4 * x + 1] = source[x * 3 + 1];
694 dest[4 * x + 2] = source[x * 3 + 2];
695 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
696 }
697 }
698}
699
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000700void Texture::loadRGBAUByteImageDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
701 int inputPitch, const void *input, size_t outputPitch, void *output) const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000702{
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000703 const unsigned int *source = NULL;
704 unsigned int *dest = NULL;
705 __m128i brMask = _mm_set1_epi32(0x00ff00ff);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000706
707 for (int y = 0; y < height; y++)
708 {
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000709 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
710 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
711 int x = 0;
712
713 // Make output writes aligned
714 for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
715 {
716 unsigned int rgba = source[x];
717 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
718 }
719
720 for (; x + 3 < width; x += 4)
721 {
722 __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
723 // Mask out g and a, which don't change
724 __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
725 // Mask out b and r
726 __m128i brComponents = _mm_and_si128(sourceData, brMask);
727 // Swap b and r
728 __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
729 __m128i result = _mm_or_si128(gaComponents, brSwapped);
730 _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
731 }
732
733 // Perform leftover writes
734 for (; x < width; x++)
735 {
736 unsigned int rgba = source[x];
737 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
738 }
739 }
740}
741
742void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
743 int inputPitch, const void *input, size_t outputPitch, void *output) const
744{
745 const unsigned int *source = NULL;
746 unsigned int *dest = NULL;
747 for (int y = 0; y < height; y++)
748 {
749 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
750 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
751
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000752 for (int x = 0; x < width; x++)
753 {
jbauman@chromium.orgf1f28c82011-05-12 20:53:34 +0000754 unsigned int rgba = source[x];
755 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000756 }
757 }
758}
759
760void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
761 int inputPitch, const void *input, size_t outputPitch, void *output) const
762{
763 const unsigned short *source = NULL;
764 unsigned char *dest = NULL;
765
766 for (int y = 0; y < height; y++)
767 {
768 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
769 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
770 for (int x = 0; x < width; x++)
771 {
772 unsigned short rgba = source[x];
773 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
774 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
775 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
776 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
777 }
778 }
779}
780
781void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
782 int inputPitch, const void *input, size_t outputPitch, void *output) const
783{
784 const unsigned short *source = NULL;
785 unsigned char *dest = NULL;
786
787 for (int y = 0; y < height; y++)
788 {
789 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
790 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
791 for (int x = 0; x < width; x++)
792 {
793 unsigned short rgba = source[x];
794 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
795 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
796 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
797 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
798 }
799 }
800}
801
802void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
803 int inputPitch, const void *input, size_t outputPitch, void *output) const
804{
805 const float *source = NULL;
806 float *dest = NULL;
807
808 for (int y = 0; y < height; y++)
809 {
810 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
811 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
812 memcpy(dest, source, width * 16);
813 }
814}
815
816void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
817 int inputPitch, const void *input, size_t outputPitch, void *output) const
818{
819 const unsigned char *source = NULL;
820 unsigned char *dest = NULL;
821
822 for (int y = 0; y < height; y++)
823 {
824 source = static_cast<const unsigned char*>(input) + y * inputPitch;
825 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8;
826 memcpy(dest, source, width * 8);
827 }
828}
829
830void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
831 int inputPitch, const void *input, size_t outputPitch, void *output) const
832{
833 const unsigned char *source = NULL;
834 unsigned char *dest = NULL;
835
836 for (int y = 0; y < height; y++)
837 {
838 source = static_cast<const unsigned char*>(input) + y * inputPitch;
839 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
840 memcpy(dest, source, width*4);
841 }
842}
843
844void Texture::loadCompressedImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
gman@chromium.org50c526d2011-08-10 05:19:44 +0000845 int inputPitch, const void *input, size_t outputPitch, void *output) const {
846 switch (getD3DFormat())
847 {
848 case D3DFMT_DXT1:
849 loadDXT1ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
850 break;
851 case D3DFMT_DXT3:
852 loadDXT3ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
853 break;
854 case D3DFMT_DXT5:
855 loadDXT5ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
856 break;
857 }
858}
859
860static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
861 // A DXT1 block layout is:
862 // [0-1] color0.
863 // [2-3] color1.
864 // [4-7] color bitmap, 2 bits per pixel.
865 // So each of the 4-7 bytes represents one line, flipping a block is just
866 // flipping those bytes.
867
868 // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
869 dest[0] = source[0];
870
871 // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
872 dest[1] = (source[1] >> 24) |
873 ((source[1] << 8) & 0x00FF0000) |
874 ((source[1] >> 8) & 0x0000FF00) |
875 (source[1] << 24);
876}
877
878// Flips the first 2 lines of a DXT1 block in the y direction.
879static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
880 // See layout above.
881 dest[0] = source[0];
882 dest[1] = ((source[1] << 8) & 0x0000FF00) |
883 ((source[1] >> 8) & 0x000000FF);
884}
885
886// Flips a full DXT3 block in the y direction.
887static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
888 // A DXT3 block layout is:
889 // [0-7] alpha bitmap, 4 bits per pixel.
890 // [8-15] a DXT1 block.
891
892 // First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
893 dest[0] = (source[1] >> 16) | (source[1] << 16);
894 dest[1] = (source[0] >> 16) | (source[0] << 16);
895
896 // And flip the DXT1 block using the above function.
897 FlipCopyDXT1BlockFull(source + 2, dest + 2);
898}
899
900// Flips the first 2 lines of a DXT3 block in the y direction.
901static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
902 // See layout above.
903 dest[0] = (source[1] >> 16) | (source[1] << 16);
904 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
905}
906
907// Flips a full DXT5 block in the y direction.
908static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
909 // A DXT5 block layout is:
910 // [0] alpha0.
911 // [1] alpha1.
912 // [2-7] alpha bitmap, 3 bits per pixel.
913 // [8-15] a DXT1 block.
914
915 // The alpha bitmap doesn't easily map lines to bytes, so we have to
916 // interpret it correctly. Extracted from
917 // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
918 //
919 // The 6 "bits" bytes of the block are decoded into one 48-bit integer:
920 //
921 // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
922 // 256 * (bits_4 + 256 * bits_5))))
923 //
924 // bits is a 48-bit unsigned integer, from which a three-bit control code
925 // is extracted for a texel at location (x,y) in the block using:
926 //
927 // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
928 //
929 // where bit 47 is the most significant and bit 0 is the least
930 // significant bit.
931 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
932 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
933 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
934 unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
935 // swap lines 0 and 1 in line_0_1.
936 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
937 ((line_0_1 & 0xfff000) >> 12);
938 // swap lines 2 and 3 in line_2_3.
939 unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
940 ((line_2_3 & 0xfff000) >> 12);
941 destBytes[0] = sourceBytes[0];
942 destBytes[1] = sourceBytes[1];
943 destBytes[2] = line_3_2 & 0xff;
944 destBytes[3] = (line_3_2 & 0xff00) >> 8;
gman@chromium.org2ac3e732011-08-10 07:59:47 +0000945 destBytes[4] = (line_3_2 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000946 destBytes[5] = line_1_0 & 0xff;
947 destBytes[6] = (line_1_0 & 0xff00) >> 8;
gman@chromium.org2ac3e732011-08-10 07:59:47 +0000948 destBytes[7] = (line_1_0 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000949
950 // And flip the DXT1 block using the above function.
951 FlipCopyDXT1BlockFull(source + 2, dest + 2);
952}
953
954// Flips the first 2 lines of a DXT5 block in the y direction.
955static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
956 // See layout above.
957 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
958 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
959 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
960 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
961 ((line_0_1 & 0xfff000) >> 12);
962 destBytes[0] = sourceBytes[0];
963 destBytes[1] = sourceBytes[1];
964 destBytes[2] = line_1_0 & 0xff;
965 destBytes[3] = (line_1_0 & 0xff00) >> 8;
gman@chromium.org25c5cf62011-08-10 08:07:54 +0000966 destBytes[4] = (line_1_0 & 0xff0000) >> 16;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000967 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
968}
969
970void Texture::loadDXT1ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000971 int inputPitch, const void *input, size_t outputPitch, void *output) const
972{
973 ASSERT(xoffset % 4 == 0);
974 ASSERT(yoffset % 4 == 0);
975 ASSERT(width % 4 == 0 || width == 2 || width == 1);
976 ASSERT(inputPitch % 8 == 0);
977 ASSERT(outputPitch % 8 == 0);
978
979 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
980 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
981
gman@chromium.org50c526d2011-08-10 05:19:44 +0000982 // Round width up in case it is less than 4.
983 int blocksAcross = (width + 3) / 4;
984 int intsAcross = blocksAcross * 2;
985
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000986 switch (height)
987 {
988 case 1:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000989 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000990 {
gman@chromium.org50c526d2011-08-10 05:19:44 +0000991 // just copy the block
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000992 dest[x] = source[x];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000993 dest[x + 1] = source[x + 1];
994 }
995 break;
996 case 2:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000997 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000998 {
gman@chromium.org50c526d2011-08-10 05:19:44 +0000999 FlipCopyDXT1BlockHalf(source + x, dest + x);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001000 }
1001 break;
1002 default:
1003 ASSERT(height % 4 == 0);
1004 for (int y = 0; y < height / 4; ++y)
1005 {
1006 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1007 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
1008
gman@chromium.org50c526d2011-08-10 05:19:44 +00001009 for (int x = 0; x < intsAcross; x += 2)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001010 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001011 FlipCopyDXT1BlockFull(source + x, dest + x);
1012 }
1013 }
1014 break;
1015 }
1016}
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001017
gman@chromium.org50c526d2011-08-10 05:19:44 +00001018void Texture::loadDXT3ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
1019 int inputPitch, const void *input, size_t outputPitch, void *output) const
1020{
1021 ASSERT(xoffset % 4 == 0);
1022 ASSERT(yoffset % 4 == 0);
1023 ASSERT(width % 4 == 0 || width == 2 || width == 1);
1024 ASSERT(inputPitch % 16 == 0);
1025 ASSERT(outputPitch % 16 == 0);
1026
1027 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
1028 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
1029
1030 // Round width up in case it is less than 4.
1031 int blocksAcross = (width + 3) / 4;
1032 int intsAcross = blocksAcross * 4;
1033
1034 switch (height)
1035 {
1036 case 1:
1037 for (int x = 0; x < intsAcross; x += 4)
1038 {
1039 // just copy the block
1040 dest[x] = source[x];
1041 dest[x + 1] = source[x + 1];
1042 dest[x + 2] = source[x + 2];
1043 dest[x + 3] = source[x + 3];
1044 }
1045 break;
1046 case 2:
1047 for (int x = 0; x < intsAcross; x += 4)
1048 {
1049 FlipCopyDXT3BlockHalf(source + x, dest + x);
1050 }
1051 break;
1052 default:
1053 ASSERT(height % 4 == 0);
1054 for (int y = 0; y < height / 4; ++y)
1055 {
1056 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1057 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
1058
1059 for (int x = 0; x < intsAcross; x += 4)
1060 {
1061 FlipCopyDXT3BlockFull(source + x, dest + x);
1062 }
1063 }
1064 break;
1065 }
1066}
1067
1068void Texture::loadDXT5ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
1069 int inputPitch, const void *input, size_t outputPitch, void *output) const
1070{
1071 ASSERT(xoffset % 4 == 0);
1072 ASSERT(yoffset % 4 == 0);
1073 ASSERT(width % 4 == 0 || width == 2 || width == 1);
1074 ASSERT(inputPitch % 16 == 0);
1075 ASSERT(outputPitch % 16 == 0);
1076
1077 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
1078 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
1079
1080 // Round width up in case it is less than 4.
1081 int blocksAcross = (width + 3) / 4;
1082 int intsAcross = blocksAcross * 4;
1083
1084 switch (height)
1085 {
1086 case 1:
1087 for (int x = 0; x < intsAcross; x += 4)
1088 {
1089 // just copy the block
1090 dest[x] = source[x];
1091 dest[x + 1] = source[x + 1];
1092 dest[x + 2] = source[x + 2];
1093 dest[x + 3] = source[x + 3];
1094 }
1095 break;
1096 case 2:
1097 for (int x = 0; x < intsAcross; x += 4)
1098 {
1099 FlipCopyDXT5BlockHalf(source + x, dest + x);
1100 }
1101 break;
1102 default:
1103 ASSERT(height % 4 == 0);
gman@chromium.org2ac3e732011-08-10 07:59:47 +00001104 for (int y = 0; y < height / 4; ++y)
gman@chromium.org50c526d2011-08-10 05:19:44 +00001105 {
1106 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1107 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
1108
1109 for (int x = 0; x < intsAcross; x += 4)
1110 {
1111 FlipCopyDXT5BlockFull(source + x, dest + x);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001112 }
1113 }
1114 break;
1115 }
1116}
1117
daniel@transgaming.com61208202011-03-21 16:38:50 +00001118void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001119{
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001120 image->createSurface();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001121
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001122 if (pixels != NULL && image->getSurface() != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001123 {
1124 D3DSURFACE_DESC description;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001125 image->getSurface()->GetDesc(&description);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001126
1127 D3DLOCKED_RECT locked;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001128 HRESULT result = image->getSurface()->LockRect(&locked, NULL, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001129
1130 ASSERT(SUCCEEDED(result));
1131
1132 if (SUCCEEDED(result))
1133 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001134 loadImageData(0, 0, image->getWidth(), image->getHeight(), image->getFormat(), image->getType(), unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
1135 image->getSurface()->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001136 }
1137
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001138 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001139 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001140 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001141}
1142
daniel@transgaming.com61208202011-03-21 16:38:50 +00001143void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001144{
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001145 image->createSurface();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001146
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001147 if (pixels != NULL && image->getSurface() != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001148 {
1149 D3DLOCKED_RECT locked;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001150 HRESULT result = image->getSurface()->LockRect(&locked, NULL, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001151
1152 ASSERT(SUCCEEDED(result));
1153
1154 if (SUCCEEDED(result))
1155 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001156 int inputPitch = ComputeCompressedPitch(image->getWidth(), image->getFormat());
1157 int inputSize = ComputeCompressedSize(image->getWidth(), image->getHeight(), image->getFormat());
1158 loadCompressedImageData(0, 0, image->getWidth(), image->getHeight(), -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
1159 image->getSurface()->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001160 }
1161
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001162 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001163 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001164 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001165}
1166
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001167bool 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 +00001168{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001169 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001170 {
1171 error(GL_INVALID_VALUE);
1172 return false;
1173 }
1174
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001175 if (IsCompressed(image->getFormat()))
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001176 {
1177 error(GL_INVALID_OPERATION);
1178 return false;
1179 }
1180
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001181 if (format != image->getFormat())
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001182 {
1183 error(GL_INVALID_OPERATION);
1184 return false;
1185 }
1186
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001187 image->createSurface();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001188
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001189 if (pixels != NULL && image->getSurface() != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001190 {
1191 D3DSURFACE_DESC description;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001192 image->getSurface()->GetDesc(&description);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001193
1194 D3DLOCKED_RECT locked;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001195 HRESULT result = image->getSurface()->LockRect(&locked, NULL, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001196
1197 ASSERT(SUCCEEDED(result));
1198
1199 if (SUCCEEDED(result))
1200 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001201 loadImageData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
1202 image->getSurface()->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001203 }
1204
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001205 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001206 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001207 }
1208
1209 return true;
1210}
1211
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001212bool 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 +00001213{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001214 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001215 {
1216 error(GL_INVALID_VALUE);
1217 return false;
1218 }
1219
1220 if (format != getInternalFormat())
1221 {
1222 error(GL_INVALID_OPERATION);
1223 return false;
1224 }
1225
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001226 image->createSurface();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001227
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001228 if (pixels != NULL && image->getSurface() != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001229 {
1230 RECT updateRegion;
1231 updateRegion.left = xoffset;
1232 updateRegion.right = xoffset + width;
1233 updateRegion.bottom = yoffset + height;
1234 updateRegion.top = yoffset;
1235
1236 D3DLOCKED_RECT locked;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001237 HRESULT result = image->getSurface()->LockRect(&locked, &updateRegion, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001238
1239 ASSERT(SUCCEEDED(result));
1240
1241 if (SUCCEEDED(result))
1242 {
1243 int inputPitch = ComputeCompressedPitch(width, format);
1244 int inputSize = ComputeCompressedSize(width, height, format);
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001245 loadCompressedImageData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
1246 image->getSurface()->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001247 }
1248
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001249 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001250 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001251 }
1252
1253 return true;
1254}
1255
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001256// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
1257void 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 +00001258{
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001259 image->createSurface();
1260
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001261 if (!image->getSurface())
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001262 {
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00001263 ERR("Failed to create an image surface.");
1264 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001265 }
1266
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001267 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001268 IDirect3DSurface9 *renderTargetData = NULL;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001269 D3DSURFACE_DESC description;
1270 renderTarget->GetDesc(&description);
1271
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001272 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001273
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001274 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001275 {
1276 ERR("Could not create matching destination surface.");
1277 return error(GL_OUT_OF_MEMORY);
1278 }
1279
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001280 result = device->GetRenderTargetData(renderTarget, renderTargetData);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001281
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001282 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001283 {
1284 ERR("GetRenderTargetData unexpectedly failed.");
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001285 renderTargetData->Release();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001286 return error(GL_OUT_OF_MEMORY);
1287 }
1288
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001289 RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001290 int destYOffset = transformPixelYOffset(yoffset, height, image->getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001291 RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001292
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001293 if (image->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001294 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001295 result = D3DXLoadSurfaceFromSurface(image->getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001296
1297 if (FAILED(result))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001298 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001299 ERR("Copying surfaces unexpectedly failed.");
1300 renderTargetData->Release();
1301 return error(GL_OUT_OF_MEMORY);
1302 }
1303 }
1304 else
1305 {
1306 D3DLOCKED_RECT sourceLock = {0};
1307 result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001308
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001309 if (FAILED(result))
1310 {
1311 ERR("Failed to lock the source surface (rectangle might be invalid).");
1312 renderTargetData->Release();
1313 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001314 }
1315
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001316 D3DLOCKED_RECT destLock = {0};
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001317 result = image->getSurface()->LockRect(&destLock, &destRect, 0);
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001318
1319 if (FAILED(result))
1320 {
1321 ERR("Failed to lock the destination surface (rectangle might be invalid).");
1322 renderTargetData->UnlockRect();
1323 renderTargetData->Release();
1324 return error(GL_OUT_OF_MEMORY);
1325 }
1326
1327 if (destLock.pBits && sourceLock.pBits)
1328 {
1329 unsigned char *source = (unsigned char*)sourceLock.pBits;
1330 unsigned char *dest = (unsigned char*)destLock.pBits;
1331
1332 switch (description.Format)
1333 {
1334 case D3DFMT_X8R8G8B8:
1335 case D3DFMT_A8R8G8B8:
1336 switch(image->getD3DFormat())
1337 {
1338 case D3DFMT_L8:
1339 for(int y = 0; y < height; y++)
1340 {
1341 for(int x = 0; x < width; x++)
1342 {
1343 dest[x] = source[x * 4 + 2];
1344 }
1345
1346 source += sourceLock.Pitch;
1347 dest += destLock.Pitch;
1348 }
1349 break;
1350 case D3DFMT_A8L8:
1351 for(int y = 0; y < height; y++)
1352 {
1353 for(int x = 0; x < width; x++)
1354 {
1355 dest[x * 2 + 0] = source[x * 4 + 2];
1356 dest[x * 2 + 1] = source[x * 4 + 3];
1357 }
1358
1359 source += sourceLock.Pitch;
1360 dest += destLock.Pitch;
1361 }
1362 break;
1363 default:
1364 UNREACHABLE();
1365 }
1366 break;
1367 case D3DFMT_R5G6B5:
1368 switch(image->getD3DFormat())
1369 {
1370 case D3DFMT_L8:
1371 for(int y = 0; y < height; y++)
1372 {
1373 for(int x = 0; x < width; x++)
1374 {
1375 unsigned char red = source[x * 2 + 1] & 0xF8;
1376 dest[x] = red | (red >> 5);
1377 }
1378
1379 source += sourceLock.Pitch;
1380 dest += destLock.Pitch;
1381 }
1382 break;
1383 default:
1384 UNREACHABLE();
1385 }
1386 break;
1387 case D3DFMT_A1R5G5B5:
1388 switch(image->getD3DFormat())
1389 {
1390 case D3DFMT_L8:
1391 for(int y = 0; y < height; y++)
1392 {
1393 for(int x = 0; x < width; x++)
1394 {
1395 unsigned char red = source[x * 2 + 1] & 0x7C;
1396 dest[x] = (red << 1) | (red >> 4);
1397 }
1398
1399 source += sourceLock.Pitch;
1400 dest += destLock.Pitch;
1401 }
1402 break;
1403 case D3DFMT_A8L8:
1404 for(int y = 0; y < height; y++)
1405 {
1406 for(int x = 0; x < width; x++)
1407 {
1408 unsigned char red = source[x * 2 + 1] & 0x7C;
1409 dest[x * 2 + 0] = (red << 1) | (red >> 4);
1410 dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
1411 }
1412
1413 source += sourceLock.Pitch;
1414 dest += destLock.Pitch;
1415 }
1416 break;
1417 default:
1418 UNREACHABLE();
1419 }
1420 break;
1421 default:
1422 UNREACHABLE();
1423 }
1424 }
1425
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001426 image->getSurface()->UnlockRect();
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001427 renderTargetData->UnlockRect();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001428 }
1429
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001430 renderTargetData->Release();
1431
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001432 image->markDirty();
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001433 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001434}
1435
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001436IDirect3DBaseTexture9 *Texture::getTexture()
1437{
1438 if (!isComplete())
1439 {
1440 return NULL;
1441 }
1442
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001443 if (!getBaseTexture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001444 {
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001445 createTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001446 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001447
daniel@transgaming.comc50edcb2011-03-21 16:38:40 +00001448 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001449
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001450 return getBaseTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001451}
1452
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001453bool Texture::hasDirtyParameters() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001454{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001455 return mDirtyParameters;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001456}
1457
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001458bool Texture::hasDirtyImages() const
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001459{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001460 return mDirtyImages;
daniel@transgaming.com38e76e52011-03-21 16:39:10 +00001461}
1462
1463void Texture::resetDirty()
1464{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001465 mDirtyParameters = false;
1466 mDirtyImages = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001467}
1468
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001469unsigned int Texture::getSerial() const
1470{
1471 return mSerial;
1472}
1473
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001474GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
1475{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001476 if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001477 {
1478 return maxlevel;
1479 }
1480 else
1481 {
1482 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1483 return 1;
1484 }
1485}
1486
1487GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
1488{
1489 return creationLevels(size, size, maxlevel);
1490}
1491
1492int Texture::levelCount() const
1493{
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001494 return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001495}
1496
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001497unsigned int Texture::issueSerial()
1498{
1499 return mCurrentSerial++;
1500}
1501
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001502Texture2D::Texture2D(GLuint id) : Texture(id)
1503{
1504 mTexture = NULL;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001505 mSurface = NULL;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001506}
1507
1508Texture2D::~Texture2D()
1509{
1510 mColorbufferProxy.set(NULL);
1511
1512 if (mTexture)
1513 {
1514 mTexture->Release();
1515 mTexture = NULL;
1516 }
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001517
1518 if (mSurface)
1519 {
1520 mSurface->setBoundTexture(NULL);
1521 mSurface = NULL;
1522 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001523}
1524
1525GLenum Texture2D::getTarget() const
1526{
1527 return GL_TEXTURE_2D;
1528}
1529
daniel@transgaming.com61208202011-03-21 16:38:50 +00001530GLsizei Texture2D::getWidth() const
1531{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001532 return mImageArray[0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001533}
1534
1535GLsizei Texture2D::getHeight() const
1536{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001537 return mImageArray[0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001538}
1539
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001540GLenum Texture2D::getInternalFormat() const
1541{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001542 return mImageArray[0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001543}
1544
daniel@transgaming.com61208202011-03-21 16:38:50 +00001545GLenum Texture2D::getType() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001546{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001547 return mImageArray[0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001548}
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001549
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001550D3DFORMAT Texture2D::getD3DFormat() const
1551{
1552 return mImageArray[0].getD3DFormat();
1553}
1554
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001555void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRedefine)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001556{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001557 GLsizei textureWidth = mImageArray[0].getWidth();
1558 GLsizei textureHeight = mImageArray[0].getHeight();
1559 GLenum textureFormat = mImageArray[0].getFormat();
1560 GLenum textureType = mImageArray[0].getType();
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00001561
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001562 mImageArray[level].redefine(format, width, height, type);
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00001563
daniel@transgaming.com61208202011-03-21 16:38:50 +00001564 if (!mTexture)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001565 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001566 return;
1567 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001568
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00001569 bool widthOkay = (textureWidth >> level == width) || (textureWidth >> level == 0 && width == 1);
1570 bool heightOkay = (textureHeight >> level == height) || (textureHeight >> level == 0 && height == 1);
1571 bool textureOkay = (widthOkay && heightOkay && textureFormat == format && textureType == type);
daniel@transgaming.com61208202011-03-21 16:38:50 +00001572
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00001573 if (!textureOkay || forceRedefine || mSurface)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001574 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001575 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1576 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001577 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001578 }
1579
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001580 mTexture->Release();
1581 mTexture = NULL;
1582 mDirtyImages = true;
1583 mIsRenderable = false;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001584
1585 if (mSurface)
1586 {
1587 mSurface->setBoundTexture(NULL);
1588 mSurface = NULL;
1589 }
apatrick@chromium.org57a2cd62011-06-08 00:04:07 +00001590
1591 mColorbufferProxy.set(NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001592 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001593}
1594
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001595void 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 +00001596{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001597 redefineImage(level, format, width, height, type, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001598
daniel@transgaming.com61208202011-03-21 16:38:50 +00001599 Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001600}
1601
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001602void Texture2D::bindTexImage(egl::Surface *surface)
1603{
1604 GLenum format;
1605
1606 switch(surface->getFormat())
1607 {
1608 case D3DFMT_A8R8G8B8:
1609 format = GL_RGBA;
1610 break;
1611 case D3DFMT_X8R8G8B8:
1612 format = GL_RGB;
1613 break;
1614 default:
1615 UNIMPLEMENTED();
1616 return;
1617 }
1618
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001619 redefineImage(0, format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001620
1621 IDirect3DTexture9 *texture = surface->getOffscreenTexture();
1622
1623 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001624 mDirtyImages = true;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001625 mIsRenderable = true;
1626 mSurface = surface;
1627 mSurface->setBoundTexture(this);
1628}
1629
1630void Texture2D::releaseTexImage()
1631{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001632 redefineImage(0, GL_RGB, 0, 0, GL_UNSIGNED_BYTE, true);
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001633}
1634
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001635void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001636{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001637 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001638
daniel@transgaming.com61208202011-03-21 16:38:50 +00001639 Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001640}
1641
1642void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1643{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001644 ASSERT(mImageArray[level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001645
1646 if (level < levelCount())
1647 {
1648 IDirect3DSurface9 *destLevel = NULL;
1649 HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
1650
1651 ASSERT(SUCCEEDED(result));
1652
1653 if (SUCCEEDED(result))
1654 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001655 Image *image = &mImageArray[level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001656
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001657 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());;
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001658 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001659
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001660 result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001661 ASSERT(SUCCEEDED(result));
1662
1663 destLevel->Release();
1664
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001665 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001666 }
1667 }
1668}
1669
1670void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
1671{
1672 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1673 {
1674 commitRect(level, xoffset, yoffset, width, height);
1675 }
1676}
1677
1678void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1679{
1680 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1681 {
1682 commitRect(level, xoffset, yoffset, width, height);
1683 }
1684}
1685
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001686void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001687{
1688 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1689
1690 if (!renderTarget)
1691 {
1692 ERR("Failed to retrieve the render target.");
1693 return error(GL_OUT_OF_MEMORY);
1694 }
1695
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00001696 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE, false);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001697
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001698 if (!mImageArray[level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001699 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001700 copyToImage(&mImageArray[level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001701 }
1702 else
1703 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001704 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001705 {
1706 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001707 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00001708
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001709 mImageArray[level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001710
1711 if (width != 0 && height != 0 && level < levelCount())
1712 {
1713 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1714 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1715 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1716 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1717 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001718
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001719 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001720
1721 IDirect3DSurface9 *dest;
1722 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
1723
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001724 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001725 dest->Release();
1726 }
1727 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001728}
1729
1730void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1731{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001732 if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001733 {
1734 return error(GL_INVALID_VALUE);
1735 }
1736
1737 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1738
1739 if (!renderTarget)
1740 {
1741 ERR("Failed to retrieve the render target.");
1742 return error(GL_OUT_OF_MEMORY);
1743 }
1744
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001745 if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001746 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00001747 copyToImage(&mImageArray[level], xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001748 }
1749 else
1750 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00001751 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001752 {
1753 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001754 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00001755
1756 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001757
1758 if (level < levelCount())
1759 {
1760 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1761 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1762 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1763 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1764 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
1765
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001766 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001767
1768 IDirect3DSurface9 *dest;
1769 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
1770
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001771 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001772 dest->Release();
1773 }
1774 }
1775}
1776
1777// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1778bool Texture2D::isComplete() const
1779{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001780 GLsizei width = mImageArray[0].getWidth();
1781 GLsizei height = mImageArray[0].getHeight();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001782
1783 if (width <= 0 || height <= 0)
1784 {
1785 return false;
1786 }
1787
1788 bool mipmapping = false;
1789
1790 switch (mMinFilter)
1791 {
1792 case GL_NEAREST:
1793 case GL_LINEAR:
1794 mipmapping = false;
1795 break;
1796 case GL_NEAREST_MIPMAP_NEAREST:
1797 case GL_LINEAR_MIPMAP_NEAREST:
1798 case GL_NEAREST_MIPMAP_LINEAR:
1799 case GL_LINEAR_MIPMAP_LINEAR:
1800 mipmapping = true;
1801 break;
1802 default: UNREACHABLE();
1803 }
1804
1805 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1806 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1807 {
1808 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1809 {
1810 return false;
1811 }
1812 }
1813
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001814 bool npot = getContext()->supportsNonPower2Texture();
1815
1816 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001817 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001818 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
1819 (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1820 {
1821 return false;
1822 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001823 }
1824
1825 if (mipmapping)
1826 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001827 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001828 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001829 if (!isPow2(width) || !isPow2(height))
1830 {
1831 return false;
1832 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001833 }
1834
1835 int q = log2(std::max(width, height));
1836
1837 for (int level = 1; level <= q; level++)
1838 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001839 if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001840 {
1841 return false;
1842 }
1843
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001844 if (mImageArray[level].getType() != mImageArray[0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00001845 {
1846 return false;
1847 }
1848
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001849 if (mImageArray[level].getWidth() != std::max(1, width >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001850 {
1851 return false;
1852 }
1853
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001854 if (mImageArray[level].getHeight() != std::max(1, height >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001855 {
1856 return false;
1857 }
1858 }
1859 }
1860
1861 return true;
1862}
1863
1864bool Texture2D::isCompressed() const
1865{
1866 return IsCompressed(getInternalFormat());
1867}
1868
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001869IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
1870{
1871 return mTexture;
1872}
1873
1874// Constructs a Direct3D 9 texture resource from the texture images
1875void Texture2D::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001876{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001877 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001878 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001879 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001880
daniel@transgaming.com61208202011-03-21 16:38:50 +00001881 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001882 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 +00001883
1884 if (FAILED(result))
1885 {
1886 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001887 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001888 }
1889
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001890 if (mTexture)
1891 {
1892 mTexture->Release();
1893 }
1894
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001895 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001896 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001897 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001898}
1899
1900void Texture2D::updateTexture()
1901{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001902 int levels = levelCount();
1903
1904 for (int level = 0; level < levels; level++)
1905 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001906 Image *image = &mImageArray[level];
1907
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001908 if (image->getSurface() && image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001909 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001910 commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001911 }
1912 }
1913}
1914
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001915void Texture2D::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001916{
1917 IDirect3DTexture9 *texture = NULL;
1918
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001919 if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001920 {
1921 egl::Display *display = getDisplay();
1922 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001923 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001924 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001925
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001926 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 +00001927
1928 if (FAILED(result))
1929 {
1930 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001931 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001932 }
1933
1934 if (mTexture != NULL)
1935 {
1936 int levels = levelCount();
1937 for (int i = 0; i < levels; i++)
1938 {
1939 IDirect3DSurface9 *source;
1940 result = mTexture->GetSurfaceLevel(i, &source);
1941
1942 if (FAILED(result))
1943 {
1944 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1945
1946 texture->Release();
1947
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001948 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001949 }
1950
1951 IDirect3DSurface9 *dest;
1952 result = texture->GetSurfaceLevel(i, &dest);
1953
1954 if (FAILED(result))
1955 {
1956 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1957
1958 texture->Release();
1959 source->Release();
1960
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001961 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001962 }
1963
1964 display->endScene();
1965 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1966
1967 if (FAILED(result))
1968 {
1969 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1970
1971 texture->Release();
1972 source->Release();
1973 dest->Release();
1974
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001975 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001976 }
1977
1978 source->Release();
1979 dest->Release();
1980 }
1981 }
1982 }
1983
1984 if (mTexture != NULL)
1985 {
1986 mTexture->Release();
1987 }
1988
1989 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001990 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001991 mIsRenderable = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001992}
1993
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001994void Texture2D::generateMipmaps()
1995{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001996 if (!getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001997 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001998 if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001999 {
2000 return error(GL_INVALID_OPERATION);
2001 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002002 }
2003
2004 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002005 unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002006 for (unsigned int i = 1; i <= q; i++)
2007 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002008 mImageArray[i].redefine(mImageArray[0].getFormat(),
2009 std::max(mImageArray[0].getWidth() >> i, 1),
2010 std::max(mImageArray[0].getHeight() >> i, 1),
2011 mImageArray[0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002012 }
2013
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002014 if (mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002015 {
2016 if (mTexture == NULL)
2017 {
2018 ERR(" failed because mTexture was null.");
2019 return;
2020 }
2021
2022 for (unsigned int i = 1; i <= q; i++)
2023 {
2024 IDirect3DSurface9 *upper = NULL;
2025 IDirect3DSurface9 *lower = NULL;
2026
2027 mTexture->GetSurfaceLevel(i-1, &upper);
2028 mTexture->GetSurfaceLevel(i, &lower);
2029
2030 if (upper != NULL && lower != NULL)
2031 {
2032 getBlitter()->boxFilter(upper, lower);
2033 }
2034
2035 if (upper != NULL) upper->Release();
2036 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002037
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002038 mImageArray[i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002039 }
2040 }
2041 else
2042 {
2043 for (unsigned int i = 1; i <= q; i++)
2044 {
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00002045 mImageArray[i].createSurface();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002046
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002047 if (mImageArray[i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002048 {
2049 return error(GL_OUT_OF_MEMORY);
2050 }
2051
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002052 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 +00002053 {
2054 ERR(" failed to load filter %d to %d.", i - 1, i);
2055 }
2056
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002057 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002058 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002059 }
2060}
2061
2062Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
2063{
2064 if (target != GL_TEXTURE_2D)
2065 {
2066 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2067 }
2068
2069 if (mColorbufferProxy.get() == NULL)
2070 {
2071 mColorbufferProxy.set(new Renderbuffer(id(), new Colorbuffer(this, target)));
2072 }
2073
2074 return mColorbufferProxy.get();
2075}
2076
2077IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
2078{
2079 ASSERT(target == GL_TEXTURE_2D);
2080
daniel@transgaming.com61208202011-03-21 16:38:50 +00002081 if (!mIsRenderable)
2082 {
2083 convertToRenderTarget();
2084 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002085
2086 if (mTexture == NULL)
2087 {
2088 return NULL;
2089 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002090
2091 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002092
2093 IDirect3DSurface9 *renderTarget = NULL;
2094 mTexture->GetSurfaceLevel(0, &renderTarget);
2095
2096 return renderTarget;
2097}
2098
2099TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
2100{
2101 mTexture = NULL;
2102}
2103
2104TextureCubeMap::~TextureCubeMap()
2105{
2106 for (int i = 0; i < 6; i++)
2107 {
2108 mFaceProxies[i].set(NULL);
2109 }
2110
2111 if (mTexture)
2112 {
2113 mTexture->Release();
2114 mTexture = NULL;
2115 }
2116}
2117
2118GLenum TextureCubeMap::getTarget() const
2119{
2120 return GL_TEXTURE_CUBE_MAP;
2121}
2122
daniel@transgaming.com61208202011-03-21 16:38:50 +00002123GLsizei TextureCubeMap::getWidth() const
2124{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002125 return mImageArray[0][0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002126}
2127
2128GLsizei TextureCubeMap::getHeight() const
2129{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002130 return mImageArray[0][0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002131}
2132
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002133GLenum TextureCubeMap::getInternalFormat() const
2134{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002135 return mImageArray[0][0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002136}
2137
daniel@transgaming.com61208202011-03-21 16:38:50 +00002138GLenum TextureCubeMap::getType() const
2139{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002140 return mImageArray[0][0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002141}
2142
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002143D3DFORMAT TextureCubeMap::getD3DFormat() const
2144{
2145 return mImageArray[0][0].getD3DFormat();
2146}
2147
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002148void 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 +00002149{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002150 setImage(0, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002151}
2152
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002153void 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 +00002154{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002155 setImage(1, 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::setImagePosY(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(2, 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::setImageNegY(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(3, 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::setImagePosZ(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(4, 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::setImageNegZ(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(5, 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::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002179{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002180 redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002181
daniel@transgaming.com61208202011-03-21 16:38:50 +00002182 Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002183}
2184
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002185void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002186{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002187 ASSERT(mImageArray[face][level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002188
2189 if (level < levelCount())
2190 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002191 IDirect3DSurface9 *destLevel = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002192 ASSERT(destLevel != NULL);
2193
2194 if (destLevel != NULL)
2195 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002196 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002197
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002198 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());;
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002199 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002200
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002201 HRESULT result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002202 ASSERT(SUCCEEDED(result));
2203
2204 destLevel->Release();
2205
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002206 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002207 }
2208 }
2209}
2210
2211void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2212{
2213 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
2214 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002215 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002216 }
2217}
2218
2219void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
2220{
2221 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
2222 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002223 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002224 }
2225}
2226
2227// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
2228bool TextureCubeMap::isComplete() const
2229{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002230 int size = mImageArray[0][0].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002231
2232 if (size <= 0)
2233 {
2234 return false;
2235 }
2236
2237 bool mipmapping;
2238
2239 switch (mMinFilter)
2240 {
2241 case GL_NEAREST:
2242 case GL_LINEAR:
2243 mipmapping = false;
2244 break;
2245 case GL_NEAREST_MIPMAP_NEAREST:
2246 case GL_LINEAR_MIPMAP_NEAREST:
2247 case GL_NEAREST_MIPMAP_LINEAR:
2248 case GL_LINEAR_MIPMAP_LINEAR:
2249 mipmapping = true;
2250 break;
2251 default: UNREACHABLE();
2252 }
2253
2254 for (int face = 0; face < 6; face++)
2255 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002256 if (mImageArray[face][0].getWidth() != size || mImageArray[face][0].getHeight() != size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002257 {
2258 return false;
2259 }
2260 }
2261
2262 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
2263 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
2264 {
2265 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
2266 {
2267 return false;
2268 }
2269 }
2270
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002271 bool npot = getContext()->supportsNonPower2Texture();
2272
2273 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002274 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002275 if ((getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE) && !isPow2(size))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002276 {
2277 return false;
2278 }
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002279 }
2280
2281 if (mipmapping)
2282 {
2283 if (!npot)
2284 {
2285 if (!isPow2(size))
2286 {
2287 return false;
2288 }
2289 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002290
2291 int q = log2(size);
2292
2293 for (int face = 0; face < 6; face++)
2294 {
2295 for (int level = 1; level <= q; level++)
2296 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002297 if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002298 {
2299 return false;
2300 }
2301
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002302 if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00002303 {
2304 return false;
2305 }
2306
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002307 if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002308 {
2309 return false;
2310 }
2311
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002312 ASSERT(mImageArray[face][level].getHeight() == mImageArray[face][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002313 }
2314 }
2315 }
2316
2317 return true;
2318}
2319
2320bool TextureCubeMap::isCompressed() const
2321{
2322 return IsCompressed(getInternalFormat());
2323}
2324
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002325IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
2326{
2327 return mTexture;
2328}
2329
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002330// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002331void TextureCubeMap::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002332{
2333 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002334 D3DFORMAT format = mImageArray[0][0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002335 GLint levels = creationLevels(mImageArray[0][0].getWidth(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002336
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00002337 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002338 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002339
2340 if (FAILED(result))
2341 {
2342 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002343 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002344 }
2345
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002346 if (mTexture)
2347 {
2348 mTexture->Release();
2349 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002350
2351 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002352 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00002353 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002354}
2355
2356void TextureCubeMap::updateTexture()
2357{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002358 for (int face = 0; face < 6; face++)
2359 {
2360 int levels = levelCount();
2361 for (int level = 0; level < levels; level++)
2362 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002363 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002364
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002365 if (image->getSurface() && image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002366 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002367 commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002368 }
2369 }
2370 }
2371}
2372
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002373void TextureCubeMap::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002374{
2375 IDirect3DCubeTexture9 *texture = NULL;
2376
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002377 if (mImageArray[0][0].getWidth() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002378 {
2379 egl::Display *display = getDisplay();
2380 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002381 D3DFORMAT format = mImageArray[0][0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002382 GLint levels = creationLevels(mImageArray[0][0].getWidth(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002383
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002384 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002385
2386 if (FAILED(result))
2387 {
2388 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002389 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002390 }
2391
2392 if (mTexture != NULL)
2393 {
2394 int levels = levelCount();
2395 for (int f = 0; f < 6; f++)
2396 {
2397 for (int i = 0; i < levels; i++)
2398 {
2399 IDirect3DSurface9 *source;
2400 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
2401
2402 if (FAILED(result))
2403 {
2404 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2405
2406 texture->Release();
2407
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002408 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002409 }
2410
2411 IDirect3DSurface9 *dest;
2412 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
2413
2414 if (FAILED(result))
2415 {
2416 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2417
2418 texture->Release();
2419 source->Release();
2420
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002421 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002422 }
2423
2424 display->endScene();
2425 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
2426
2427 if (FAILED(result))
2428 {
2429 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2430
2431 texture->Release();
2432 source->Release();
2433 dest->Release();
2434
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002435 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002436 }
daniel@transgaming.coma1a86202011-08-09 13:41:08 +00002437
2438 source->Release();
2439 dest->Release();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002440 }
2441 }
2442 }
2443 }
2444
2445 if (mTexture != NULL)
2446 {
2447 mTexture->Release();
2448 }
2449
2450 mTexture = texture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002451 mDirtyImages = true;
daniel@transgaming.comaed18322011-03-21 16:38:13 +00002452 mIsRenderable = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002453}
2454
daniel@transgaming.com61208202011-03-21 16:38:50 +00002455void 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 +00002456{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002457 redefineImage(faceIndex, level, format, width, height, type);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002458
daniel@transgaming.com61208202011-03-21 16:38:50 +00002459 Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002460}
2461
2462unsigned int TextureCubeMap::faceIndex(GLenum face)
2463{
2464 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2465 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2466 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2467 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2468 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2469
2470 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2471}
2472
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002473void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002474{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002475 GLsizei textureWidth = mImageArray[0][0].getWidth();
2476 GLsizei textureHeight = mImageArray[0][0].getHeight();
2477 GLenum textureFormat = mImageArray[0][0].getFormat();
2478 GLenum textureType = mImageArray[0][0].getType();
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00002479
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002480 mImageArray[face][level].redefine(format, width, height, type);
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00002481
daniel@transgaming.com61208202011-03-21 16:38:50 +00002482 if (!mTexture)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002483 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002484 return;
2485 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002486
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00002487 bool sizeOkay = (textureWidth >> level == width);
2488 bool textureOkay = (sizeOkay && textureFormat == format && textureType == type);
daniel@transgaming.com61208202011-03-21 16:38:50 +00002489
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00002490 if (!textureOkay)
daniel@transgaming.com61208202011-03-21 16:38:50 +00002491 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002492 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2493 {
2494 for (int f = 0; f < 6; f++)
2495 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002496 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002497 }
2498 }
2499
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002500 mTexture->Release();
2501 mTexture = NULL;
2502 mDirtyImages = true;
2503 mIsRenderable = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002504 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002505}
2506
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002507void 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 +00002508{
2509 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2510
2511 if (!renderTarget)
2512 {
2513 ERR("Failed to retrieve the render target.");
2514 return error(GL_OUT_OF_MEMORY);
2515 }
2516
2517 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002518 redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002519
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002520 if (!mImageArray[faceindex][level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002521 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00002522 copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002523 }
2524 else
2525 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002526 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002527 {
2528 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002529 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00002530
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002531 mImageArray[faceindex][level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002532
2533 ASSERT(width == height);
2534
2535 if (width > 0 && level < levelCount())
2536 {
2537 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2538 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2539 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2540 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2541 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2542
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002543 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002544
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002545 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2546
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002547 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002548 dest->Release();
2549 }
2550 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002551}
2552
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002553IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(GLenum target, unsigned int level)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002554{
2555 if (mTexture == NULL)
2556 {
2557 UNREACHABLE();
2558 return NULL;
2559 }
2560
2561 IDirect3DSurface9 *surface = NULL;
2562
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002563 HRESULT hr = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), level, &surface);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002564
2565 return (SUCCEEDED(hr)) ? surface : NULL;
2566}
2567
2568void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
2569{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002570 GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002571
2572 if (xoffset + width > size || yoffset + height > size)
2573 {
2574 return error(GL_INVALID_VALUE);
2575 }
2576
2577 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2578
2579 if (!renderTarget)
2580 {
2581 ERR("Failed to retrieve the render target.");
2582 return error(GL_OUT_OF_MEMORY);
2583 }
2584
2585 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com01dae852011-11-09 17:44:53 +00002586
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002587 if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002588 {
daniel@transgaming.comb6276992011-03-29 00:58:18 +00002589 copyToImage(&mImageArray[faceindex][level], 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002590 }
2591 else
2592 {
daniel@transgaming.com61208202011-03-21 16:38:50 +00002593 if (!mTexture || !mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002594 {
2595 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002596 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002597
2598 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002599
2600 if (level < levelCount())
2601 {
2602 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2603 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2604 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2605 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2606 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2607
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002608 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002609
2610 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2611
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002612 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002613 dest->Release();
2614 }
2615 }
2616}
2617
2618bool TextureCubeMap::isCubeComplete() const
2619{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002620 if (mImageArray[0][0].getWidth() == 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002621 {
2622 return false;
2623 }
2624
2625 for (unsigned int f = 1; f < 6; f++)
2626 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002627 if (mImageArray[f][0].getWidth() != mImageArray[0][0].getWidth()
2628 || mImageArray[f][0].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002629 {
2630 return false;
2631 }
2632 }
2633
2634 return true;
2635}
2636
2637void TextureCubeMap::generateMipmaps()
2638{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002639 if (!isCubeComplete())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002640 {
2641 return error(GL_INVALID_OPERATION);
2642 }
2643
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002644 if (!getContext()->supportsNonPower2Texture())
2645 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002646 if (!isPow2(mImageArray[0][0].getWidth()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002647 {
2648 return error(GL_INVALID_OPERATION);
2649 }
2650 }
2651
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002652 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002653 unsigned int q = log2(mImageArray[0][0].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002654 for (unsigned int f = 0; f < 6; f++)
2655 {
2656 for (unsigned int i = 1; i <= q; i++)
2657 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002658 mImageArray[f][i].redefine(mImageArray[f][0].getFormat(),
2659 std::max(mImageArray[f][0].getWidth() >> i, 1),
2660 std::max(mImageArray[f][0].getWidth() >> i, 1),
2661 mImageArray[f][0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002662 }
2663 }
2664
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002665 if (mIsRenderable)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002666 {
2667 if (mTexture == NULL)
2668 {
2669 return;
2670 }
2671
2672 for (unsigned int f = 0; f < 6; f++)
2673 {
2674 for (unsigned int i = 1; i <= q; i++)
2675 {
2676 IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
2677 IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2678
2679 if (upper != NULL && lower != NULL)
2680 {
2681 getBlitter()->boxFilter(upper, lower);
2682 }
2683
2684 if (upper != NULL) upper->Release();
2685 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002686
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002687 mImageArray[f][i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002688 }
2689 }
2690 }
2691 else
2692 {
2693 for (unsigned int f = 0; f < 6; f++)
2694 {
2695 for (unsigned int i = 1; i <= q; i++)
2696 {
daniel@transgaming.com31e22e12011-11-09 17:44:44 +00002697 mImageArray[f][i].createSurface();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002698 if (mImageArray[f][i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002699 {
2700 return error(GL_OUT_OF_MEMORY);
2701 }
2702
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002703 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 +00002704 {
2705 ERR(" failed to load filter %d to %d.", i - 1, i);
2706 }
2707
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002708 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002709 }
2710 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002711 }
2712}
2713
2714Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
2715{
2716 if (!IsCubemapTextureTarget(target))
2717 {
2718 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2719 }
2720
2721 unsigned int face = faceIndex(target);
2722
2723 if (mFaceProxies[face].get() == NULL)
2724 {
2725 mFaceProxies[face].set(new Renderbuffer(id(), new Colorbuffer(this, target)));
2726 }
2727
2728 return mFaceProxies[face].get();
2729}
2730
2731IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2732{
2733 ASSERT(IsCubemapTextureTarget(target));
2734
daniel@transgaming.com61208202011-03-21 16:38:50 +00002735 if (!mIsRenderable)
2736 {
2737 convertToRenderTarget();
2738 }
2739
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002740 if (mTexture == NULL)
2741 {
2742 return NULL;
2743 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002744
2745 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002746
2747 IDirect3DSurface9 *renderTarget = NULL;
2748 mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(target), 0, &renderTarget);
2749
2750 return renderTarget;
2751}
2752
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002753}