blob: 6d07c532ddc854f12734204f2ebef24448c7a1b6 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Texture.cpp: Implements the gl::Texture class and its derived classes
8// Texture2D and TextureCubeMap. Implements GL texture objects and related
9// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
10
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libGLESv2/Texture.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
daniel@transgaming.com16973022010-03-11 19:22:19 +000013#include <algorithm>
14
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000015#include "common/debug.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000016
17#include "libGLESv2/main.h"
18#include "libGLESv2/mathutil.h"
19#include "libGLESv2/utilities.h"
20#include "libGLESv2/Blit.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021
22namespace gl
23{
daniel@transgaming.com842f7a42010-03-21 04:31:03 +000024
25Texture::Image::Image()
daniel@transgaming.com01868132010-08-24 19:21:17 +000026 : width(0), height(0), dirty(false), surface(NULL), format(GL_NONE)
daniel@transgaming.com842f7a42010-03-21 04:31:03 +000027{
28}
29
30Texture::Image::~Image()
31{
32 if (surface) surface->Release();
33}
34
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000035Texture::Texture(GLuint id) : RefCountObject(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036{
37 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
38 mMagFilter = GL_LINEAR;
39 mWrapS = GL_REPEAT;
40 mWrapT = GL_REPEAT;
daniel@transgaming.com29d27002010-03-11 19:41:22 +000041
daniel@transgaming.com31273552010-08-04 13:42:44 +000042 mWidth = 0;
43 mHeight = 0;
44
daniel@transgaming.com00c75962010-03-11 20:36:15 +000045 mDirtyMetaData = true;
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +000046 mDirty = true;
daniel@transgaming.com93a81472010-04-20 18:52:58 +000047 mIsRenderable = false;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +000048 mType = GL_UNSIGNED_BYTE;
daniel@transgaming.com0a311a42010-05-17 09:58:33 +000049 mBaseTexture = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000050}
51
52Texture::~Texture()
53{
54}
55
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000056Blit *Texture::getBlitter()
57{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000058 Context *context = getContext();
59 return context->getBlitter();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +000060}
61
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000062// Returns true on successful filter state update (valid enum parameter)
63bool Texture::setMinFilter(GLenum filter)
64{
65 switch (filter)
66 {
67 case GL_NEAREST:
68 case GL_LINEAR:
69 case GL_NEAREST_MIPMAP_NEAREST:
70 case GL_LINEAR_MIPMAP_NEAREST:
71 case GL_NEAREST_MIPMAP_LINEAR:
72 case GL_LINEAR_MIPMAP_LINEAR:
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +000073 {
74 if (mMinFilter != filter)
75 {
76 mMinFilter = filter;
77 mDirty = true;
78 }
79 return true;
80 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 default:
82 return false;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +000083 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084}
85
86// Returns true on successful filter state update (valid enum parameter)
87bool Texture::setMagFilter(GLenum filter)
88{
89 switch (filter)
90 {
91 case GL_NEAREST:
92 case GL_LINEAR:
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +000093 {
94 if (mMagFilter != filter)
95 {
96 mMagFilter = filter;
97 mDirty = true;
98 }
99 return true;
100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 default:
102 return false;
103 }
104}
105
106// Returns true on successful wrap state update (valid enum parameter)
107bool Texture::setWrapS(GLenum wrap)
108{
109 switch (wrap)
110 {
111 case GL_REPEAT:
112 case GL_CLAMP_TO_EDGE:
113 case GL_MIRRORED_REPEAT:
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +0000114 {
115 if (mWrapS != wrap)
116 {
117 mWrapS = wrap;
118 mDirty = true;
119 }
120 return true;
121 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 default:
123 return false;
124 }
125}
126
127// Returns true on successful wrap state update (valid enum parameter)
128bool Texture::setWrapT(GLenum wrap)
129{
130 switch (wrap)
131 {
132 case GL_REPEAT:
133 case GL_CLAMP_TO_EDGE:
134 case GL_MIRRORED_REPEAT:
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +0000135 {
136 if (mWrapT != wrap)
137 {
138 mWrapT = wrap;
139 mDirty = true;
140 }
141 return true;
142 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143 default:
144 return false;
145 }
146}
147
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000148GLenum Texture::getMinFilter() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149{
150 return mMinFilter;
151}
152
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000153GLenum Texture::getMagFilter() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154{
155 return mMagFilter;
156}
157
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000158GLenum Texture::getWrapS() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159{
160 return mWrapS;
161}
162
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000163GLenum Texture::getWrapT() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164{
165 return mWrapT;
166}
167
daniel@transgaming.com93a81472010-04-20 18:52:58 +0000168GLuint Texture::getWidth() const
169{
170 return mWidth;
171}
172
173GLuint Texture::getHeight() const
174{
175 return mHeight;
176}
177
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000178bool Texture::isFloatingPoint() const
179{
180 return (mType == GL_FLOAT || mType == GL_HALF_FLOAT_OES);
181}
182
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000183bool Texture::isRenderableFormat() const
184{
185 D3DFORMAT format = getD3DFormat();
186
187 switch(format)
188 {
189 case D3DFMT_L8:
190 case D3DFMT_A8L8:
191 case D3DFMT_DXT1:
192 return false;
193 case D3DFMT_A8R8G8B8:
194 case D3DFMT_A16B16G16R16F:
195 case D3DFMT_A32B32G32R32F:
196 return true;
197 default:
198 UNREACHABLE();
199 }
200
201 return false;
202}
203
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204// Selects an internal Direct3D 9 format for storing an Image
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000205D3DFORMAT Texture::selectFormat(GLenum format, GLenum type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206{
daniel@transgaming.com01868132010-08-24 19:21:17 +0000207 if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
208 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
209 {
210 return D3DFMT_DXT1;
211 }
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000212 else if (type == GL_FLOAT)
213 {
214 return D3DFMT_A32B32G32R32F;
215 }
216 else if (type == GL_HALF_FLOAT_OES)
217 {
218 return D3DFMT_A16B16G16R16F;
219 }
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000220 else if (type == GL_UNSIGNED_BYTE)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000221 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000222 if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
223 {
224 return D3DFMT_L8;
225 }
226 else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
227 {
228 return D3DFMT_A8L8;
229 }
230
daniel@transgaming.com01868132010-08-24 19:21:17 +0000231 return D3DFMT_A8R8G8B8;
232 }
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000233
234 return D3DFMT_A8R8G8B8;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235}
236
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000237// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000238// into the target pixel rectangle at output with outputPitch bytes in between each line.
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000239void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000240 GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000241{
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000242 GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000243
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000244 switch (type)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000245 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000246 case GL_UNSIGNED_BYTE:
247 switch (format)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000248 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000249 case GL_ALPHA:
250 loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
251 break;
252 case GL_LUMINANCE:
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000253 loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_L8);
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000254 break;
255 case GL_LUMINANCE_ALPHA:
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000256 loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000257 break;
258 case GL_RGB:
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000259 loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
260 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000261 case GL_RGBA:
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000262 loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
263 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000264 case GL_BGRA_EXT:
265 loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000266 break;
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000267 default: UNREACHABLE();
268 }
269 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000270 case GL_UNSIGNED_SHORT_5_6_5:
271 switch (format)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000272 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000273 case GL_RGB:
274 loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000275 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000276 default: UNREACHABLE();
277 }
278 break;
279 case GL_UNSIGNED_SHORT_4_4_4_4:
280 switch (format)
281 {
282 case GL_RGBA:
283 loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
284 break;
285 default: UNREACHABLE();
286 }
287 break;
288 case GL_UNSIGNED_SHORT_5_5_5_1:
289 switch (format)
290 {
291 case GL_RGBA:
292 loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
293 break;
294 default: UNREACHABLE();
295 }
296 break;
297 case GL_FLOAT:
298 switch (format)
299 {
300 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
301 case GL_ALPHA:
302 loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
303 break;
304 case GL_LUMINANCE:
305 loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
306 break;
307 case GL_LUMINANCE_ALPHA:
308 loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
309 break;
310 case GL_RGB:
311 loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
312 break;
313 case GL_RGBA:
314 loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
315 break;
316 default: UNREACHABLE();
317 }
318 break;
319 case GL_HALF_FLOAT_OES:
320 switch (format)
321 {
322 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
323 case GL_ALPHA:
324 loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
325 break;
326 case GL_LUMINANCE:
327 loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
328 break;
329 case GL_LUMINANCE_ALPHA:
330 loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
331 break;
332 case GL_RGB:
333 loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
334 break;
335 case GL_RGBA:
336 loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
337 break;
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000338 default: UNREACHABLE();
339 }
340 break;
341 default: UNREACHABLE();
342 }
343}
344
345void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
346 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
347{
348 const unsigned char *source = NULL;
349 unsigned char *dest = NULL;
350
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000351 for (int y = 0; y < height; y++)
352 {
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000353 source = static_cast<const unsigned char*>(input) + y * inputPitch;
354 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000355 for (int x = 0; x < width; x++)
356 {
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000357 dest[4 * x + 0] = 0;
358 dest[4 * x + 1] = 0;
359 dest[4 * x + 2] = 0;
360 dest[4 * x + 3] = source[x];
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000361 }
362 }
363}
364
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000365void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
366 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
367{
368 const float *source = NULL;
369 float *dest = NULL;
370
371 for (int y = 0; y < height; y++)
372 {
373 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
374 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
375 for (int x = 0; x < width; x++)
376 {
377 dest[4 * x + 0] = 0;
378 dest[4 * x + 1] = 0;
379 dest[4 * x + 2] = 0;
380 dest[4 * x + 3] = source[x];
381 }
382 }
383}
384
385void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
386 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
387{
388 const unsigned short *source = NULL;
389 unsigned short *dest = NULL;
390
391 for (int y = 0; y < height; y++)
392 {
393 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
394 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
395 for (int x = 0; x < width; x++)
396 {
397 dest[4 * x + 0] = 0;
398 dest[4 * x + 1] = 0;
399 dest[4 * x + 2] = 0;
400 dest[4 * x + 3] = source[x];
401 }
402 }
403}
404
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000405void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000406 size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000407{
408 const unsigned char *source = NULL;
409 unsigned char *dest = NULL;
410
411 for (int y = 0; y < height; y++)
412 {
413 source = static_cast<const unsigned char*>(input) + y * inputPitch;
414 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000415
416 if (!native) // BGRA8 destination format
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000417 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000418 for (int x = 0; x < width; x++)
419 {
420 dest[4 * x + 0] = source[x];
421 dest[4 * x + 1] = source[x];
422 dest[4 * x + 2] = source[x];
423 dest[4 * x + 3] = 0xFF;
424 }
425 }
426 else // L8 destination format
427 {
428 memcpy(dest, source, width);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000429 }
430 }
431}
432
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000433void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
434 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
435{
436 const float *source = NULL;
437 float *dest = NULL;
438
439 for (int y = 0; y < height; y++)
440 {
441 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
442 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
443 for (int x = 0; x < width; x++)
444 {
445 dest[4 * x + 0] = source[x];
446 dest[4 * x + 1] = source[x];
447 dest[4 * x + 2] = source[x];
448 dest[4 * x + 3] = 1.0f;
449 }
450 }
451}
452
453void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
454 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
455{
456 const unsigned short *source = NULL;
457 unsigned short *dest = NULL;
458
459 for (int y = 0; y < height; y++)
460 {
461 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
462 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
463 for (int x = 0; x < width; x++)
464 {
465 dest[4 * x + 0] = source[x];
466 dest[4 * x + 1] = source[x];
467 dest[4 * x + 2] = source[x];
468 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
469 }
470 }
471}
472
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000473void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000474 size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000475{
476 const unsigned char *source = NULL;
477 unsigned char *dest = NULL;
478
479 for (int y = 0; y < height; y++)
480 {
481 source = static_cast<const unsigned char*>(input) + y * inputPitch;
482 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000483
484 if (!native) // BGRA8 destination format
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000485 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000486 for (int x = 0; x < width; x++)
487 {
488 dest[4 * x + 0] = source[2*x+0];
489 dest[4 * x + 1] = source[2*x+0];
490 dest[4 * x + 2] = source[2*x+0];
491 dest[4 * x + 3] = source[2*x+1];
492 }
493 }
494 else
495 {
496 memcpy(dest, source, width * 2);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000497 }
498 }
499}
500
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000501void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
502 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
503{
504 const float *source = NULL;
505 float *dest = NULL;
506
507 for (int y = 0; y < height; y++)
508 {
509 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
510 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
511 for (int x = 0; x < width; x++)
512 {
513 dest[4 * x + 0] = source[2*x+0];
514 dest[4 * x + 1] = source[2*x+0];
515 dest[4 * x + 2] = source[2*x+0];
516 dest[4 * x + 3] = source[2*x+1];
517 }
518 }
519}
520
521void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
522 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
523{
524 const unsigned short *source = NULL;
525 unsigned short *dest = NULL;
526
527 for (int y = 0; y < height; y++)
528 {
529 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
530 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
531 for (int x = 0; x < width; x++)
532 {
533 dest[4 * x + 0] = source[2*x+0];
534 dest[4 * x + 1] = source[2*x+0];
535 dest[4 * x + 2] = source[2*x+0];
536 dest[4 * x + 3] = source[2*x+1];
537 }
538 }
539}
540
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000541void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
542 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
543{
544 const unsigned char *source = NULL;
545 unsigned char *dest = NULL;
546
547 for (int y = 0; y < height; y++)
548 {
549 source = static_cast<const unsigned char*>(input) + y * inputPitch;
550 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
551 for (int x = 0; x < width; x++)
552 {
553 dest[4 * x + 0] = source[x * 3 + 2];
554 dest[4 * x + 1] = source[x * 3 + 1];
555 dest[4 * x + 2] = source[x * 3 + 0];
556 dest[4 * x + 3] = 0xFF;
557 }
558 }
559}
560
561void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
562 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
563{
564 const unsigned short *source = NULL;
565 unsigned char *dest = NULL;
566
567 for (int y = 0; y < height; y++)
568 {
569 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
570 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
571 for (int x = 0; x < width; x++)
572 {
573 unsigned short rgba = source[x];
574 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
575 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
576 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
577 dest[4 * x + 3] = 0xFF;
578 }
579 }
580}
581
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000582void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
583 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
584{
585 const float *source = NULL;
586 float *dest = NULL;
587
588 for (int y = 0; y < height; y++)
589 {
590 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
591 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
592 for (int x = 0; x < width; x++)
593 {
594 dest[4 * x + 0] = source[x * 3 + 0];
595 dest[4 * x + 1] = source[x * 3 + 1];
596 dest[4 * x + 2] = source[x * 3 + 2];
597 dest[4 * x + 3] = 1.0f;
598 }
599 }
600}
601
602void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
603 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
604{
605 const unsigned short *source = NULL;
606 unsigned short *dest = NULL;
607
608 for (int y = 0; y < height; y++)
609 {
610 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
611 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
612 for (int x = 0; x < width; x++)
613 {
614 dest[4 * x + 0] = source[x * 3 + 0];
615 dest[4 * x + 1] = source[x * 3 + 1];
616 dest[4 * x + 2] = source[x * 3 + 2];
617 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
618 }
619 }
620}
621
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000622void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
623 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
624{
625 const unsigned char *source = NULL;
626 unsigned char *dest = NULL;
627
628 for (int y = 0; y < height; y++)
629 {
630 source = static_cast<const unsigned char*>(input) + y * inputPitch;
631 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
632 for (int x = 0; x < width; x++)
633 {
634 dest[4 * x + 0] = source[x * 4 + 2];
635 dest[4 * x + 1] = source[x * 4 + 1];
636 dest[4 * x + 2] = source[x * 4 + 0];
637 dest[4 * x + 3] = source[x * 4 + 3];
638 }
639 }
640}
641
642void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
643 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
644{
645 const unsigned short *source = NULL;
646 unsigned char *dest = NULL;
647
648 for (int y = 0; y < height; y++)
649 {
650 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
651 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
652 for (int x = 0; x < width; x++)
653 {
654 unsigned short rgba = source[x];
655 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
656 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
657 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
658 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
659 }
660 }
661}
662
663void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
664 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
665{
666 const unsigned short *source = NULL;
667 unsigned char *dest = NULL;
668
669 for (int y = 0; y < height; y++)
670 {
671 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
672 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
673 for (int x = 0; x < width; x++)
674 {
675 unsigned short rgba = source[x];
676 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
677 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
678 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
679 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
680 }
681 }
682}
683
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000684void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
685 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
686{
687 const float *source = NULL;
688 float *dest = NULL;
689
690 for (int y = 0; y < height; y++)
691 {
692 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
693 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
694 memcpy(dest, source, width * 16);
695 }
696}
697
698void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
699 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
700{
701 const unsigned char *source = NULL;
702 unsigned char *dest = NULL;
703
704 for (int y = 0; y < height; y++)
705 {
706 source = static_cast<const unsigned char*>(input) + y * inputPitch;
707 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8;
708 memcpy(dest, source, width * 8);
709 }
710}
711
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000712void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
713 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
714{
715 const unsigned char *source = NULL;
716 unsigned char *dest = NULL;
717
718 for (int y = 0; y < height; y++)
719 {
720 source = static_cast<const unsigned char*>(input) + y * inputPitch;
721 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
722 memcpy(dest, source, width*4);
723 }
724}
725
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000726void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000727{
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000728 IDirect3DTexture9 *newTexture = NULL;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000729 IDirect3DSurface9 *newSurface = NULL;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000730
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +0000731 if (width != 0 && height != 0)
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000732 {
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000733 int levelToFetch = 0;
734 GLsizei requestWidth = width;
735 GLsizei requestHeight = height;
736 if (IsCompressed(format) && (width % 4 != 0 || height % 4 != 0))
737 {
738 bool isMult4 = false;
739 int upsampleCount = 0;
740 while (!isMult4)
741 {
742 requestWidth <<= 1;
743 requestHeight <<= 1;
744 upsampleCount++;
745 if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
746 {
747 isMult4 = true;
748 }
749 }
750 levelToFetch = upsampleCount;
751 }
752
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000753 HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format, type),
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000754 D3DPOOL_SYSTEMMEM, &newTexture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +0000755
756 if (FAILED(result))
757 {
758 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
759 return error(GL_OUT_OF_MEMORY);
760 }
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000761
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000762 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000763 newTexture->Release();
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000764 }
765
766 if (img->surface) img->surface->Release();
767 img->surface = newSurface;
768
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000769 img->width = width;
770 img->height = height;
771 img->format = format;
daniel@transgaming.com01868132010-08-24 19:21:17 +0000772}
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000773
daniel@transgaming.com01868132010-08-24 19:21:17 +0000774void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
775{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000776 createSurface(width, height, format, type, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000777
778 if (pixels != NULL && img->surface != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000779 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000780 D3DSURFACE_DESC description;
781 img->surface->GetDesc(&description);
782
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000783 D3DLOCKED_RECT locked;
daniel@transgaming.com01868132010-08-24 19:21:17 +0000784 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000785
786 ASSERT(SUCCEEDED(result));
787
788 if (SUCCEEDED(result))
789 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000790 loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000791 img->surface->UnlockRect();
792 }
793
794 img->dirty = true;
795 }
796
797 mDirtyMetaData = true;
798}
799
800void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
801{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000802 createSurface(width, height, format, GL_UNSIGNED_BYTE, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000803
804 if (pixels != NULL && img->surface != NULL)
805 {
806 D3DLOCKED_RECT locked;
807 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
808
809 ASSERT(SUCCEEDED(result));
810
811 if (SUCCEEDED(result))
812 {
813 memcpy(locked.pBits, pixels, imageSize);
814 img->surface->UnlockRect();
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000815 }
816
817 img->dirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818 }
819
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000820 mDirtyMetaData = true;
821}
822
daniel@transgaming.com31273552010-08-04 13:42:44 +0000823bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000824{
daniel@transgaming.com31273552010-08-04 13:42:44 +0000825 if (width + xoffset > img->width || height + yoffset > img->height)
826 {
827 error(GL_INVALID_VALUE);
828 return false;
829 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000830
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000831 if (!img->surface)
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000832 {
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000833 createSurface(img->width, img->height, format, type, img);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000834 }
835
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000836 if (pixels != NULL && img->surface != NULL)
837 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000838 D3DSURFACE_DESC description;
839 img->surface->GetDesc(&description);
840
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000841 D3DLOCKED_RECT locked;
842 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
843
844 ASSERT(SUCCEEDED(result));
845
846 if (SUCCEEDED(result))
847 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000848 loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000849 img->surface->UnlockRect();
850 }
851
852 img->dirty = true;
853 }
854
daniel@transgaming.com31273552010-08-04 13:42:44 +0000855 return true;
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000856}
857
daniel@transgaming.com01868132010-08-24 19:21:17 +0000858bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
859{
860 if (width + xoffset > img->width || height + yoffset > img->height)
861 {
862 error(GL_INVALID_VALUE);
863 return false;
864 }
865
866 if (format != getFormat())
867 {
868 error(GL_INVALID_OPERATION);
869 return false;
870 }
871
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000872 if (!img->surface)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000873 {
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000874 createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000875 }
876
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000877 if (pixels != NULL && img->surface != NULL)
878 {
879 RECT updateRegion;
880 updateRegion.left = xoffset;
881 updateRegion.right = xoffset + width;
882 updateRegion.bottom = yoffset + height;
883 updateRegion.top = yoffset;
884
885 D3DLOCKED_RECT locked;
886 HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
887
888 ASSERT(SUCCEEDED(result));
889
890 if (SUCCEEDED(result))
891 {
892 GLsizei inputPitch = ComputeCompressedPitch(width, format);
893 int rows = imageSize / inputPitch;
894 for (int i = 0; i < rows; ++i)
895 {
896 memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
897 }
898 img->surface->UnlockRect();
899 }
900
901 img->dirty = true;
902 }
903
daniel@transgaming.com01868132010-08-24 19:21:17 +0000904 return true;
905}
906
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000907// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats
908void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
909{
910 IDirect3DDevice9 *device = getDevice();
911 IDirect3DSurface9 *surface = NULL;
912 D3DSURFACE_DESC description;
913 renderTarget->GetDesc(&description);
914
915 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
916
917 if (!SUCCEEDED(result))
918 {
919 ERR("Could not create matching destination surface.");
920 return error(GL_OUT_OF_MEMORY);
921 }
922
923 result = device->GetRenderTargetData(renderTarget, surface);
924
925 if (!SUCCEEDED(result))
926 {
927 ERR("GetRenderTargetData unexpectedly failed.");
928 surface->Release();
929 return error(GL_OUT_OF_MEMORY);
930 }
931
932 D3DLOCKED_RECT sourceLock = {0};
933 RECT sourceRect = {x, y, x + width, y + height};
934 result = surface->LockRect(&sourceLock, &sourceRect, 0);
935
936 if (FAILED(result))
937 {
938 ERR("Failed to lock the source surface (rectangle might be invalid).");
939 surface->UnlockRect();
940 surface->Release();
941 return error(GL_OUT_OF_MEMORY);
942 }
943
944 if (!image->surface)
945 {
946 createSurface(width, height, internalFormat, mType, image);
947 }
948
949 if (image->surface == NULL)
950 {
951 ERR("Failed to create an image surface.");
952 surface->UnlockRect();
953 surface->Release();
954 return error(GL_OUT_OF_MEMORY);
955 }
956
957 D3DLOCKED_RECT destLock = {0};
958 RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
959 result = image->surface->LockRect(&destLock, &destRect, 0);
960
961 if (FAILED(result))
962 {
963 ERR("Failed to lock the destination surface (rectangle might be invalid).");
964 surface->UnlockRect();
965 surface->Release();
966 return error(GL_OUT_OF_MEMORY);
967 }
968
969 if (destLock.pBits && sourceLock.pBits)
970 {
971 unsigned char *source = (unsigned char*)sourceLock.pBits;
972 unsigned char *dest = (unsigned char*)destLock.pBits;
973
974 switch (description.Format)
975 {
976 case D3DFMT_X8R8G8B8:
977 case D3DFMT_A8R8G8B8:
978 switch(getD3DFormat())
979 {
980 case D3DFMT_L8:
981 for(int y = 0; y < height; y++)
982 {
983 for(int x = 0; x < height; x++)
984 {
985 dest[x] = source[x * 4 + 2];
986 }
987
988 source += sourceLock.Pitch;
989 dest += destLock.Pitch;
990 }
991 break;
992 case D3DFMT_A8L8:
993 for(int y = 0; y < height; y++)
994 {
995 for(int x = 0; x < height; x++)
996 {
997 dest[x * 2 + 0] = source[x * 4 + 2];
998 dest[x * 2 + 1] = source[x * 4 + 3];
999 }
1000
1001 source += sourceLock.Pitch;
1002 dest += destLock.Pitch;
1003 }
1004 break;
1005 default:
1006 UNREACHABLE();
1007 }
1008 break;
1009 default:
1010 UNREACHABLE();
1011 }
1012
1013 image->dirty = true;
1014 mDirtyMetaData = true;
1015 }
1016
1017 image->surface->UnlockRect();
1018 surface->UnlockRect();
1019 surface->Release();
1020}
1021
enne@chromium.org0fa74632010-09-21 16:18:52 +00001022D3DFORMAT Texture::getD3DFormat() const
1023{
1024 return selectFormat(getFormat(), mType);
1025}
1026
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001027IDirect3DBaseTexture9 *Texture::getTexture()
1028{
1029 if (!isComplete())
1030 {
1031 return NULL;
1032 }
1033
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001034 if (mDirtyMetaData)
1035 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001036 mBaseTexture = createTexture();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001037 mIsRenderable = false;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001038 }
1039
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001040 if (mDirtyMetaData || dirtyImageData())
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001041 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001042 updateTexture();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001043 }
1044
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001045 mDirtyMetaData = false;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001046 ASSERT(!dirtyImageData());
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001047
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001048 return mBaseTexture;
1049}
1050
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001051bool Texture::isDirty() const
1052{
1053 return (mDirty || mDirtyMetaData || dirtyImageData());
1054}
1055
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001056// Returns the top-level texture surface as a render target
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001057void Texture::needRenderTarget()
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001058{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001059 if (!mIsRenderable)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001060 {
1061 mBaseTexture = convertToRenderTarget();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001062 mIsRenderable = true;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001063 }
1064
1065 if (dirtyImageData())
1066 {
1067 updateTexture();
1068 }
1069
1070 mDirtyMetaData = false;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001071}
1072
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001073void Texture::dropTexture()
1074{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001075 if (mBaseTexture)
1076 {
1077 mBaseTexture = NULL;
1078 }
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001079
1080 mIsRenderable = false;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001081}
1082
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001083void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001084{
1085 mBaseTexture = newTexture;
1086 mDirtyMetaData = false;
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001087 mIsRenderable = renderable;
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001088 mDirty = true;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001089}
1090
1091
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001092GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
1093{
1094 if (isPow2(width) && isPow2(height))
1095 {
1096 return maxlevel;
1097 }
1098 else
1099 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001100 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1101 return 1;
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001102 }
1103}
1104
1105GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
1106{
1107 return creationLevels(size, size, maxlevel);
1108}
1109
1110int Texture::levelCount() const
1111{
1112 return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
1113}
1114
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001115Texture2D::Texture2D(GLuint id) : Texture(id)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001116{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001117 mTexture = NULL;
1118}
1119
1120Texture2D::~Texture2D()
1121{
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001122 mColorbufferProxy.set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001123
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001124 if (mTexture)
1125 {
1126 mTexture->Release();
1127 mTexture = NULL;
1128 }
1129}
1130
1131GLenum Texture2D::getTarget() const
1132{
1133 return GL_TEXTURE_2D;
1134}
1135
daniel@transgaming.com01868132010-08-24 19:21:17 +00001136GLenum Texture2D::getFormat() const
1137{
1138 return mImageArray[0].format;
1139}
1140
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001141// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
1142// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
1143// Call this when a particular level of the texture must be defined with a specific format, width and height.
1144//
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +00001145// Returns true if the existing texture was unsuitable and had to be destroyed. If so, it will also set
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001146// a new height and width for the texture by working backwards from the given width and height.
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001147bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001148{
1149 bool widthOkay = (mWidth >> level == width);
1150 bool heightOkay = (mHeight >> level == height);
1151
1152 bool sizeOkay = ((widthOkay && heightOkay)
1153 || (widthOkay && mHeight >> level == 0 && height == 1)
1154 || (heightOkay && mWidth >> level == 0 && width == 1));
1155
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001156 bool typeOkay = (type == mType);
1157
1158 bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001159
1160 if (!textureOkay)
1161 {
1162 TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
1163 mImageArray[0].format, mWidth, mHeight,
1164 internalFormat, width, height);
1165
1166 // Purge all the levels and the texture.
1167
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001168 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001169 {
1170 if (mImageArray[i].surface != NULL)
1171 {
1172 mImageArray[i].dirty = false;
1173
1174 mImageArray[i].surface->Release();
1175 mImageArray[i].surface = NULL;
1176 }
1177 }
1178
1179 if (mTexture != NULL)
1180 {
1181 mTexture->Release();
1182 mTexture = NULL;
1183 dropTexture();
1184 }
1185
1186 mWidth = width << level;
1187 mHeight = height << level;
1188 mImageArray[0].format = internalFormat;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001189 mType = type;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001190 }
1191
1192 return !textureOkay;
1193}
1194
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001195void Texture2D::setImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001196{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001197 redefineTexture(level, internalFormat, width, height, type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001198
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001199 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001200}
1201
daniel@transgaming.com01868132010-08-24 19:21:17 +00001202void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1203{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001204 redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001205
1206 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
1207}
1208
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001209void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1210{
1211 ASSERT(mImageArray[level].surface != NULL);
1212
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001213 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001214 {
1215 IDirect3DSurface9 *destLevel = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001216 HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001217
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001218 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001219
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001220 if (SUCCEEDED(result))
1221 {
1222 Image *img = &mImageArray[level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001223
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001224 RECT sourceRect;
1225 sourceRect.left = xoffset;
1226 sourceRect.top = yoffset;
1227 sourceRect.right = xoffset + width;
1228 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001229
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001230 POINT destPoint;
1231 destPoint.x = xoffset;
1232 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001233
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001234 result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
1235 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001236
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001237 destLevel->Release();
1238
1239 img->dirty = false;
1240 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001241 }
1242}
1243
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001244void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001245{
daniel@transgaming.com31273552010-08-04 13:42:44 +00001246 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1247 {
1248 commitRect(level, xoffset, yoffset, width, height);
1249 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001250}
1251
daniel@transgaming.com01868132010-08-24 19:21:17 +00001252void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1253{
1254 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1255 {
1256 commitRect(level, xoffset, yoffset, width, height);
1257 }
1258}
1259
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001260void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001261{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001262 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1263
1264 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001265 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001266 ERR("Failed to retrieve the render target.");
1267 return error(GL_OUT_OF_MEMORY);
1268 }
1269
1270 bool redefined = redefineTexture(level, internalFormat, width, height, mType);
1271
1272 if (!isRenderableFormat())
1273 {
1274 needRenderTarget();
1275 copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001276 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001277 else
1278 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001279 if (redefined)
1280 {
1281 convertToRenderTarget();
1282 pushTexture(mTexture, true);
1283 }
1284 else
1285 {
1286 needRenderTarget();
1287 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001288
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001289 if (width != 0 && height != 0 && level < levelCount())
1290 {
1291 RECT sourceRect;
1292 sourceRect.left = x;
1293 sourceRect.right = x + width;
1294 sourceRect.top = y;
1295 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001296
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001297 IDirect3DSurface9 *dest;
1298 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001299
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001300 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
1301 dest->Release();
1302 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001303 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001304
1305 mImageArray[level].width = width;
1306 mImageArray[level].height = height;
1307 mImageArray[level].format = internalFormat;
1308}
1309
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001310void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001311{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001312 if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
1313 {
1314 return error(GL_INVALID_VALUE);
1315 }
1316
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001317 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1318
1319 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001320 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001321 ERR("Failed to retrieve the render target.");
1322 return error(GL_OUT_OF_MEMORY);
1323 }
1324
1325 bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
1326
1327 if (!isRenderableFormat())
1328 {
1329 copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001330 }
1331 else
1332 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001333 if (redefined)
1334 {
1335 convertToRenderTarget();
1336 pushTexture(mTexture, true);
1337 }
1338 else
1339 {
1340 needRenderTarget();
1341 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001342
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001343 if (level < levelCount())
1344 {
1345 RECT sourceRect;
1346 sourceRect.left = x;
1347 sourceRect.right = x + width;
1348 sourceRect.top = y;
1349 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001350
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001351 IDirect3DSurface9 *dest;
1352 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001353
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001354 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
1355 dest->Release();
1356 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001357 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001358}
1359
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001360// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1361bool Texture2D::isComplete() const
1362{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001363 GLsizei width = mImageArray[0].width;
1364 GLsizei height = mImageArray[0].height;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001365
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001366 if (width <= 0 || height <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001367 {
1368 return false;
1369 }
1370
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001371 bool mipmapping = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001372
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001373 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001374 {
1375 case GL_NEAREST:
1376 case GL_LINEAR:
1377 mipmapping = false;
1378 break;
1379 case GL_NEAREST_MIPMAP_NEAREST:
1380 case GL_LINEAR_MIPMAP_NEAREST:
1381 case GL_NEAREST_MIPMAP_LINEAR:
1382 case GL_LINEAR_MIPMAP_LINEAR:
1383 mipmapping = true;
1384 break;
1385 default: UNREACHABLE();
1386 }
1387
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001388 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1389 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1390 {
1391 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1392 {
1393 return false;
1394 }
1395 }
1396
1397
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001398 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
1399 || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1400 {
1401 return false;
1402 }
1403
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001404 if (mipmapping)
1405 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001406 if (!isPow2(width) || !isPow2(height))
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001407 {
1408 return false;
1409 }
1410
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001411 int q = log2(std::max(width, height));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001412
1413 for (int level = 1; level <= q; level++)
1414 {
1415 if (mImageArray[level].format != mImageArray[0].format)
1416 {
1417 return false;
1418 }
1419
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001420 if (mImageArray[level].width != std::max(1, width >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001421 {
1422 return false;
1423 }
1424
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001425 if (mImageArray[level].height != std::max(1, height >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001426 {
1427 return false;
1428 }
1429 }
1430 }
1431
1432 return true;
1433}
1434
daniel@transgaming.com01868132010-08-24 19:21:17 +00001435bool Texture2D::isCompressed() const
1436{
1437 return IsCompressed(getFormat());
1438}
1439
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001440// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001441IDirect3DBaseTexture9 *Texture2D::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001442{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001443 IDirect3DTexture9 *texture;
1444
1445 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001446 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001447
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001448 HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001449
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001450 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001451 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001452 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001453 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001454 }
1455
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001456 if (mTexture) mTexture->Release();
1457 mTexture = texture;
1458 return texture;
1459}
1460
1461void Texture2D::updateTexture()
1462{
1463 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001464
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001465 int levels = levelCount();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001466
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001467 for (int level = 0; level < levels; level++)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001468 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001469 if (mImageArray[level].dirty)
1470 {
1471 IDirect3DSurface9 *levelSurface = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001472 HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001473
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001474 ASSERT(SUCCEEDED(result));
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001475
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001476 if (SUCCEEDED(result))
1477 {
1478 result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
1479 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001480
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001481 levelSurface->Release();
1482
1483 mImageArray[level].dirty = false;
1484 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001485 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001486 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001487}
1488
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001489IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001490{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001491 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001492
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001493 if (mWidth != 0 && mHeight != 0)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001494 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001495 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001496 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001497 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001498
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001499 HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001500
1501 if (FAILED(result))
1502 {
1503 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1504 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1505 }
1506
1507 if (mTexture != NULL)
1508 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001509 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001510 for (int i = 0; i < levels; i++)
1511 {
1512 IDirect3DSurface9 *source;
1513 result = mTexture->GetSurfaceLevel(i, &source);
1514
1515 if (FAILED(result))
1516 {
1517 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1518
1519 texture->Release();
1520
1521 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1522 }
1523
1524 IDirect3DSurface9 *dest;
1525 result = texture->GetSurfaceLevel(i, &dest);
1526
1527 if (FAILED(result))
1528 {
1529 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1530
1531 texture->Release();
1532 source->Release();
1533
1534 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1535 }
1536
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001537 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001538 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1539
1540 if (FAILED(result))
1541 {
1542 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1543
1544 texture->Release();
1545 source->Release();
1546 dest->Release();
1547
1548 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1549 }
1550
1551 source->Release();
1552 dest->Release();
1553 }
1554 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001555 }
1556
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001557 if (mTexture != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001558 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001559 mTexture->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001560 }
1561
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001562 mTexture = texture;
1563 return mTexture;
1564}
1565
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001566bool Texture2D::dirtyImageData() const
1567{
1568 int q = log2(std::max(mWidth, mHeight));
1569
1570 for (int i = 0; i <= q; i++)
1571 {
1572 if (mImageArray[i].dirty) return true;
1573 }
1574
1575 return false;
1576}
1577
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001578void Texture2D::generateMipmaps()
1579{
1580 if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
1581 {
1582 return error(GL_INVALID_OPERATION);
1583 }
1584
1585 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1586 unsigned int q = log2(std::max(mWidth, mHeight));
1587 for (unsigned int i = 1; i <= q; i++)
1588 {
1589 if (mImageArray[i].surface != NULL)
1590 {
1591 mImageArray[i].surface->Release();
1592 mImageArray[i].surface = NULL;
1593 }
1594
1595 mImageArray[i].dirty = false;
1596
1597 mImageArray[i].format = mImageArray[0].format;
1598 mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
1599 mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
1600 }
1601
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001602 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001603
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00001604 if (mTexture == NULL)
1605 {
1606 return;
1607 }
1608
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001609 for (unsigned int i = 1; i <= q; i++)
1610 {
1611 IDirect3DSurface9 *upper = NULL;
1612 IDirect3DSurface9 *lower = NULL;
1613
1614 mTexture->GetSurfaceLevel(i-1, &upper);
1615 mTexture->GetSurfaceLevel(i, &lower);
1616
1617 if (upper != NULL && lower != NULL)
1618 {
1619 getBlitter()->boxFilter(upper, lower);
1620 }
1621
1622 if (upper != NULL) upper->Release();
1623 if (lower != NULL) lower->Release();
1624 }
1625}
1626
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001627Renderbuffer *Texture2D::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001628{
1629 if (target != GL_TEXTURE_2D)
1630 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001631 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001632 }
1633
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001634 if (mColorbufferProxy.get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001635 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001636 mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001637 }
1638
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001639 return mColorbufferProxy.get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001640}
1641
1642IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
1643{
1644 ASSERT(target == GL_TEXTURE_2D);
1645
1646 needRenderTarget();
1647
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00001648 if (mTexture == NULL)
1649 {
1650 return NULL;
1651 }
1652
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001653 IDirect3DSurface9 *renderTarget = NULL;
1654 mTexture->GetSurfaceLevel(0, &renderTarget);
1655
1656 return renderTarget;
1657}
1658
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001659TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001660{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001661 mTexture = NULL;
1662}
1663
1664TextureCubeMap::~TextureCubeMap()
1665{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001666 for (int i = 0; i < 6; i++)
1667 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001668 mFaceProxies[i].set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001669 }
1670
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001671 if (mTexture)
1672 {
1673 mTexture->Release();
1674 mTexture = NULL;
1675 }
1676}
1677
1678GLenum TextureCubeMap::getTarget() const
1679{
1680 return GL_TEXTURE_CUBE_MAP;
1681}
1682
daniel@transgaming.com01868132010-08-24 19:21:17 +00001683GLenum TextureCubeMap::getFormat() const
1684{
1685 return mImageArray[0][0].format;
1686}
1687
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001688void TextureCubeMap::setImagePosX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001689{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001690 setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001691}
1692
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001693void TextureCubeMap::setImageNegX(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001694{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001695 setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001696}
1697
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001698void TextureCubeMap::setImagePosY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001699{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001700 setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001701}
1702
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001703void TextureCubeMap::setImageNegY(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001705 setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001706}
1707
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001708void TextureCubeMap::setImagePosZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001709{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001710 setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001711}
1712
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001713void TextureCubeMap::setImageNegZ(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001714{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001715 setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001716}
1717
daniel@transgaming.com01868132010-08-24 19:21:17 +00001718void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1719{
1720 redefineTexture(level, internalFormat, width);
1721
1722 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
1723}
1724
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001725void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1726{
1727 int face = faceIndex(faceTarget);
1728
1729 ASSERT(mImageArray[face][level].surface != NULL);
1730
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001731 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001732 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001733 IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
1734 ASSERT(destLevel != NULL);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001735
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001736 if (destLevel != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001737 {
1738 Image *img = &mImageArray[face][level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001739
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001740 RECT sourceRect;
1741 sourceRect.left = xoffset;
1742 sourceRect.top = yoffset;
1743 sourceRect.right = xoffset + width;
1744 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001745
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001746 POINT destPoint;
1747 destPoint.x = xoffset;
1748 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001749
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001750 HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001751 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001752
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001753 destLevel->Release();
1754
1755 img->dirty = false;
1756 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001757 }
1758}
1759
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001760void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001761{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001762 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com31273552010-08-04 13:42:44 +00001763 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001764 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com31273552010-08-04 13:42:44 +00001765 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001766}
1767
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001768void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
daniel@transgaming.com01868132010-08-24 19:21:17 +00001769{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001770 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com01868132010-08-24 19:21:17 +00001771 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001772 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001773 }
1774}
1775
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001776// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001777bool TextureCubeMap::isComplete() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001779 int size = mImageArray[0][0].width;
1780
1781 if (size <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001782 {
1783 return false;
1784 }
1785
1786 bool mipmapping;
1787
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001788 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001789 {
1790 case GL_NEAREST:
1791 case GL_LINEAR:
1792 mipmapping = false;
1793 break;
1794 case GL_NEAREST_MIPMAP_NEAREST:
1795 case GL_LINEAR_MIPMAP_NEAREST:
1796 case GL_NEAREST_MIPMAP_LINEAR:
1797 case GL_LINEAR_MIPMAP_LINEAR:
1798 mipmapping = true;
1799 break;
1800 default: UNREACHABLE();
1801 }
1802
1803 for (int face = 0; face < 6; face++)
1804 {
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001805 if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001806 {
1807 return false;
1808 }
1809 }
1810
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001811 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1812 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1813 {
1814 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1815 {
1816 return false;
1817 }
1818 }
1819
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001820 if (mipmapping)
1821 {
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001822 if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
1823 {
1824 return false;
1825 }
1826
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001827 int q = log2(size);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001828
1829 for (int face = 0; face < 6; face++)
1830 {
1831 for (int level = 1; level <= q; level++)
1832 {
1833 if (mImageArray[face][level].format != mImageArray[0][0].format)
1834 {
1835 return false;
1836 }
1837
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001838 if (mImageArray[face][level].width != std::max(1, size >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001839 {
1840 return false;
1841 }
1842
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001843 ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001844 }
1845 }
1846 }
1847
1848 return true;
1849}
1850
daniel@transgaming.com01868132010-08-24 19:21:17 +00001851bool TextureCubeMap::isCompressed() const
1852{
1853 return IsCompressed(getFormat());
1854}
1855
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001856// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001857IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001858{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001859 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001860 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001861
1862 IDirect3DCubeTexture9 *texture;
1863
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001864 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001865
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001866 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001867 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001868 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001869 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001870 }
1871
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001872 if (mTexture) mTexture->Release();
1873
1874 mTexture = texture;
1875 return mTexture;
1876}
1877
1878void TextureCubeMap::updateTexture()
1879{
1880 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001881
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001882 for (int face = 0; face < 6; face++)
1883 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001884 int levels = levelCount();
1885 for (int level = 0; level < levels; level++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001886 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001887 Image *img = &mImageArray[face][level];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001888
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001889 if (img->dirty)
1890 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001891 IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
1892 ASSERT(levelSurface != NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001893
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001894 if (levelSurface != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001895 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001896 HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001897 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001898
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001899 levelSurface->Release();
1900
1901 img->dirty = false;
1902 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001903 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001904 }
1905 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001906}
1907
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001908IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
1909{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001910 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001911
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001912 if (mWidth != 0)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001913 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001914 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001915 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001916 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001917
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001918 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001919
1920 if (FAILED(result))
1921 {
1922 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1923 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1924 }
1925
1926 if (mTexture != NULL)
1927 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001928 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001929 for (int f = 0; f < 6; f++)
1930 {
1931 for (int i = 0; i < levels; i++)
1932 {
1933 IDirect3DSurface9 *source;
1934 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
1935
1936 if (FAILED(result))
1937 {
1938 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1939
1940 texture->Release();
1941
1942 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1943 }
1944
1945 IDirect3DSurface9 *dest;
1946 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
1947
1948 if (FAILED(result))
1949 {
1950 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1951
1952 texture->Release();
1953 source->Release();
1954
1955 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1956 }
1957
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001958 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001959 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1960
1961 if (FAILED(result))
1962 {
1963 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1964
1965 texture->Release();
1966 source->Release();
1967 dest->Release();
1968
1969 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1970 }
1971 }
1972 }
1973 }
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001974 }
1975
1976 if (mTexture != NULL)
1977 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001978 mTexture->Release();
1979 }
1980
1981 mTexture = texture;
1982 return mTexture;
1983}
1984
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001985void TextureCubeMap::setImage(int face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001986{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001987 redefineTexture(level, internalFormat, width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001988
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001989 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001990}
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001991
1992unsigned int TextureCubeMap::faceIndex(GLenum face)
1993{
1994 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
1995 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
1996 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
1997 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
1998 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
1999
2000 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2001}
2002
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00002003bool TextureCubeMap::dirtyImageData() const
2004{
2005 int q = log2(mWidth);
2006
2007 for (int f = 0; f < 6; f++)
2008 {
2009 for (int i = 0; i <= q; i++)
2010 {
2011 if (mImageArray[f][i].dirty) return true;
2012 }
2013 }
2014
2015 return false;
2016}
2017
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002018// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
2019// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
2020// Call this when a particular level of the texture must be defined with a specific format, width and height.
2021//
2022// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
2023// a new size for the texture by working backwards from the given size.
2024bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
2025{
2026 // Are these settings compatible with level 0?
2027 bool sizeOkay = (mImageArray[0][0].width >> level == width);
2028
2029 bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
2030
2031 if (!textureOkay)
2032 {
2033 TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
2034 mImageArray[0][0].format, mImageArray[0][0].width,
2035 internalFormat, width);
2036
2037 // Purge all the levels and the texture.
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00002038 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002039 {
2040 for (int f = 0; f < 6; f++)
2041 {
2042 if (mImageArray[f][i].surface != NULL)
2043 {
2044 mImageArray[f][i].dirty = false;
2045
2046 mImageArray[f][i].surface->Release();
2047 mImageArray[f][i].surface = NULL;
2048 }
2049 }
2050 }
2051
2052 if (mTexture != NULL)
2053 {
2054 mTexture->Release();
2055 mTexture = NULL;
2056 dropTexture();
2057 }
2058
2059 mWidth = width << level;
2060 mImageArray[0][0].width = width << level;
2061 mHeight = width << level;
2062 mImageArray[0][0].height = width << level;
2063
2064 mImageArray[0][0].format = internalFormat;
2065 }
2066
2067 return !textureOkay;
2068}
2069
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002070void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002071{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002072 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002073
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002074 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002075 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002076 ERR("Failed to retrieve the render target.");
2077 return error(GL_OUT_OF_MEMORY);
2078 }
2079
2080 unsigned int faceindex = faceIndex(target);
2081 bool redefined = redefineTexture(level, internalFormat, width);
2082
2083 if (!isRenderableFormat())
2084 {
2085 copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002086 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00002087 else
2088 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002089 if (redefined)
2090 {
2091 convertToRenderTarget();
2092 pushTexture(mTexture, true);
2093 }
2094 else
2095 {
2096 needRenderTarget();
2097 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002098
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002099 ASSERT(width == height);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002100
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002101 if (width > 0 && level < levelCount())
2102 {
2103 RECT sourceRect;
2104 sourceRect.left = x;
2105 sourceRect.right = x + width;
2106 sourceRect.top = y;
2107 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002108
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002109 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002110
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002111 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
2112 dest->Release();
2113 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002114 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002115
2116 mImageArray[faceindex][level].width = width;
2117 mImageArray[faceindex][level].height = height;
2118 mImageArray[faceindex][level].format = internalFormat;
2119}
2120
2121IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
2122{
2123 unsigned int faceIndex;
2124
2125 if (faceIdentifier < 6)
2126 {
2127 faceIndex = faceIdentifier;
2128 }
2129 else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2130 {
2131 faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2132 }
2133 else
2134 {
2135 UNREACHABLE();
2136 faceIndex = 0;
2137 }
2138
2139 if (mTexture == NULL)
2140 {
2141 UNREACHABLE();
2142 return NULL;
2143 }
2144
2145 IDirect3DSurface9 *surface = NULL;
2146
2147 HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
2148
2149 return (SUCCEEDED(hr)) ? surface : NULL;
2150}
2151
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002152void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002153{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002154 GLsizei size = mImageArray[faceIndex(target)][level].width;
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002155
2156 if (xoffset + width > size || yoffset + height > size)
2157 {
2158 return error(GL_INVALID_VALUE);
2159 }
2160
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002161 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2162
2163 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002164 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002165 ERR("Failed to retrieve the render target.");
2166 return error(GL_OUT_OF_MEMORY);
2167 }
2168
2169 unsigned int faceindex = faceIndex(target);
2170 bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
2171
2172 if (!isRenderableFormat())
2173 {
2174 copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002175 }
2176 else
2177 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002178 if (redefined)
2179 {
2180 convertToRenderTarget();
2181 pushTexture(mTexture, true);
2182 }
2183 else
2184 {
2185 needRenderTarget();
2186 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002187
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002188 if (level < levelCount())
2189 {
2190 RECT sourceRect;
2191 sourceRect.left = x;
2192 sourceRect.right = x + width;
2193 sourceRect.top = y;
2194 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002195
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002196 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002197
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002198 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
2199 dest->Release();
2200 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00002201 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002202}
2203
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002204bool TextureCubeMap::isCubeComplete() const
2205{
2206 if (mImageArray[0][0].width == 0)
2207 {
2208 return false;
2209 }
2210
2211 for (unsigned int f = 1; f < 6; f++)
2212 {
2213 if (mImageArray[f][0].width != mImageArray[0][0].width
2214 || mImageArray[f][0].format != mImageArray[0][0].format)
2215 {
2216 return false;
2217 }
2218 }
2219
2220 return true;
2221}
2222
2223void TextureCubeMap::generateMipmaps()
2224{
2225 if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
2226 {
2227 return error(GL_INVALID_OPERATION);
2228 }
2229
2230 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2231 unsigned int q = log2(mImageArray[0][0].width);
2232 for (unsigned int f = 0; f < 6; f++)
2233 {
2234 for (unsigned int i = 1; i <= q; i++)
2235 {
2236 if (mImageArray[f][i].surface != NULL)
2237 {
2238 mImageArray[f][i].surface->Release();
2239 mImageArray[f][i].surface = NULL;
2240 }
2241
2242 mImageArray[f][i].dirty = false;
2243
2244 mImageArray[f][i].format = mImageArray[f][0].format;
2245 mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
2246 mImageArray[f][i].height = mImageArray[f][i].width;
2247 }
2248 }
2249
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002250 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002251
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00002252 if (mTexture == NULL)
2253 {
2254 return;
2255 }
2256
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002257 for (unsigned int f = 0; f < 6; f++)
2258 {
2259 for (unsigned int i = 1; i <= q; i++)
2260 {
2261 IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
2262 IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
2263
2264 if (upper != NULL && lower != NULL)
2265 {
2266 getBlitter()->boxFilter(upper, lower);
2267 }
2268
2269 if (upper != NULL) upper->Release();
2270 if (lower != NULL) lower->Release();
2271 }
2272 }
2273}
2274
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002275Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002276{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002277 if (!IsCubemapTextureTarget(target))
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002278 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002279 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002280 }
2281
2282 unsigned int face = faceIndex(target);
2283
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002284 if (mFaceProxies[face].get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002285 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002286 mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002287 }
2288
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002289 return mFaceProxies[face].get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002290}
2291
2292IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2293{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002294 ASSERT(IsCubemapTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002295
2296 needRenderTarget();
daniel@transgaming.come979ead2010-09-23 18:03:14 +00002297
2298 if (mTexture == NULL)
2299 {
2300 return NULL;
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00002301 }
2302
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002303 IDirect3DSurface9 *renderTarget = NULL;
2304 mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
2305
2306 return renderTarget;
2307}
2308
2309Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
enne@chromium.org0fa74632010-09-21 16:18:52 +00002310 : Colorbuffer(texture), mTexture(texture), mTarget(target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002311{
daniel@transgaming.comedc19182010-10-15 17:57:55 +00002312 ASSERT(IsTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002313}
2314
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002315void Texture::TextureColorbufferProxy::addRef() const
2316{
2317 mTexture->addRef();
2318}
2319
2320void Texture::TextureColorbufferProxy::release() const
2321{
2322 mTexture->release();
2323}
2324
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002325IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
2326{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002327 if (mRenderTarget) mRenderTarget->Release();
2328
2329 mRenderTarget = mTexture->getRenderTarget(mTarget);
2330
2331 return mRenderTarget;
2332}
2333
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002334int Texture::TextureColorbufferProxy::getWidth() const
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002335{
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002336 return mTexture->getWidth();
2337}
2338
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002339int Texture::TextureColorbufferProxy::getHeight() const
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002340{
2341 return mTexture->getHeight();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002342}
2343
daniel@transgaming.com01868132010-08-24 19:21:17 +00002344GLenum Texture::TextureColorbufferProxy::getFormat() const
2345{
2346 return mTexture->getFormat();
2347}
2348
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002349bool Texture::TextureColorbufferProxy::isFloatingPoint() const
2350{
2351 return mTexture->isFloatingPoint();
2352}
2353
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002354}