blob: b2d4800aa98640af5393fe94108fa1ab34f4629a [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.com41634052011-11-09 17:46:24 +000045bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000046{
daniel@transgaming.com4c0a7712011-11-09 17:45:19 +000047 if (mWidth != width ||
48 mHeight != height ||
49 mFormat != format ||
50 mType != type)
51 {
daniel@transgaming.com41634052011-11-09 17:46:24 +000052 mWidth = width;
53 mHeight = height;
54 mFormat = format;
55 mType = type;
56
daniel@transgaming.com4c0a7712011-11-09 17:45:19 +000057 if (mSurface)
58 {
59 mSurface->Release();
60 mSurface = NULL;
61 }
daniel@transgaming.com41634052011-11-09 17:46:24 +000062
63 return true;
daniel@transgaming.com4c0a7712011-11-09 17:45:19 +000064 }
65
daniel@transgaming.com41634052011-11-09 17:46:24 +000066 return false;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +000067}
68
69void Image::createSurface()
70{
71 if(mSurface)
72 {
73 return;
74 }
75
76 IDirect3DTexture9 *newTexture = NULL;
77 IDirect3DSurface9 *newSurface = NULL;
78
79 if (mWidth != 0 && mHeight != 0)
80 {
81 int levelToFetch = 0;
82 GLsizei requestWidth = mWidth;
83 GLsizei requestHeight = mHeight;
84 if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
85 {
86 bool isMult4 = false;
87 int upsampleCount = 0;
88 while (!isMult4)
89 {
90 requestWidth <<= 1;
91 requestHeight <<= 1;
92 upsampleCount++;
93 if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
94 {
95 isMult4 = true;
96 }
97 }
98 levelToFetch = upsampleCount;
99 }
100
101 HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, getD3DFormat(),
102 D3DPOOL_SYSTEMMEM, &newTexture, NULL);
103
104 if (FAILED(result))
105 {
106 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com73de05a2011-11-09 17:45:24 +0000107 ERR("Creating image surface failed.");
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000108 return error(GL_OUT_OF_MEMORY);
109 }
110
111 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
112 newTexture->Release();
113 }
114
115 mSurface = newSurface;
daniel@transgaming.com839fb9b2011-11-09 17:45:43 +0000116 mDirty = false;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000117}
118
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +0000119HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
120{
121 createSurface();
122
123 HRESULT result = D3DERR_INVALIDCALL;
124
125 if (mSurface)
126 {
127 result = mSurface->LockRect(lockedRect, rect, 0);
128 ASSERT(SUCCEEDED(result));
129
130 mDirty = true;
131 }
132
133 return result;
134}
135
136void Image::unlock()
137{
138 if (mSurface)
139 {
140 HRESULT result = mSurface->UnlockRect();
141 ASSERT(SUCCEEDED(result));
142 }
143}
144
daniel@transgaming.comde631782011-11-09 17:45:04 +0000145bool Image::isRenderable() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000146{
147 switch(getD3DFormat())
148 {
149 case D3DFMT_L8:
150 case D3DFMT_A8L8:
151 case D3DFMT_DXT1:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000152 case D3DFMT_DXT3:
153 case D3DFMT_DXT5:
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000154 return false;
155 case D3DFMT_A8R8G8B8:
156 case D3DFMT_X8R8G8B8:
157 case D3DFMT_A16B16G16R16F:
158 case D3DFMT_A32B32G32R32F:
159 return true;
160 default:
161 UNREACHABLE();
162 }
163
164 return false;
165}
166
daniel@transgaming.comde631782011-11-09 17:45:04 +0000167D3DFORMAT Image::getD3DFormat() const
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000168{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000169 if (mFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
170 mFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000171 {
172 return D3DFMT_DXT1;
173 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000174 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000175 {
176 return D3DFMT_DXT3;
177 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000178 else if (mFormat == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
gman@chromium.org50c526d2011-08-10 05:19:44 +0000179 {
180 return D3DFMT_DXT5;
181 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000182 else if (mType == GL_FLOAT)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000183 {
184 return D3DFMT_A32B32G32R32F;
185 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000186 else if (mType == GL_HALF_FLOAT_OES)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000187 {
188 return D3DFMT_A16B16G16R16F;
189 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000190 else if (mType == GL_UNSIGNED_BYTE)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000191 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000192 if (mFormat == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000193 {
194 return D3DFMT_L8;
195 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000196 else if (mFormat == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000197 {
198 return D3DFMT_A8L8;
199 }
daniel@transgaming.comdff362f2011-11-09 17:45:08 +0000200 else if (mFormat == GL_RGB)
daniel@transgaming.com549bdef2011-03-29 00:57:01 +0000201 {
202 return D3DFMT_X8R8G8B8;
203 }
204
205 return D3DFMT_A8R8G8B8;
206 }
207
208 return D3DFMT_A8R8G8B8;
209}
210
daniel@transgaming.com73de05a2011-11-09 17:45:24 +0000211IDirect3DSurface9 *Image::getSurface()
212{
213 createSurface();
214
215 return mSurface;
216}
217
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000218// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
219// into the target pixel rectangle at output with outputPitch bytes in between each line.
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000220void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000221 GLint unpackAlignment, const void *input, size_t outputPitch, void *output) const
222{
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000223 GLsizei inputPitch = -ComputePitch(width, mFormat, type, unpackAlignment);
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000224 input = ((char*)input) - inputPitch * (height - 1);
225
226 switch (type)
227 {
228 case GL_UNSIGNED_BYTE:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000229 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000230 {
231 case GL_ALPHA:
232 loadAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
233 break;
234 case GL_LUMINANCE:
235 loadLuminanceData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_L8);
236 break;
237 case GL_LUMINANCE_ALPHA:
238 loadLuminanceAlphaData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, getD3DFormat() == D3DFMT_A8L8);
239 break;
240 case GL_RGB:
241 loadRGBUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
242 break;
243 case GL_RGBA:
244 if (supportsSSE2())
245 {
246 loadRGBAUByteDataSSE2(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
247 }
248 else
249 {
250 loadRGBAUByteData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
251 }
252 break;
253 case GL_BGRA_EXT:
254 loadBGRAData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
255 break;
256 default: UNREACHABLE();
257 }
258 break;
259 case GL_UNSIGNED_SHORT_5_6_5:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000260 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000261 {
262 case GL_RGB:
263 loadRGB565Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
264 break;
265 default: UNREACHABLE();
266 }
267 break;
268 case GL_UNSIGNED_SHORT_4_4_4_4:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000269 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000270 {
271 case GL_RGBA:
272 loadRGBA4444Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
273 break;
274 default: UNREACHABLE();
275 }
276 break;
277 case GL_UNSIGNED_SHORT_5_5_5_1:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000278 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000279 {
280 case GL_RGBA:
281 loadRGBA5551Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
282 break;
283 default: UNREACHABLE();
284 }
285 break;
286 case GL_FLOAT:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000287 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000288 {
289 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
290 case GL_ALPHA:
291 loadAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
292 break;
293 case GL_LUMINANCE:
294 loadLuminanceFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
295 break;
296 case GL_LUMINANCE_ALPHA:
297 loadLuminanceAlphaFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
298 break;
299 case GL_RGB:
300 loadRGBFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
301 break;
302 case GL_RGBA:
303 loadRGBAFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
304 break;
305 default: UNREACHABLE();
306 }
307 break;
308 case GL_HALF_FLOAT_OES:
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +0000309 switch (mFormat)
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +0000310 {
311 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
312 case GL_ALPHA:
313 loadAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
314 break;
315 case GL_LUMINANCE:
316 loadLuminanceHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
317 break;
318 case GL_LUMINANCE_ALPHA:
319 loadLuminanceAlphaHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
320 break;
321 case GL_RGB:
322 loadRGBHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
323 break;
324 case GL_RGBA:
325 loadRGBAHalfFloatData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
326 break;
327 default: UNREACHABLE();
328 }
329 break;
330 default: UNREACHABLE();
331 }
332}
333
334void Image::loadAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
335 int inputPitch, const void *input, size_t outputPitch, void *output) const
336{
337 const unsigned char *source = NULL;
338 unsigned char *dest = NULL;
339
340 for (int y = 0; y < height; y++)
341 {
342 source = static_cast<const unsigned char*>(input) + y * inputPitch;
343 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
344 for (int x = 0; x < width; x++)
345 {
346 dest[4 * x + 0] = 0;
347 dest[4 * x + 1] = 0;
348 dest[4 * x + 2] = 0;
349 dest[4 * x + 3] = source[x];
350 }
351 }
352}
353
354void Image::loadAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
355 int inputPitch, const void *input, size_t outputPitch, void *output) const
356{
357 const float *source = NULL;
358 float *dest = NULL;
359
360 for (int y = 0; y < height; y++)
361 {
362 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
363 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
364 for (int x = 0; x < width; x++)
365 {
366 dest[4 * x + 0] = 0;
367 dest[4 * x + 1] = 0;
368 dest[4 * x + 2] = 0;
369 dest[4 * x + 3] = source[x];
370 }
371 }
372}
373
374void Image::loadAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
375 int inputPitch, const void *input, size_t outputPitch, void *output) const
376{
377 const unsigned short *source = NULL;
378 unsigned short *dest = NULL;
379
380 for (int y = 0; y < height; y++)
381 {
382 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
383 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
384 for (int x = 0; x < width; x++)
385 {
386 dest[4 * x + 0] = 0;
387 dest[4 * x + 1] = 0;
388 dest[4 * x + 2] = 0;
389 dest[4 * x + 3] = source[x];
390 }
391 }
392}
393
394void Image::loadLuminanceData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
395 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
396{
397 const int destBytesPerPixel = native? 1: 4;
398 const unsigned char *source = NULL;
399 unsigned char *dest = NULL;
400
401 for (int y = 0; y < height; y++)
402 {
403 source = static_cast<const unsigned char*>(input) + y * inputPitch;
404 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
405
406 if (!native) // BGRA8 destination format
407 {
408 for (int x = 0; x < width; x++)
409 {
410 dest[4 * x + 0] = source[x];
411 dest[4 * x + 1] = source[x];
412 dest[4 * x + 2] = source[x];
413 dest[4 * x + 3] = 0xFF;
414 }
415 }
416 else // L8 destination format
417 {
418 memcpy(dest, source, width);
419 }
420 }
421}
422
423void Image::loadLuminanceFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
424 int inputPitch, const void *input, size_t outputPitch, void *output) const
425{
426 const float *source = NULL;
427 float *dest = NULL;
428
429 for (int y = 0; y < height; y++)
430 {
431 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
432 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
433 for (int x = 0; x < width; x++)
434 {
435 dest[4 * x + 0] = source[x];
436 dest[4 * x + 1] = source[x];
437 dest[4 * x + 2] = source[x];
438 dest[4 * x + 3] = 1.0f;
439 }
440 }
441}
442
443void Image::loadLuminanceHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
444 int inputPitch, const void *input, size_t outputPitch, void *output) const
445{
446 const unsigned short *source = NULL;
447 unsigned short *dest = NULL;
448
449 for (int y = 0; y < height; y++)
450 {
451 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
452 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
453 for (int x = 0; x < width; x++)
454 {
455 dest[4 * x + 0] = source[x];
456 dest[4 * x + 1] = source[x];
457 dest[4 * x + 2] = source[x];
458 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
459 }
460 }
461}
462
463void Image::loadLuminanceAlphaData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
464 int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
465{
466 const int destBytesPerPixel = native? 2: 4;
467 const unsigned char *source = NULL;
468 unsigned char *dest = NULL;
469
470 for (int y = 0; y < height; y++)
471 {
472 source = static_cast<const unsigned char*>(input) + y * inputPitch;
473 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * destBytesPerPixel;
474
475 if (!native) // BGRA8 destination format
476 {
477 for (int x = 0; x < width; x++)
478 {
479 dest[4 * x + 0] = source[2*x+0];
480 dest[4 * x + 1] = source[2*x+0];
481 dest[4 * x + 2] = source[2*x+0];
482 dest[4 * x + 3] = source[2*x+1];
483 }
484 }
485 else
486 {
487 memcpy(dest, source, width * 2);
488 }
489 }
490}
491
492void Image::loadLuminanceAlphaFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
493 int inputPitch, const void *input, size_t outputPitch, void *output) const
494{
495 const float *source = NULL;
496 float *dest = NULL;
497
498 for (int y = 0; y < height; y++)
499 {
500 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
501 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
502 for (int x = 0; x < width; x++)
503 {
504 dest[4 * x + 0] = source[2*x+0];
505 dest[4 * x + 1] = source[2*x+0];
506 dest[4 * x + 2] = source[2*x+0];
507 dest[4 * x + 3] = source[2*x+1];
508 }
509 }
510}
511
512void Image::loadLuminanceAlphaHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
513 int inputPitch, const void *input, size_t outputPitch, void *output) const
514{
515 const unsigned short *source = NULL;
516 unsigned short *dest = NULL;
517
518 for (int y = 0; y < height; y++)
519 {
520 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
521 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
522 for (int x = 0; x < width; x++)
523 {
524 dest[4 * x + 0] = source[2*x+0];
525 dest[4 * x + 1] = source[2*x+0];
526 dest[4 * x + 2] = source[2*x+0];
527 dest[4 * x + 3] = source[2*x+1];
528 }
529 }
530}
531
532void Image::loadRGBUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
533 int inputPitch, const void *input, size_t outputPitch, void *output) const
534{
535 const unsigned char *source = NULL;
536 unsigned char *dest = NULL;
537
538 for (int y = 0; y < height; y++)
539 {
540 source = static_cast<const unsigned char*>(input) + y * inputPitch;
541 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
542 for (int x = 0; x < width; x++)
543 {
544 dest[4 * x + 0] = source[x * 3 + 2];
545 dest[4 * x + 1] = source[x * 3 + 1];
546 dest[4 * x + 2] = source[x * 3 + 0];
547 dest[4 * x + 3] = 0xFF;
548 }
549 }
550}
551
552void Image::loadRGB565Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
553 int inputPitch, const void *input, size_t outputPitch, void *output) const
554{
555 const unsigned short *source = NULL;
556 unsigned char *dest = NULL;
557
558 for (int y = 0; y < height; y++)
559 {
560 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
561 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
562 for (int x = 0; x < width; x++)
563 {
564 unsigned short rgba = source[x];
565 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
566 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
567 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
568 dest[4 * x + 3] = 0xFF;
569 }
570 }
571}
572
573void Image::loadRGBFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
574 int inputPitch, const void *input, size_t outputPitch, void *output) const
575{
576 const float *source = NULL;
577 float *dest = NULL;
578
579 for (int y = 0; y < height; y++)
580 {
581 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
582 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
583 for (int x = 0; x < width; x++)
584 {
585 dest[4 * x + 0] = source[x * 3 + 0];
586 dest[4 * x + 1] = source[x * 3 + 1];
587 dest[4 * x + 2] = source[x * 3 + 2];
588 dest[4 * x + 3] = 1.0f;
589 }
590 }
591}
592
593void Image::loadRGBHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
594 int inputPitch, const void *input, size_t outputPitch, void *output) const
595{
596 const unsigned short *source = NULL;
597 unsigned short *dest = NULL;
598
599 for (int y = 0; y < height; y++)
600 {
601 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
602 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
603 for (int x = 0; x < width; x++)
604 {
605 dest[4 * x + 0] = source[x * 3 + 0];
606 dest[4 * x + 1] = source[x * 3 + 1];
607 dest[4 * x + 2] = source[x * 3 + 2];
608 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
609 }
610 }
611}
612
613void Image::loadRGBAUByteDataSSE2(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
614 int inputPitch, const void *input, size_t outputPitch, void *output) const
615{
616 const unsigned int *source = NULL;
617 unsigned int *dest = NULL;
618 __m128i brMask = _mm_set1_epi32(0x00ff00ff);
619
620 for (int y = 0; y < height; y++)
621 {
622 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
623 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
624 int x = 0;
625
626 // Make output writes aligned
627 for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
628 {
629 unsigned int rgba = source[x];
630 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
631 }
632
633 for (; x + 3 < width; x += 4)
634 {
635 __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
636 // Mask out g and a, which don't change
637 __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
638 // Mask out b and r
639 __m128i brComponents = _mm_and_si128(sourceData, brMask);
640 // Swap b and r
641 __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
642 __m128i result = _mm_or_si128(gaComponents, brSwapped);
643 _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
644 }
645
646 // Perform leftover writes
647 for (; x < width; x++)
648 {
649 unsigned int rgba = source[x];
650 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
651 }
652 }
653}
654
655void Image::loadRGBAUByteData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
656 int inputPitch, const void *input, size_t outputPitch, void *output) const
657{
658 const unsigned int *source = NULL;
659 unsigned int *dest = NULL;
660 for (int y = 0; y < height; y++)
661 {
662 source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
663 dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4);
664
665 for (int x = 0; x < width; x++)
666 {
667 unsigned int rgba = source[x];
668 dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
669 }
670 }
671}
672
673void Image::loadRGBA4444Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
674 int inputPitch, const void *input, size_t outputPitch, void *output) const
675{
676 const unsigned short *source = NULL;
677 unsigned char *dest = NULL;
678
679 for (int y = 0; y < height; y++)
680 {
681 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
682 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
683 for (int x = 0; x < width; x++)
684 {
685 unsigned short rgba = source[x];
686 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
687 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
688 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
689 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
690 }
691 }
692}
693
694void Image::loadRGBA5551Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
695 int inputPitch, const void *input, size_t outputPitch, void *output) const
696{
697 const unsigned short *source = NULL;
698 unsigned char *dest = NULL;
699
700 for (int y = 0; y < height; y++)
701 {
702 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
703 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
704 for (int x = 0; x < width; x++)
705 {
706 unsigned short rgba = source[x];
707 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
708 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
709 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
710 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
711 }
712 }
713}
714
715void Image::loadRGBAFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
716 int inputPitch, const void *input, size_t outputPitch, void *output) const
717{
718 const float *source = NULL;
719 float *dest = NULL;
720
721 for (int y = 0; y < height; y++)
722 {
723 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
724 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
725 memcpy(dest, source, width * 16);
726 }
727}
728
729void Image::loadRGBAHalfFloatData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
730 int inputPitch, const void *input, size_t outputPitch, void *output) const
731{
732 const unsigned char *source = NULL;
733 unsigned char *dest = NULL;
734
735 for (int y = 0; y < height; y++)
736 {
737 source = static_cast<const unsigned char*>(input) + y * inputPitch;
738 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8;
739 memcpy(dest, source, width * 8);
740 }
741}
742
743void Image::loadBGRAData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
744 int inputPitch, const void *input, size_t outputPitch, void *output) const
745{
746 const unsigned char *source = NULL;
747 unsigned char *dest = NULL;
748
749 for (int y = 0; y < height; y++)
750 {
751 source = static_cast<const unsigned char*>(input) + y * inputPitch;
752 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
753 memcpy(dest, source, width*4);
754 }
755}
756
757void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
758 int inputPitch, const void *input, size_t outputPitch, void *output) const {
759 switch (getD3DFormat())
760 {
761 case D3DFMT_DXT1:
762 loadDXT1Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
763 break;
764 case D3DFMT_DXT3:
765 loadDXT3Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
766 break;
767 case D3DFMT_DXT5:
768 loadDXT5Data(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
769 break;
770 }
771}
772
773static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
774 // A DXT1 block layout is:
775 // [0-1] color0.
776 // [2-3] color1.
777 // [4-7] color bitmap, 2 bits per pixel.
778 // So each of the 4-7 bytes represents one line, flipping a block is just
779 // flipping those bytes.
780
781 // First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
782 dest[0] = source[0];
783
784 // Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
785 dest[1] = (source[1] >> 24) |
786 ((source[1] << 8) & 0x00FF0000) |
787 ((source[1] >> 8) & 0x0000FF00) |
788 (source[1] << 24);
789}
790
791// Flips the first 2 lines of a DXT1 block in the y direction.
792static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
793 // See layout above.
794 dest[0] = source[0];
795 dest[1] = ((source[1] << 8) & 0x0000FF00) |
796 ((source[1] >> 8) & 0x000000FF);
797}
798
799// Flips a full DXT3 block in the y direction.
800static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
801 // A DXT3 block layout is:
802 // [0-7] alpha bitmap, 4 bits per pixel.
803 // [8-15] a DXT1 block.
804
805 // First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
806 dest[0] = (source[1] >> 16) | (source[1] << 16);
807 dest[1] = (source[0] >> 16) | (source[0] << 16);
808
809 // And flip the DXT1 block using the above function.
810 FlipCopyDXT1BlockFull(source + 2, dest + 2);
811}
812
813// Flips the first 2 lines of a DXT3 block in the y direction.
814static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
815 // See layout above.
816 dest[0] = (source[1] >> 16) | (source[1] << 16);
817 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
818}
819
820// Flips a full DXT5 block in the y direction.
821static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
822 // A DXT5 block layout is:
823 // [0] alpha0.
824 // [1] alpha1.
825 // [2-7] alpha bitmap, 3 bits per pixel.
826 // [8-15] a DXT1 block.
827
828 // The alpha bitmap doesn't easily map lines to bytes, so we have to
829 // interpret it correctly. Extracted from
830 // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
831 //
832 // The 6 "bits" bytes of the block are decoded into one 48-bit integer:
833 //
834 // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
835 // 256 * (bits_4 + 256 * bits_5))))
836 //
837 // bits is a 48-bit unsigned integer, from which a three-bit control code
838 // is extracted for a texel at location (x,y) in the block using:
839 //
840 // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
841 //
842 // where bit 47 is the most significant and bit 0 is the least
843 // significant bit.
844 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
845 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
846 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
847 unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
848 // swap lines 0 and 1 in line_0_1.
849 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
850 ((line_0_1 & 0xfff000) >> 12);
851 // swap lines 2 and 3 in line_2_3.
852 unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
853 ((line_2_3 & 0xfff000) >> 12);
854 destBytes[0] = sourceBytes[0];
855 destBytes[1] = sourceBytes[1];
856 destBytes[2] = line_3_2 & 0xff;
857 destBytes[3] = (line_3_2 & 0xff00) >> 8;
858 destBytes[4] = (line_3_2 & 0xff0000) >> 16;
859 destBytes[5] = line_1_0 & 0xff;
860 destBytes[6] = (line_1_0 & 0xff00) >> 8;
861 destBytes[7] = (line_1_0 & 0xff0000) >> 16;
862
863 // And flip the DXT1 block using the above function.
864 FlipCopyDXT1BlockFull(source + 2, dest + 2);
865}
866
867// Flips the first 2 lines of a DXT5 block in the y direction.
868static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
869 // See layout above.
870 const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
871 unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
872 unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
873 unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
874 ((line_0_1 & 0xfff000) >> 12);
875 destBytes[0] = sourceBytes[0];
876 destBytes[1] = sourceBytes[1];
877 destBytes[2] = line_1_0 & 0xff;
878 destBytes[3] = (line_1_0 & 0xff00) >> 8;
879 destBytes[4] = (line_1_0 & 0xff0000) >> 16;
880 FlipCopyDXT1BlockHalf(source + 2, dest + 2);
881}
882
883void Image::loadDXT1Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
884 int inputPitch, const void *input, size_t outputPitch, void *output) const
885{
886 ASSERT(xoffset % 4 == 0);
887 ASSERT(yoffset % 4 == 0);
888 ASSERT(width % 4 == 0 || width == 2 || width == 1);
889 ASSERT(inputPitch % 8 == 0);
890 ASSERT(outputPitch % 8 == 0);
891
892 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
893 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
894
895 // Round width up in case it is less than 4.
896 int blocksAcross = (width + 3) / 4;
897 int intsAcross = blocksAcross * 2;
898
899 switch (height)
900 {
901 case 1:
902 for (int x = 0; x < intsAcross; x += 2)
903 {
904 // just copy the block
905 dest[x] = source[x];
906 dest[x + 1] = source[x + 1];
907 }
908 break;
909 case 2:
910 for (int x = 0; x < intsAcross; x += 2)
911 {
912 FlipCopyDXT1BlockHalf(source + x, dest + x);
913 }
914 break;
915 default:
916 ASSERT(height % 4 == 0);
917 for (int y = 0; y < height / 4; ++y)
918 {
919 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
920 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
921
922 for (int x = 0; x < intsAcross; x += 2)
923 {
924 FlipCopyDXT1BlockFull(source + x, dest + x);
925 }
926 }
927 break;
928 }
929}
930
931void Image::loadDXT3Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
932 int inputPitch, const void *input, size_t outputPitch, void *output) const
933{
934 ASSERT(xoffset % 4 == 0);
935 ASSERT(yoffset % 4 == 0);
936 ASSERT(width % 4 == 0 || width == 2 || width == 1);
937 ASSERT(inputPitch % 16 == 0);
938 ASSERT(outputPitch % 16 == 0);
939
940 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
941 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
942
943 // Round width up in case it is less than 4.
944 int blocksAcross = (width + 3) / 4;
945 int intsAcross = blocksAcross * 4;
946
947 switch (height)
948 {
949 case 1:
950 for (int x = 0; x < intsAcross; x += 4)
951 {
952 // just copy the block
953 dest[x] = source[x];
954 dest[x + 1] = source[x + 1];
955 dest[x + 2] = source[x + 2];
956 dest[x + 3] = source[x + 3];
957 }
958 break;
959 case 2:
960 for (int x = 0; x < intsAcross; x += 4)
961 {
962 FlipCopyDXT3BlockHalf(source + x, dest + x);
963 }
964 break;
965 default:
966 ASSERT(height % 4 == 0);
967 for (int y = 0; y < height / 4; ++y)
968 {
969 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
970 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
971
972 for (int x = 0; x < intsAcross; x += 4)
973 {
974 FlipCopyDXT3BlockFull(source + x, dest + x);
975 }
976 }
977 break;
978 }
979}
980
981void Image::loadDXT5Data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
982 int inputPitch, const void *input, size_t outputPitch, void *output) const
983{
984 ASSERT(xoffset % 4 == 0);
985 ASSERT(yoffset % 4 == 0);
986 ASSERT(width % 4 == 0 || width == 2 || width == 1);
987 ASSERT(inputPitch % 16 == 0);
988 ASSERT(outputPitch % 16 == 0);
989
990 const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
991 unsigned int *dest = reinterpret_cast<unsigned int*>(output);
992
993 // Round width up in case it is less than 4.
994 int blocksAcross = (width + 3) / 4;
995 int intsAcross = blocksAcross * 4;
996
997 switch (height)
998 {
999 case 1:
1000 for (int x = 0; x < intsAcross; x += 4)
1001 {
1002 // just copy the block
1003 dest[x] = source[x];
1004 dest[x + 1] = source[x + 1];
1005 dest[x + 2] = source[x + 2];
1006 dest[x + 3] = source[x + 3];
1007 }
1008 break;
1009 case 2:
1010 for (int x = 0; x < intsAcross; x += 4)
1011 {
1012 FlipCopyDXT5BlockHalf(source + x, dest + x);
1013 }
1014 break;
1015 default:
1016 ASSERT(height % 4 == 0);
1017 for (int y = 0; y < height / 4; ++y)
1018 {
1019 const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
1020 unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
1021
1022 for (int x = 0; x < intsAcross; x += 4)
1023 {
1024 FlipCopyDXT5BlockFull(source + x, dest + x);
1025 }
1026 }
1027 break;
1028 }
1029}
1030
daniel@transgaming.com90cfcc92011-11-09 17:45:48 +00001031// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
1032void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
1033{
1034 IDirect3DDevice9 *device = getDevice();
1035 IDirect3DSurface9 *renderTargetData = NULL;
1036 D3DSURFACE_DESC description;
1037 renderTarget->GetDesc(&description);
1038
1039 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
1040
1041 if (FAILED(result))
1042 {
1043 ERR("Could not create matching destination surface.");
1044 return error(GL_OUT_OF_MEMORY);
1045 }
1046
1047 result = device->GetRenderTargetData(renderTarget, renderTargetData);
1048
1049 if (FAILED(result))
1050 {
1051 ERR("GetRenderTargetData unexpectedly failed.");
1052 renderTargetData->Release();
1053 return error(GL_OUT_OF_MEMORY);
1054 }
1055
1056 RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
1057 int destYOffset = transformPixelYOffset(yoffset, height, mHeight);
1058 RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
1059
1060 if (isRenderable())
1061 {
1062 result = D3DXLoadSurfaceFromSurface(getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
1063
1064 if (FAILED(result))
1065 {
1066 ERR("Copying surfaces unexpectedly failed.");
1067 renderTargetData->Release();
1068 return error(GL_OUT_OF_MEMORY);
1069 }
1070 }
1071 else
1072 {
1073 D3DLOCKED_RECT sourceLock = {0};
1074 result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
1075
1076 if (FAILED(result))
1077 {
1078 ERR("Failed to lock the source surface (rectangle might be invalid).");
1079 renderTargetData->Release();
1080 return error(GL_OUT_OF_MEMORY);
1081 }
1082
1083 D3DLOCKED_RECT destLock = {0};
1084 result = lock(&destLock, &destRect);
1085
1086 if (FAILED(result))
1087 {
1088 ERR("Failed to lock the destination surface (rectangle might be invalid).");
1089 renderTargetData->UnlockRect();
1090 renderTargetData->Release();
1091 return error(GL_OUT_OF_MEMORY);
1092 }
1093
1094 if (destLock.pBits && sourceLock.pBits)
1095 {
1096 unsigned char *source = (unsigned char*)sourceLock.pBits;
1097 unsigned char *dest = (unsigned char*)destLock.pBits;
1098
1099 switch (description.Format)
1100 {
1101 case D3DFMT_X8R8G8B8:
1102 case D3DFMT_A8R8G8B8:
1103 switch(getD3DFormat())
1104 {
1105 case D3DFMT_L8:
1106 for(int y = 0; y < height; y++)
1107 {
1108 for(int x = 0; x < width; x++)
1109 {
1110 dest[x] = source[x * 4 + 2];
1111 }
1112
1113 source += sourceLock.Pitch;
1114 dest += destLock.Pitch;
1115 }
1116 break;
1117 case D3DFMT_A8L8:
1118 for(int y = 0; y < height; y++)
1119 {
1120 for(int x = 0; x < width; x++)
1121 {
1122 dest[x * 2 + 0] = source[x * 4 + 2];
1123 dest[x * 2 + 1] = source[x * 4 + 3];
1124 }
1125
1126 source += sourceLock.Pitch;
1127 dest += destLock.Pitch;
1128 }
1129 break;
1130 default:
1131 UNREACHABLE();
1132 }
1133 break;
1134 case D3DFMT_R5G6B5:
1135 switch(getD3DFormat())
1136 {
1137 case D3DFMT_L8:
1138 for(int y = 0; y < height; y++)
1139 {
1140 for(int x = 0; x < width; x++)
1141 {
1142 unsigned char red = source[x * 2 + 1] & 0xF8;
1143 dest[x] = red | (red >> 5);
1144 }
1145
1146 source += sourceLock.Pitch;
1147 dest += destLock.Pitch;
1148 }
1149 break;
1150 default:
1151 UNREACHABLE();
1152 }
1153 break;
1154 case D3DFMT_A1R5G5B5:
1155 switch(getD3DFormat())
1156 {
1157 case D3DFMT_L8:
1158 for(int y = 0; y < height; y++)
1159 {
1160 for(int x = 0; x < width; x++)
1161 {
1162 unsigned char red = source[x * 2 + 1] & 0x7C;
1163 dest[x] = (red << 1) | (red >> 4);
1164 }
1165
1166 source += sourceLock.Pitch;
1167 dest += destLock.Pitch;
1168 }
1169 break;
1170 case D3DFMT_A8L8:
1171 for(int y = 0; y < height; y++)
1172 {
1173 for(int x = 0; x < width; x++)
1174 {
1175 unsigned char red = source[x * 2 + 1] & 0x7C;
1176 dest[x * 2 + 0] = (red << 1) | (red >> 4);
1177 dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
1178 }
1179
1180 source += sourceLock.Pitch;
1181 dest += destLock.Pitch;
1182 }
1183 break;
1184 default:
1185 UNREACHABLE();
1186 }
1187 break;
1188 default:
1189 UNREACHABLE();
1190 }
1191 }
1192
1193 unlock();
1194 renderTargetData->UnlockRect();
1195 }
1196
1197 renderTargetData->Release();
1198
1199 mDirty = true;
1200}
1201
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001202TextureStorage::TextureStorage(bool renderable) : mIsRenderable(renderable)
1203{
1204}
1205
1206TextureStorage::~TextureStorage()
1207{
1208}
1209
1210bool TextureStorage::isRenderable()
1211{
1212 return mIsRenderable;
1213}
1214
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001215Texture::Texture(GLuint id) : RefCountObject(id)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001216{
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001217 mSerial = 0;
1218
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001219 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
1220 mMagFilter = GL_LINEAR;
1221 mWrapS = GL_REPEAT;
1222 mWrapT = GL_REPEAT;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001223 mDirtyParameters = true;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001224
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001225 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001226}
1227
1228Texture::~Texture()
1229{
1230}
1231
1232Blit *Texture::getBlitter()
1233{
1234 Context *context = getContext();
1235 return context->getBlitter();
1236}
1237
1238// Returns true on successful filter state update (valid enum parameter)
1239bool Texture::setMinFilter(GLenum filter)
1240{
1241 switch (filter)
1242 {
1243 case GL_NEAREST:
1244 case GL_LINEAR:
1245 case GL_NEAREST_MIPMAP_NEAREST:
1246 case GL_LINEAR_MIPMAP_NEAREST:
1247 case GL_NEAREST_MIPMAP_LINEAR:
1248 case GL_LINEAR_MIPMAP_LINEAR:
1249 {
1250 if (mMinFilter != filter)
1251 {
1252 mMinFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001253 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001254 }
1255 return true;
1256 }
1257 default:
1258 return false;
1259 }
1260}
1261
1262// Returns true on successful filter state update (valid enum parameter)
1263bool Texture::setMagFilter(GLenum filter)
1264{
1265 switch (filter)
1266 {
1267 case GL_NEAREST:
1268 case GL_LINEAR:
1269 {
1270 if (mMagFilter != filter)
1271 {
1272 mMagFilter = filter;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001273 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001274 }
1275 return true;
1276 }
1277 default:
1278 return false;
1279 }
1280}
1281
1282// Returns true on successful wrap state update (valid enum parameter)
1283bool Texture::setWrapS(GLenum wrap)
1284{
1285 switch (wrap)
1286 {
1287 case GL_REPEAT:
1288 case GL_CLAMP_TO_EDGE:
1289 case GL_MIRRORED_REPEAT:
1290 {
1291 if (mWrapS != wrap)
1292 {
1293 mWrapS = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001294 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001295 }
1296 return true;
1297 }
1298 default:
1299 return false;
1300 }
1301}
1302
1303// Returns true on successful wrap state update (valid enum parameter)
1304bool Texture::setWrapT(GLenum wrap)
1305{
1306 switch (wrap)
1307 {
1308 case GL_REPEAT:
1309 case GL_CLAMP_TO_EDGE:
1310 case GL_MIRRORED_REPEAT:
1311 {
1312 if (mWrapT != wrap)
1313 {
1314 mWrapT = wrap;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001315 mDirtyParameters = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001316 }
1317 return true;
1318 }
1319 default:
1320 return false;
1321 }
1322}
1323
1324GLenum Texture::getMinFilter() const
1325{
1326 return mMinFilter;
1327}
1328
1329GLenum Texture::getMagFilter() const
1330{
1331 return mMagFilter;
1332}
1333
1334GLenum Texture::getWrapS() const
1335{
1336 return mWrapS;
1337}
1338
1339GLenum Texture::getWrapT() const
1340{
1341 return mWrapT;
1342}
1343
daniel@transgaming.com61208202011-03-21 16:38:50 +00001344void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001345{
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001346 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001347 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001348 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001349 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001350
1351 if (SUCCEEDED(result))
1352 {
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +00001353 image->loadData(0, 0, image->getWidth(), image->getHeight(), image->getType(), unpackAlignment, pixels, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001354 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001355 }
1356
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001357 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001358 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001359}
1360
daniel@transgaming.com61208202011-03-21 16:38:50 +00001361void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001362{
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001363 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001364 {
1365 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001366 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001367
1368 if (SUCCEEDED(result))
1369 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001370 int inputPitch = ComputeCompressedPitch(image->getWidth(), image->getFormat());
1371 int inputSize = ComputeCompressedSize(image->getWidth(), image->getHeight(), image->getFormat());
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +00001372 image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001373 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001374 }
1375
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001376 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001377 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001378}
1379
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001380bool 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 +00001381{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001382 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001383 {
1384 error(GL_INVALID_VALUE);
1385 return false;
1386 }
1387
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001388 if (IsCompressed(image->getFormat()))
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001389 {
1390 error(GL_INVALID_OPERATION);
1391 return false;
1392 }
1393
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001394 if (format != image->getFormat())
jbauman@chromium.orge2f954c2011-05-03 20:45:27 +00001395 {
1396 error(GL_INVALID_OPERATION);
1397 return false;
1398 }
1399
daniel@transgaming.com73de05a2011-11-09 17:45:24 +00001400 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001401 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001402 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001403 HRESULT result = image->lock(&locked, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001404
1405 if (SUCCEEDED(result))
1406 {
daniel@transgaming.com0c67f3c2011-11-09 17:45:38 +00001407 image->loadData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, type, unpackAlignment, pixels, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001408 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001409 }
1410
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001411 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001412 }
1413
1414 return true;
1415}
1416
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001417bool 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 +00001418{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001419 if (width + xoffset > image->getWidth() || height + yoffset > image->getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001420 {
1421 error(GL_INVALID_VALUE);
1422 return false;
1423 }
1424
1425 if (format != getInternalFormat())
1426 {
1427 error(GL_INVALID_OPERATION);
1428 return false;
1429 }
1430
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001431 if (pixels != NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001432 {
1433 RECT updateRegion;
1434 updateRegion.left = xoffset;
1435 updateRegion.right = xoffset + width;
1436 updateRegion.bottom = yoffset + height;
1437 updateRegion.top = yoffset;
1438
1439 D3DLOCKED_RECT locked;
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001440 HRESULT result = image->lock(&locked, &updateRegion);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001441
1442 if (SUCCEEDED(result))
1443 {
1444 int inputPitch = ComputeCompressedPitch(width, format);
1445 int inputSize = ComputeCompressedSize(width, height, format);
daniel@transgaming.comf749f0e2011-11-09 17:45:34 +00001446 image->loadCompressedData(xoffset, transformPixelYOffset(yoffset, height, image->getHeight()), width, height, -inputPitch, static_cast<const char*>(pixels) + inputSize - inputPitch, locked.Pitch, locked.pBits);
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001447 image->unlock();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001448 }
1449
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001450 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001451 }
1452
1453 return true;
1454}
1455
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001456IDirect3DBaseTexture9 *Texture::getTexture()
1457{
1458 if (!isComplete())
1459 {
1460 return NULL;
1461 }
1462
daniel@transgaming.comaed18322011-03-21 16:38:13 +00001463 if (!getBaseTexture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001464 {
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001465 createTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001466 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001467
daniel@transgaming.comc50edcb2011-03-21 16:38:40 +00001468 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001469
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001470 return getBaseTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001471}
1472
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001473bool Texture::hasDirtyParameters() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001474{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001475 return mDirtyParameters;
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001476}
1477
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001478bool Texture::hasDirtyImages() const
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00001479{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001480 return mDirtyImages;
daniel@transgaming.com38e76e52011-03-21 16:39:10 +00001481}
1482
1483void Texture::resetDirty()
1484{
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001485 mDirtyParameters = false;
1486 mDirtyImages = false;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001487}
1488
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001489unsigned int Texture::getSerial() const
1490{
1491 return mSerial;
1492}
1493
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001494GLint Texture::creationLevels(GLsizei width, GLsizei height) const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001495{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001496 if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001497 {
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001498 return 0; // Maximum number of levels
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001499 }
1500 else
1501 {
1502 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1503 return 1;
1504 }
1505}
1506
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001507GLint Texture::creationLevels(GLsizei size) const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001508{
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001509 return creationLevels(size, size);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001510}
1511
1512int Texture::levelCount() const
1513{
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001514 return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001515}
1516
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00001517unsigned int Texture::issueSerial()
1518{
1519 return mCurrentSerial++;
1520}
1521
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001522TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *texture, bool renderable) : TextureStorage(renderable)
1523{
1524 mTexture = texture;
1525}
1526
1527TextureStorage2D::~TextureStorage2D()
1528{
1529 mTexture->Release();
1530}
1531
1532IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level)
1533{
1534 IDirect3DSurface9 *surface = NULL;
1535
1536 if (mTexture)
1537 {
1538 HRESULT result = mTexture->GetSurfaceLevel(level, &surface);
1539 ASSERT(SUCCEEDED(result));
1540 }
1541
1542 return surface;
1543}
1544
1545IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
1546{
1547 return mTexture;
1548}
1549
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001550Texture2D::Texture2D(GLuint id) : Texture(id)
1551{
1552 mTexture = NULL;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001553 mSurface = NULL;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001554}
1555
1556Texture2D::~Texture2D()
1557{
1558 mColorbufferProxy.set(NULL);
1559
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001560 delete mTexture;
1561 mTexture = NULL;
1562
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001563 if (mSurface)
1564 {
1565 mSurface->setBoundTexture(NULL);
1566 mSurface = NULL;
1567 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001568}
1569
1570GLenum Texture2D::getTarget() const
1571{
1572 return GL_TEXTURE_2D;
1573}
1574
daniel@transgaming.com61208202011-03-21 16:38:50 +00001575GLsizei Texture2D::getWidth() const
1576{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001577 return mImageArray[0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001578}
1579
1580GLsizei Texture2D::getHeight() const
1581{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001582 return mImageArray[0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001583}
1584
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001585GLenum Texture2D::getInternalFormat() const
1586{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001587 return mImageArray[0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001588}
1589
daniel@transgaming.com61208202011-03-21 16:38:50 +00001590GLenum Texture2D::getType() const
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001591{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001592 return mImageArray[0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00001593}
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001594
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001595D3DFORMAT Texture2D::getD3DFormat() const
1596{
1597 return mImageArray[0].getD3DFormat();
1598}
1599
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001600void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001601{
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001602 releaseTexImage();
1603
daniel@transgaming.com41634052011-11-09 17:46:24 +00001604 bool redefined = mImageArray[level].redefine(format, width, height, type);
daniel@transgaming.comc9ba4ad2011-11-09 17:44:35 +00001605
daniel@transgaming.com41634052011-11-09 17:46:24 +00001606 if (mTexture && redefined)
daniel@transgaming.com61208202011-03-21 16:38:50 +00001607 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001608 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1609 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001610 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001611 }
1612
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001613 delete mTexture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001614 mTexture = NULL;
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001615 mSerial = 0;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001616 mDirtyImages = true;
apatrick@chromium.org57a2cd62011-06-08 00:04:07 +00001617 mColorbufferProxy.set(NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001618 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001619}
1620
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001621void 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 +00001622{
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001623 redefineImage(level, format, width, height, type);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001624
daniel@transgaming.com61208202011-03-21 16:38:50 +00001625 Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001626}
1627
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001628void Texture2D::bindTexImage(egl::Surface *surface)
1629{
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001630 releaseTexImage();
1631
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001632 GLenum format;
1633
1634 switch(surface->getFormat())
1635 {
1636 case D3DFMT_A8R8G8B8:
1637 format = GL_RGBA;
1638 break;
1639 case D3DFMT_X8R8G8B8:
1640 format = GL_RGB;
1641 break;
1642 default:
1643 UNIMPLEMENTED();
1644 return;
1645 }
1646
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001647 mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE);
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001648
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001649 delete mTexture;
1650 mTexture = new TextureStorage2D(surface->getOffscreenTexture(), true);
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001651 mSerial = issueSerial();
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00001652 mColorbufferProxy.set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001653 mDirtyImages = true;
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001654 mSurface = surface;
1655 mSurface->setBoundTexture(this);
1656}
1657
1658void Texture2D::releaseTexImage()
1659{
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001660 if (mSurface)
1661 {
1662 mSurface->setBoundTexture(NULL);
1663 mSurface = NULL;
1664
1665 if (mTexture)
1666 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001667 delete mTexture;
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001668 mTexture = NULL;
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001669 mSerial = 0;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00001670 mColorbufferProxy.set(NULL);
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001671 }
1672
1673 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1674 {
1675 mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE);
1676 }
1677 }
jbauman@chromium.orgae345802011-03-30 22:04:25 +00001678}
1679
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001680void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001681{
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001682 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001683
daniel@transgaming.com61208202011-03-21 16:38:50 +00001684 Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001685}
1686
1687void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1688{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001689 ASSERT(mImageArray[level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001690
1691 if (level < levelCount())
1692 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001693 IDirect3DSurface9 *destLevel = mTexture->getSurfaceLevel(level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001694
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001695 if (destLevel)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001696 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001697 Image *image = &mImageArray[level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001698
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001699 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001700 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001701
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001702 HRESULT result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001703 ASSERT(SUCCEEDED(result));
1704
1705 destLevel->Release();
1706
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001707 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001708 }
1709 }
1710}
1711
1712void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
1713{
1714 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1715 {
1716 commitRect(level, xoffset, yoffset, width, height);
1717 }
1718}
1719
1720void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1721{
1722 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1723 {
1724 commitRect(level, xoffset, yoffset, width, height);
1725 }
1726}
1727
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00001728void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001729{
1730 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1731
1732 if (!renderTarget)
1733 {
1734 ERR("Failed to retrieve the render target.");
1735 return error(GL_OUT_OF_MEMORY);
1736 }
1737
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00001738 redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001739
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001740 if (!mImageArray[level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001741 {
daniel@transgaming.com90cfcc92011-11-09 17:45:48 +00001742 mImageArray[level].copy(0, 0, x, y, width, height, renderTarget);
1743 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001744 }
1745 else
1746 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001747 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001748 {
1749 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001750 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00001751
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001752 mImageArray[level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001753
1754 if (width != 0 && height != 0 && level < levelCount())
1755 {
1756 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1757 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1758 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1759 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1760 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001761
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001762 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001763
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001764 IDirect3DSurface9 *dest = mTexture->getSurfaceLevel(level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001765
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00001766 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001767 dest->Release();
1768 }
1769 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001770}
1771
1772void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1773{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001774 if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001775 {
1776 return error(GL_INVALID_VALUE);
1777 }
1778
1779 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1780
1781 if (!renderTarget)
1782 {
1783 ERR("Failed to retrieve the render target.");
1784 return error(GL_OUT_OF_MEMORY);
1785 }
1786
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001787 if (!mImageArray[level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001788 {
daniel@transgaming.com90cfcc92011-11-09 17:45:48 +00001789 mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget);
1790 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001791 }
1792 else
1793 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001794 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001795 {
1796 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001797 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00001798
1799 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001800
1801 if (level < levelCount())
1802 {
1803 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
1804 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
1805 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
1806 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
1807 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
1808
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001809 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001810
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001811 IDirect3DSurface9 *dest = mTexture->getSurfaceLevel(level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001812
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001813 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001814 dest->Release();
1815 }
1816 }
1817}
1818
1819// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1820bool Texture2D::isComplete() const
1821{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001822 GLsizei width = mImageArray[0].getWidth();
1823 GLsizei height = mImageArray[0].getHeight();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001824
1825 if (width <= 0 || height <= 0)
1826 {
1827 return false;
1828 }
1829
1830 bool mipmapping = false;
1831
1832 switch (mMinFilter)
1833 {
1834 case GL_NEAREST:
1835 case GL_LINEAR:
1836 mipmapping = false;
1837 break;
1838 case GL_NEAREST_MIPMAP_NEAREST:
1839 case GL_LINEAR_MIPMAP_NEAREST:
1840 case GL_NEAREST_MIPMAP_LINEAR:
1841 case GL_LINEAR_MIPMAP_LINEAR:
1842 mipmapping = true;
1843 break;
1844 default: UNREACHABLE();
1845 }
1846
daniel@transgaming.combbeffbb2011-11-09 17:46:11 +00001847 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
1848 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001849 {
1850 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1851 {
1852 return false;
1853 }
1854 }
1855
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001856 bool npot = getContext()->supportsNonPower2Texture();
1857
1858 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001859 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001860 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
1861 (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1862 {
1863 return false;
1864 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001865 }
1866
1867 if (mipmapping)
1868 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001869 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001870 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00001871 if (!isPow2(width) || !isPow2(height))
1872 {
1873 return false;
1874 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001875 }
1876
1877 int q = log2(std::max(width, height));
1878
1879 for (int level = 1; level <= q; level++)
1880 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001881 if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001882 {
1883 return false;
1884 }
1885
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001886 if (mImageArray[level].getType() != mImageArray[0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00001887 {
1888 return false;
1889 }
1890
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001891 if (mImageArray[level].getWidth() != std::max(1, width >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001892 {
1893 return false;
1894 }
1895
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001896 if (mImageArray[level].getHeight() != std::max(1, height >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001897 {
1898 return false;
1899 }
1900 }
1901 }
1902
1903 return true;
1904}
1905
1906bool Texture2D::isCompressed() const
1907{
1908 return IsCompressed(getInternalFormat());
1909}
1910
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001911IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
1912{
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001913 return mTexture ? mTexture->getBaseTexture() : NULL;
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001914}
1915
1916// Constructs a Direct3D 9 texture resource from the texture images
1917void Texture2D::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001918{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001919 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001920 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001921 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001922
daniel@transgaming.com61208202011-03-21 16:38:50 +00001923 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001924 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 +00001925
1926 if (FAILED(result))
1927 {
1928 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001929 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001930 }
1931
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001932 delete mTexture;
1933 mTexture = new TextureStorage2D(texture, false);
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00001934 mSerial = issueSerial();
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00001935 mColorbufferProxy.set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00001936 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001937}
1938
1939void Texture2D::updateTexture()
1940{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001941 int levels = levelCount();
1942
1943 for (int level = 0; level < levels; level++)
1944 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00001945 Image *image = &mImageArray[level];
1946
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00001947 if (image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001948 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001949 commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001950 }
1951 }
1952}
1953
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001954void Texture2D::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001955{
1956 IDirect3DTexture9 *texture = NULL;
1957
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001958 if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001959 {
1960 egl::Display *display = getDisplay();
1961 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00001962 D3DFORMAT format = mImageArray[0].getD3DFormat();
daniel@transgaming.comf81103a2011-11-09 17:46:28 +00001963 GLint levels = creationLevels(mImageArray[0].getWidth(), mImageArray[0].getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001964
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00001965 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 +00001966
1967 if (FAILED(result))
1968 {
1969 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001970 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001971 }
1972
1973 if (mTexture != NULL)
1974 {
1975 int levels = levelCount();
1976 for (int i = 0; i < levels; i++)
1977 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001978 IDirect3DSurface9 *source = mTexture->getSurfaceLevel(i);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001979
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00001980 if (!source)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001981 {
1982 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1983
1984 texture->Release();
1985
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001986 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001987 }
1988
1989 IDirect3DSurface9 *dest;
1990 result = texture->GetSurfaceLevel(i, &dest);
1991
1992 if (FAILED(result))
1993 {
1994 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1995
1996 texture->Release();
1997 source->Release();
1998
daniel@transgaming.com68076a02011-03-21 16:38:09 +00001999 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002000 }
2001
2002 display->endScene();
2003 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
2004
2005 if (FAILED(result))
2006 {
2007 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2008
2009 texture->Release();
2010 source->Release();
2011 dest->Release();
2012
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002013 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002014 }
2015
2016 source->Release();
2017 dest->Release();
2018 }
2019 }
2020 }
2021
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002022 delete mTexture;
2023 mTexture = new TextureStorage2D(texture, true);
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00002024 mSerial = issueSerial();
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002025 mColorbufferProxy.set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002026 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002027}
2028
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002029void Texture2D::generateMipmaps()
2030{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002031 if (!getContext()->supportsNonPower2Texture())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002032 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002033 if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002034 {
2035 return error(GL_INVALID_OPERATION);
2036 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002037 }
2038
2039 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002040 unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002041 for (unsigned int i = 1; i <= q; i++)
2042 {
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00002043 redefineImage(i, mImageArray[0].getFormat(),
2044 std::max(mImageArray[0].getWidth() >> i, 1),
2045 std::max(mImageArray[0].getHeight() >> i, 1),
2046 mImageArray[0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002047 }
2048
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002049 if (mTexture && mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002050 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002051 for (unsigned int i = 1; i <= q; i++)
2052 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002053 IDirect3DSurface9 *upper = mTexture->getSurfaceLevel(i - 1);
2054 IDirect3DSurface9 *lower = mTexture->getSurfaceLevel(i);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002055
2056 if (upper != NULL && lower != NULL)
2057 {
2058 getBlitter()->boxFilter(upper, lower);
2059 }
2060
2061 if (upper != NULL) upper->Release();
2062 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002063
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002064 mImageArray[i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002065 }
2066 }
2067 else
2068 {
2069 for (unsigned int i = 1; i <= q; i++)
2070 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002071 if (mImageArray[i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002072 {
2073 return error(GL_OUT_OF_MEMORY);
2074 }
2075
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002076 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 +00002077 {
2078 ERR(" failed to load filter %d to %d.", i - 1, i);
2079 }
2080
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002081 mImageArray[i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002082 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002083 }
2084}
2085
2086Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
2087{
2088 if (target != GL_TEXTURE_2D)
2089 {
2090 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2091 }
2092
2093 if (mColorbufferProxy.get() == NULL)
2094 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002095 mColorbufferProxy.set(new Renderbuffer(id(), new RenderbufferTexture(this, target)));
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002096 }
2097
2098 return mColorbufferProxy.get();
2099}
2100
2101IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
2102{
2103 ASSERT(target == GL_TEXTURE_2D);
2104
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002105 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.com61208202011-03-21 16:38:50 +00002106 {
2107 convertToRenderTarget();
2108 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002109
2110 if (mTexture == NULL)
2111 {
2112 return NULL;
2113 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002114
2115 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002116
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002117 IDirect3DSurface9 *renderTarget = mTexture->getSurfaceLevel(0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002118
2119 return renderTarget;
2120}
2121
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002122TextureStorageCubeMap::TextureStorageCubeMap(IDirect3DCubeTexture9 *texture, bool renderable) : TextureStorage(renderable)
2123{
2124 mTexture = texture;
2125}
2126
2127TextureStorageCubeMap::~TextureStorageCubeMap()
2128{
2129 mTexture->Release();
2130}
2131
2132IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(int face, int level)
2133{
2134 IDirect3DSurface9 *surface = NULL;
2135
2136 if (mTexture)
2137 {
2138 HRESULT result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(face), level, &surface);
2139 ASSERT(SUCCEEDED(result));
2140 }
2141
2142 return surface;
2143}
2144
2145IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
2146{
2147 return mTexture;
2148}
2149
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002150TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
2151{
2152 mTexture = NULL;
2153}
2154
2155TextureCubeMap::~TextureCubeMap()
2156{
2157 for (int i = 0; i < 6; i++)
2158 {
2159 mFaceProxies[i].set(NULL);
2160 }
2161
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002162 delete mTexture;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002163}
2164
2165GLenum TextureCubeMap::getTarget() const
2166{
2167 return GL_TEXTURE_CUBE_MAP;
2168}
2169
daniel@transgaming.com61208202011-03-21 16:38:50 +00002170GLsizei TextureCubeMap::getWidth() const
2171{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002172 return mImageArray[0][0].getWidth();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002173}
2174
2175GLsizei TextureCubeMap::getHeight() const
2176{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002177 return mImageArray[0][0].getHeight();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002178}
2179
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002180GLenum TextureCubeMap::getInternalFormat() const
2181{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002182 return mImageArray[0][0].getFormat();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002183}
2184
daniel@transgaming.com61208202011-03-21 16:38:50 +00002185GLenum TextureCubeMap::getType() const
2186{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002187 return mImageArray[0][0].getType();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002188}
2189
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002190D3DFORMAT TextureCubeMap::getD3DFormat() const
2191{
2192 return mImageArray[0][0].getD3DFormat();
2193}
2194
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002195void 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 +00002196{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002197 setImage(0, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002198}
2199
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002200void 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 +00002201{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002202 setImage(1, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002203}
2204
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002205void 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 +00002206{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002207 setImage(2, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002208}
2209
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002210void 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 +00002211{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002212 setImage(3, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002213}
2214
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002215void 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 +00002216{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002217 setImage(4, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002218}
2219
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002220void 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 +00002221{
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002222 setImage(5, level, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002223}
2224
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002225void 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 +00002226{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002227 redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002228
daniel@transgaming.com61208202011-03-21 16:38:50 +00002229 Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002230}
2231
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002232void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002233{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002234 ASSERT(mImageArray[face][level].getSurface() != NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002235
2236 if (level < levelCount())
2237 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002238 IDirect3DSurface9 *destLevel = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002239 ASSERT(destLevel != NULL);
2240
2241 if (destLevel != NULL)
2242 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002243 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002244
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002245 RECT sourceRect = transformPixelRect(xoffset, yoffset, width, height, image->getHeight());
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002246 POINT destPoint = {sourceRect.left, sourceRect.top};
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002247
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002248 HRESULT result = getDevice()->UpdateSurface(image->getSurface(), &sourceRect, destLevel, &destPoint);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002249 ASSERT(SUCCEEDED(result));
2250
2251 destLevel->Release();
2252
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002253 image->markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002254 }
2255 }
2256}
2257
2258void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2259{
2260 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
2261 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002262 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002263 }
2264}
2265
2266void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
2267{
2268 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
2269 {
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002270 commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002271 }
2272}
2273
2274// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
2275bool TextureCubeMap::isComplete() const
2276{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002277 int size = mImageArray[0][0].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002278
2279 if (size <= 0)
2280 {
2281 return false;
2282 }
2283
2284 bool mipmapping;
2285
2286 switch (mMinFilter)
2287 {
2288 case GL_NEAREST:
2289 case GL_LINEAR:
2290 mipmapping = false;
2291 break;
2292 case GL_NEAREST_MIPMAP_NEAREST:
2293 case GL_LINEAR_MIPMAP_NEAREST:
2294 case GL_NEAREST_MIPMAP_LINEAR:
2295 case GL_LINEAR_MIPMAP_LINEAR:
2296 mipmapping = true;
2297 break;
2298 default: UNREACHABLE();
2299 }
2300
2301 for (int face = 0; face < 6; face++)
2302 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002303 if (mImageArray[face][0].getWidth() != size || mImageArray[face][0].getHeight() != size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002304 {
2305 return false;
2306 }
2307 }
2308
daniel@transgaming.combbeffbb2011-11-09 17:46:11 +00002309 if ((getInternalFormat() == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
2310 (getInternalFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002311 {
2312 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
2313 {
2314 return false;
2315 }
2316 }
2317
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002318 bool npot = getContext()->supportsNonPower2Texture();
2319
2320 if (!npot)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002321 {
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002322 if ((getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE) && !isPow2(size))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002323 {
2324 return false;
2325 }
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002326 }
2327
2328 if (mipmapping)
2329 {
2330 if (!npot)
2331 {
2332 if (!isPow2(size))
2333 {
2334 return false;
2335 }
2336 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002337
2338 int q = log2(size);
2339
2340 for (int face = 0; face < 6; face++)
2341 {
2342 for (int level = 1; level <= q; level++)
2343 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002344 if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002345 {
2346 return false;
2347 }
2348
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002349 if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
daniel@transgaming.com0bd22bc2011-03-21 16:38:26 +00002350 {
2351 return false;
2352 }
2353
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002354 if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002355 {
2356 return false;
2357 }
2358
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002359 ASSERT(mImageArray[face][level].getHeight() == mImageArray[face][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002360 }
2361 }
2362 }
2363
2364 return true;
2365}
2366
2367bool TextureCubeMap::isCompressed() const
2368{
2369 return IsCompressed(getInternalFormat());
2370}
2371
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002372IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
2373{
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002374 return mTexture ? mTexture->getBaseTexture() : NULL;
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002375}
2376
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002377// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002378void TextureCubeMap::createTexture()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002379{
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.com0bd22bc2011-03-21 16:38:26 +00002384 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002385 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002386
2387 if (FAILED(result))
2388 {
2389 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002390 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002391 }
2392
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002393 delete mTexture;
2394 mTexture = new TextureStorageCubeMap(texture, false);
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00002395 mSerial = issueSerial();
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002396 for(int face = 0; face < 6; face++) mFaceProxies[face].set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002397 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002398}
2399
2400void TextureCubeMap::updateTexture()
2401{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002402 for (int face = 0; face < 6; face++)
2403 {
2404 int levels = levelCount();
2405 for (int level = 0; level < levels; level++)
2406 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002407 Image *image = &mImageArray[face][level];
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002408
daniel@transgaming.com5cce3ff2011-11-09 17:45:14 +00002409 if (image->isDirty())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002410 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002411 commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002412 }
2413 }
2414 }
2415}
2416
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002417void TextureCubeMap::convertToRenderTarget()
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002418{
2419 IDirect3DCubeTexture9 *texture = NULL;
2420
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002421 if (mImageArray[0][0].getWidth() != 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002422 {
2423 egl::Display *display = getDisplay();
2424 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002425 D3DFORMAT format = mImageArray[0][0].getD3DFormat();
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002426 GLint levels = creationLevels(mImageArray[0][0].getWidth(), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002427
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002428 HRESULT result = device->CreateCubeTexture(mImageArray[0][0].getWidth(), levels, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002429
2430 if (FAILED(result))
2431 {
2432 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002433 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002434 }
2435
2436 if (mTexture != NULL)
2437 {
2438 int levels = levelCount();
2439 for (int f = 0; f < 6; f++)
2440 {
2441 for (int i = 0; i < levels; i++)
2442 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002443 IDirect3DSurface9 *source = mTexture->getCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002444
2445 if (FAILED(result))
2446 {
2447 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2448
2449 texture->Release();
2450
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002451 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002452 }
2453
2454 IDirect3DSurface9 *dest;
2455 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
2456
2457 if (FAILED(result))
2458 {
2459 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2460
2461 texture->Release();
2462 source->Release();
2463
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002464 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002465 }
2466
2467 display->endScene();
2468 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
2469
2470 if (FAILED(result))
2471 {
2472 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2473
2474 texture->Release();
2475 source->Release();
2476 dest->Release();
2477
daniel@transgaming.com68076a02011-03-21 16:38:09 +00002478 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002479 }
daniel@transgaming.coma1a86202011-08-09 13:41:08 +00002480
2481 source->Release();
2482 dest->Release();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002483 }
2484 }
2485 }
2486 }
2487
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002488 delete mTexture;
2489 mTexture = new TextureStorageCubeMap(texture, true);
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00002490 mSerial = issueSerial();
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002491 for(int face = 0; face < 6; face++) mFaceProxies[face].set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002492 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002493}
2494
daniel@transgaming.com61208202011-03-21 16:38:50 +00002495void 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 +00002496{
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002497 redefineImage(faceIndex, level, format, width, height, type);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002498
daniel@transgaming.com61208202011-03-21 16:38:50 +00002499 Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002500}
2501
2502unsigned int TextureCubeMap::faceIndex(GLenum face)
2503{
2504 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2505 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2506 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2507 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2508 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2509
2510 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2511}
2512
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002513void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002514{
daniel@transgaming.com41634052011-11-09 17:46:24 +00002515 bool redefined = mImageArray[face][level].redefine(format, width, height, type);
daniel@transgaming.com94a4f032011-03-21 16:38:55 +00002516
daniel@transgaming.com41634052011-11-09 17:46:24 +00002517 if (mTexture && redefined)
daniel@transgaming.com61208202011-03-21 16:38:50 +00002518 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002519 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2520 {
2521 for (int f = 0; f < 6; f++)
2522 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002523 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002524 }
2525 }
2526
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002527 delete mTexture;
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002528 mTexture = NULL;
daniel@transgaming.comc1fde762011-11-09 17:46:07 +00002529 mSerial = 0;
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002530 for(int face = 0; face < 6; face++) mFaceProxies[face].set(NULL);
daniel@transgaming.com0da803b2011-11-09 17:44:58 +00002531 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002532 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002533}
2534
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00002535void 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 +00002536{
2537 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2538
2539 if (!renderTarget)
2540 {
2541 ERR("Failed to retrieve the render target.");
2542 return error(GL_OUT_OF_MEMORY);
2543 }
2544
2545 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com68ae2992011-11-09 17:44:49 +00002546 redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002547
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002548 if (!mImageArray[faceindex][level].isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002549 {
daniel@transgaming.com90cfcc92011-11-09 17:45:48 +00002550 mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
2551 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002552 }
2553 else
2554 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002555 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002556 {
2557 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002558 }
daniel@transgaming.com3b3c1d42011-06-08 20:38:09 +00002559
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002560 mImageArray[faceindex][level].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002561
2562 ASSERT(width == height);
2563
2564 if (width > 0 && level < levelCount())
2565 {
2566 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2567 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2568 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2569 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2570 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2571
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002572 GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002573
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002574 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2575
daniel@transgaming.comeef864a2011-04-22 11:33:27 +00002576 getBlitter()->copy(source->getRenderTarget(), sourceRect, format, 0, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002577 dest->Release();
2578 }
2579 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002580}
2581
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002582IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(GLenum target, unsigned int level)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002583{
2584 if (mTexture == NULL)
2585 {
2586 UNREACHABLE();
2587 return NULL;
2588 }
2589
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002590 return mTexture->getCubeMapSurface(es2dx::ConvertCubeFace(target), level);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002591}
2592
2593void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
2594{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002595 GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002596
2597 if (xoffset + width > size || yoffset + height > size)
2598 {
2599 return error(GL_INVALID_VALUE);
2600 }
2601
2602 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2603
2604 if (!renderTarget)
2605 {
2606 ERR("Failed to retrieve the render target.");
2607 return error(GL_OUT_OF_MEMORY);
2608 }
2609
2610 unsigned int faceindex = faceIndex(target);
daniel@transgaming.com01dae852011-11-09 17:44:53 +00002611
daniel@transgaming.com549bdef2011-03-29 00:57:01 +00002612 if (!mImageArray[faceindex][level].isRenderable() || (!mTexture && !isComplete()))
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002613 {
daniel@transgaming.com90cfcc92011-11-09 17:45:48 +00002614 mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
2615 mDirtyImages = true;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002616 }
2617 else
2618 {
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002619 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002620 {
2621 convertToRenderTarget();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002622 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002623
2624 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002625
2626 if (level < levelCount())
2627 {
2628 RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
2629 sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
2630 sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
2631 sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
2632 sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
2633
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002634 GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002635
2636 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
2637
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002638 getBlitter()->copy(source->getRenderTarget(), sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002639 dest->Release();
2640 }
2641 }
2642}
2643
2644bool TextureCubeMap::isCubeComplete() const
2645{
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002646 if (mImageArray[0][0].getWidth() == 0)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002647 {
2648 return false;
2649 }
2650
2651 for (unsigned int f = 1; f < 6; f++)
2652 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002653 if (mImageArray[f][0].getWidth() != mImageArray[0][0].getWidth()
2654 || mImageArray[f][0].getFormat() != mImageArray[0][0].getFormat())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002655 {
2656 return false;
2657 }
2658 }
2659
2660 return true;
2661}
2662
2663void TextureCubeMap::generateMipmaps()
2664{
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002665 if (!isCubeComplete())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002666 {
2667 return error(GL_INVALID_OPERATION);
2668 }
2669
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002670 if (!getContext()->supportsNonPower2Texture())
2671 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002672 if (!isPow2(mImageArray[0][0].getWidth()))
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00002673 {
2674 return error(GL_INVALID_OPERATION);
2675 }
2676 }
2677
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002678 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002679 unsigned int q = log2(mImageArray[0][0].getWidth());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002680 for (unsigned int f = 0; f < 6; f++)
2681 {
2682 for (unsigned int i = 1; i <= q; i++)
2683 {
daniel@transgaming.com1a01e832011-11-09 17:45:57 +00002684 redefineImage(f, i, mImageArray[f][0].getFormat(),
2685 std::max(mImageArray[f][0].getWidth() >> i, 1),
2686 std::max(mImageArray[f][0].getWidth() >> i, 1),
2687 mImageArray[f][0].getType());
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002688 }
2689 }
2690
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002691 if (mTexture && mTexture->isRenderable())
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002692 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002693 for (unsigned int f = 0; f < 6; f++)
2694 {
2695 for (unsigned int i = 1; i <= q; i++)
2696 {
2697 IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
2698 IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2699
2700 if (upper != NULL && lower != NULL)
2701 {
2702 getBlitter()->boxFilter(upper, lower);
2703 }
2704
2705 if (upper != NULL) upper->Release();
2706 if (lower != NULL) lower->Release();
daniel@transgaming.com61208202011-03-21 16:38:50 +00002707
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002708 mImageArray[f][i].markClean();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002709 }
2710 }
2711 }
2712 else
2713 {
2714 for (unsigned int f = 0; f < 6; f++)
2715 {
2716 for (unsigned int i = 1; i <= q; i++)
2717 {
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002718 if (mImageArray[f][i].getSurface() == NULL)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002719 {
2720 return error(GL_OUT_OF_MEMORY);
2721 }
2722
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002723 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 +00002724 {
2725 ERR(" failed to load filter %d to %d.", i - 1, i);
2726 }
2727
daniel@transgaming.comdff362f2011-11-09 17:45:08 +00002728 mImageArray[f][i].markDirty();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002729 }
2730 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002731 }
2732}
2733
2734Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
2735{
2736 if (!IsCubemapTextureTarget(target))
2737 {
2738 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2739 }
2740
2741 unsigned int face = faceIndex(target);
2742
2743 if (mFaceProxies[face].get() == NULL)
2744 {
daniel@transgaming.comd14558a2011-11-09 17:46:18 +00002745 mFaceProxies[face].set(new Renderbuffer(id(), new RenderbufferTexture(this, target)));
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002746 }
2747
2748 return mFaceProxies[face].get();
2749}
2750
2751IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2752{
2753 ASSERT(IsCubemapTextureTarget(target));
2754
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002755 if (!mTexture || !mTexture->isRenderable())
daniel@transgaming.com61208202011-03-21 16:38:50 +00002756 {
2757 convertToRenderTarget();
2758 }
2759
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002760 if (mTexture == NULL)
2761 {
2762 return NULL;
2763 }
daniel@transgaming.com61208202011-03-21 16:38:50 +00002764
2765 updateTexture();
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002766
daniel@transgaming.comdc82bf92011-11-11 04:10:08 +00002767 return mTexture->getCubeMapSurface(es2dx::ConvertCubeFace(target), 0);
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002768}
2769
daniel@transgaming.comb612f882011-11-09 17:44:31 +00002770}