blob: 904b7aca8bcc807412b9d679e110c1333990417c [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 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001274 copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001275 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001276 else
1277 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001278 if (redefined)
1279 {
1280 convertToRenderTarget();
1281 pushTexture(mTexture, true);
1282 }
1283 else
1284 {
1285 needRenderTarget();
1286 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001287
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001288 if (width != 0 && height != 0 && level < levelCount())
1289 {
1290 RECT sourceRect;
1291 sourceRect.left = x;
1292 sourceRect.right = x + width;
1293 sourceRect.top = y;
1294 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001295
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001296 IDirect3DSurface9 *dest;
1297 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001298
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001299 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
1300 dest->Release();
1301 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001302 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001303
1304 mImageArray[level].width = width;
1305 mImageArray[level].height = height;
1306 mImageArray[level].format = internalFormat;
1307}
1308
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001309void 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 +00001310{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001311 if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
1312 {
1313 return error(GL_INVALID_VALUE);
1314 }
1315
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001316 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1317
1318 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001319 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001320 ERR("Failed to retrieve the render target.");
1321 return error(GL_OUT_OF_MEMORY);
1322 }
1323
1324 bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
1325
1326 if (!isRenderableFormat())
1327 {
1328 copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001329 }
1330 else
1331 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001332 if (redefined)
1333 {
1334 convertToRenderTarget();
1335 pushTexture(mTexture, true);
1336 }
1337 else
1338 {
1339 needRenderTarget();
1340 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001341
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001342 if (level < levelCount())
1343 {
1344 RECT sourceRect;
1345 sourceRect.left = x;
1346 sourceRect.right = x + width;
1347 sourceRect.top = y;
1348 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001349
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001350 IDirect3DSurface9 *dest;
1351 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001352
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001353 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
1354 dest->Release();
1355 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001356 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001357}
1358
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001359// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1360bool Texture2D::isComplete() const
1361{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001362 GLsizei width = mImageArray[0].width;
1363 GLsizei height = mImageArray[0].height;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001364
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001365 if (width <= 0 || height <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001366 {
1367 return false;
1368 }
1369
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001370 bool mipmapping = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001371
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001372 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001373 {
1374 case GL_NEAREST:
1375 case GL_LINEAR:
1376 mipmapping = false;
1377 break;
1378 case GL_NEAREST_MIPMAP_NEAREST:
1379 case GL_LINEAR_MIPMAP_NEAREST:
1380 case GL_NEAREST_MIPMAP_LINEAR:
1381 case GL_LINEAR_MIPMAP_LINEAR:
1382 mipmapping = true;
1383 break;
1384 default: UNREACHABLE();
1385 }
1386
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001387 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1388 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1389 {
1390 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1391 {
1392 return false;
1393 }
1394 }
1395
1396
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001397 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
1398 || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1399 {
1400 return false;
1401 }
1402
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001403 if (mipmapping)
1404 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001405 if (!isPow2(width) || !isPow2(height))
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001406 {
1407 return false;
1408 }
1409
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001410 int q = log2(std::max(width, height));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001411
1412 for (int level = 1; level <= q; level++)
1413 {
1414 if (mImageArray[level].format != mImageArray[0].format)
1415 {
1416 return false;
1417 }
1418
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001419 if (mImageArray[level].width != std::max(1, width >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001420 {
1421 return false;
1422 }
1423
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001424 if (mImageArray[level].height != std::max(1, height >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001425 {
1426 return false;
1427 }
1428 }
1429 }
1430
1431 return true;
1432}
1433
daniel@transgaming.com01868132010-08-24 19:21:17 +00001434bool Texture2D::isCompressed() const
1435{
1436 return IsCompressed(getFormat());
1437}
1438
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001439// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001440IDirect3DBaseTexture9 *Texture2D::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001441{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001442 IDirect3DTexture9 *texture;
1443
1444 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001445 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001446
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001447 HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001448
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001449 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001450 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001451 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001452 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001453 }
1454
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001455 if (mTexture) mTexture->Release();
1456 mTexture = texture;
1457 return texture;
1458}
1459
1460void Texture2D::updateTexture()
1461{
1462 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001463
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001464 int levels = levelCount();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001465
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001466 for (int level = 0; level < levels; level++)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001467 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001468 if (mImageArray[level].dirty)
1469 {
1470 IDirect3DSurface9 *levelSurface = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001471 HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001472
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001473 ASSERT(SUCCEEDED(result));
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001474
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001475 if (SUCCEEDED(result))
1476 {
1477 result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
1478 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001479
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001480 levelSurface->Release();
1481
1482 mImageArray[level].dirty = false;
1483 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001484 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001485 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001486}
1487
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001488IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001489{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001490 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001491
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001492 if (mWidth != 0 && mHeight != 0)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001493 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001494 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001495 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001496 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001497
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001498 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 +00001499
1500 if (FAILED(result))
1501 {
1502 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1503 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1504 }
1505
1506 if (mTexture != NULL)
1507 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001508 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001509 for (int i = 0; i < levels; i++)
1510 {
1511 IDirect3DSurface9 *source;
1512 result = mTexture->GetSurfaceLevel(i, &source);
1513
1514 if (FAILED(result))
1515 {
1516 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1517
1518 texture->Release();
1519
1520 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1521 }
1522
1523 IDirect3DSurface9 *dest;
1524 result = texture->GetSurfaceLevel(i, &dest);
1525
1526 if (FAILED(result))
1527 {
1528 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1529
1530 texture->Release();
1531 source->Release();
1532
1533 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1534 }
1535
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001536 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001537 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1538
1539 if (FAILED(result))
1540 {
1541 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1542
1543 texture->Release();
1544 source->Release();
1545 dest->Release();
1546
1547 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1548 }
1549
1550 source->Release();
1551 dest->Release();
1552 }
1553 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001554 }
1555
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001556 if (mTexture != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001557 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001558 mTexture->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001559 }
1560
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001561 mTexture = texture;
1562 return mTexture;
1563}
1564
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001565bool Texture2D::dirtyImageData() const
1566{
1567 int q = log2(std::max(mWidth, mHeight));
1568
1569 for (int i = 0; i <= q; i++)
1570 {
1571 if (mImageArray[i].dirty) return true;
1572 }
1573
1574 return false;
1575}
1576
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001577void Texture2D::generateMipmaps()
1578{
1579 if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
1580 {
1581 return error(GL_INVALID_OPERATION);
1582 }
1583
1584 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1585 unsigned int q = log2(std::max(mWidth, mHeight));
1586 for (unsigned int i = 1; i <= q; i++)
1587 {
1588 if (mImageArray[i].surface != NULL)
1589 {
1590 mImageArray[i].surface->Release();
1591 mImageArray[i].surface = NULL;
1592 }
1593
1594 mImageArray[i].dirty = false;
1595
1596 mImageArray[i].format = mImageArray[0].format;
1597 mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
1598 mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
1599 }
1600
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001601 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001602
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00001603 if (mTexture == NULL)
1604 {
1605 return;
1606 }
1607
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001608 for (unsigned int i = 1; i <= q; i++)
1609 {
1610 IDirect3DSurface9 *upper = NULL;
1611 IDirect3DSurface9 *lower = NULL;
1612
1613 mTexture->GetSurfaceLevel(i-1, &upper);
1614 mTexture->GetSurfaceLevel(i, &lower);
1615
1616 if (upper != NULL && lower != NULL)
1617 {
1618 getBlitter()->boxFilter(upper, lower);
1619 }
1620
1621 if (upper != NULL) upper->Release();
1622 if (lower != NULL) lower->Release();
1623 }
1624}
1625
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001626Renderbuffer *Texture2D::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001627{
1628 if (target != GL_TEXTURE_2D)
1629 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001630 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001631 }
1632
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001633 if (mColorbufferProxy.get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001634 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001635 mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001636 }
1637
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001638 return mColorbufferProxy.get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001639}
1640
1641IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
1642{
1643 ASSERT(target == GL_TEXTURE_2D);
1644
1645 needRenderTarget();
1646
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00001647 if (mTexture == NULL)
1648 {
1649 return NULL;
1650 }
1651
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001652 IDirect3DSurface9 *renderTarget = NULL;
1653 mTexture->GetSurfaceLevel(0, &renderTarget);
1654
1655 return renderTarget;
1656}
1657
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001658TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001659{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001660 mTexture = NULL;
1661}
1662
1663TextureCubeMap::~TextureCubeMap()
1664{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001665 for (int i = 0; i < 6; i++)
1666 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001667 mFaceProxies[i].set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001668 }
1669
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001670 if (mTexture)
1671 {
1672 mTexture->Release();
1673 mTexture = NULL;
1674 }
1675}
1676
1677GLenum TextureCubeMap::getTarget() const
1678{
1679 return GL_TEXTURE_CUBE_MAP;
1680}
1681
daniel@transgaming.com01868132010-08-24 19:21:17 +00001682GLenum TextureCubeMap::getFormat() const
1683{
1684 return mImageArray[0][0].format;
1685}
1686
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001687void 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 +00001688{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001689 setImage(0, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690}
1691
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001692void 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 +00001693{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001694 setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001695}
1696
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001697void 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 +00001698{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001699 setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700}
1701
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001702void 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 +00001703{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001704 setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001705}
1706
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001707void 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 +00001708{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001709 setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001710}
1711
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001712void 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 +00001713{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001714 setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001715}
1716
daniel@transgaming.com01868132010-08-24 19:21:17 +00001717void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1718{
1719 redefineTexture(level, internalFormat, width);
1720
1721 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
1722}
1723
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001724void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1725{
1726 int face = faceIndex(faceTarget);
1727
1728 ASSERT(mImageArray[face][level].surface != NULL);
1729
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001730 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001731 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001732 IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
1733 ASSERT(destLevel != NULL);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001734
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001735 if (destLevel != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001736 {
1737 Image *img = &mImageArray[face][level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001738
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001739 RECT sourceRect;
1740 sourceRect.left = xoffset;
1741 sourceRect.top = yoffset;
1742 sourceRect.right = xoffset + width;
1743 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001744
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001745 POINT destPoint;
1746 destPoint.x = xoffset;
1747 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001748
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001749 HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001750 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001751
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001752 destLevel->Release();
1753
1754 img->dirty = false;
1755 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001756 }
1757}
1758
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001759void 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 +00001760{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001761 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com31273552010-08-04 13:42:44 +00001762 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001763 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com31273552010-08-04 13:42:44 +00001764 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001765}
1766
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001767void 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 +00001768{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001769 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com01868132010-08-24 19:21:17 +00001770 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001771 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001772 }
1773}
1774
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775// 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 +00001776bool TextureCubeMap::isComplete() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001777{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001778 int size = mImageArray[0][0].width;
1779
1780 if (size <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001781 {
1782 return false;
1783 }
1784
1785 bool mipmapping;
1786
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001787 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001788 {
1789 case GL_NEAREST:
1790 case GL_LINEAR:
1791 mipmapping = false;
1792 break;
1793 case GL_NEAREST_MIPMAP_NEAREST:
1794 case GL_LINEAR_MIPMAP_NEAREST:
1795 case GL_NEAREST_MIPMAP_LINEAR:
1796 case GL_LINEAR_MIPMAP_LINEAR:
1797 mipmapping = true;
1798 break;
1799 default: UNREACHABLE();
1800 }
1801
1802 for (int face = 0; face < 6; face++)
1803 {
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001804 if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001805 {
1806 return false;
1807 }
1808 }
1809
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001810 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1811 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1812 {
1813 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1814 {
1815 return false;
1816 }
1817 }
1818
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001819 if (mipmapping)
1820 {
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001821 if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
1822 {
1823 return false;
1824 }
1825
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001826 int q = log2(size);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001827
1828 for (int face = 0; face < 6; face++)
1829 {
1830 for (int level = 1; level <= q; level++)
1831 {
1832 if (mImageArray[face][level].format != mImageArray[0][0].format)
1833 {
1834 return false;
1835 }
1836
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001837 if (mImageArray[face][level].width != std::max(1, size >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001838 {
1839 return false;
1840 }
1841
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001842 ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001843 }
1844 }
1845 }
1846
1847 return true;
1848}
1849
daniel@transgaming.com01868132010-08-24 19:21:17 +00001850bool TextureCubeMap::isCompressed() const
1851{
1852 return IsCompressed(getFormat());
1853}
1854
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001855// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001856IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001857{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001858 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001859 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001860
1861 IDirect3DCubeTexture9 *texture;
1862
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001863 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001864
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001865 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001866 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001867 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001868 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001869 }
1870
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001871 if (mTexture) mTexture->Release();
1872
1873 mTexture = texture;
1874 return mTexture;
1875}
1876
1877void TextureCubeMap::updateTexture()
1878{
1879 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001880
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001881 for (int face = 0; face < 6; face++)
1882 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001883 int levels = levelCount();
1884 for (int level = 0; level < levels; level++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001885 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001886 Image *img = &mImageArray[face][level];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001887
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001888 if (img->dirty)
1889 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001890 IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
1891 ASSERT(levelSurface != NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001892
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001893 if (levelSurface != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001894 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001895 HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001896 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001897
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001898 levelSurface->Release();
1899
1900 img->dirty = false;
1901 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001902 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001903 }
1904 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905}
1906
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001907IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
1908{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001909 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001910
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001911 if (mWidth != 0)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001912 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001913 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001914 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001915 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001916
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001917 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001918
1919 if (FAILED(result))
1920 {
1921 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1922 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1923 }
1924
1925 if (mTexture != NULL)
1926 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001927 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001928 for (int f = 0; f < 6; f++)
1929 {
1930 for (int i = 0; i < levels; i++)
1931 {
1932 IDirect3DSurface9 *source;
1933 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
1934
1935 if (FAILED(result))
1936 {
1937 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1938
1939 texture->Release();
1940
1941 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1942 }
1943
1944 IDirect3DSurface9 *dest;
1945 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
1946
1947 if (FAILED(result))
1948 {
1949 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1950
1951 texture->Release();
1952 source->Release();
1953
1954 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1955 }
1956
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001957 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001958 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1959
1960 if (FAILED(result))
1961 {
1962 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1963
1964 texture->Release();
1965 source->Release();
1966 dest->Release();
1967
1968 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1969 }
1970 }
1971 }
1972 }
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001973 }
1974
1975 if (mTexture != NULL)
1976 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001977 mTexture->Release();
1978 }
1979
1980 mTexture = texture;
1981 return mTexture;
1982}
1983
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001984void 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 +00001985{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001986 redefineTexture(level, internalFormat, width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001987
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001988 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001989}
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001990
1991unsigned int TextureCubeMap::faceIndex(GLenum face)
1992{
1993 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
1994 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
1995 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
1996 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
1997 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
1998
1999 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2000}
2001
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00002002bool TextureCubeMap::dirtyImageData() const
2003{
2004 int q = log2(mWidth);
2005
2006 for (int f = 0; f < 6; f++)
2007 {
2008 for (int i = 0; i <= q; i++)
2009 {
2010 if (mImageArray[f][i].dirty) return true;
2011 }
2012 }
2013
2014 return false;
2015}
2016
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002017// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
2018// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
2019// Call this when a particular level of the texture must be defined with a specific format, width and height.
2020//
2021// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
2022// a new size for the texture by working backwards from the given size.
2023bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
2024{
2025 // Are these settings compatible with level 0?
2026 bool sizeOkay = (mImageArray[0][0].width >> level == width);
2027
2028 bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
2029
2030 if (!textureOkay)
2031 {
2032 TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
2033 mImageArray[0][0].format, mImageArray[0][0].width,
2034 internalFormat, width);
2035
2036 // Purge all the levels and the texture.
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00002037 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002038 {
2039 for (int f = 0; f < 6; f++)
2040 {
2041 if (mImageArray[f][i].surface != NULL)
2042 {
2043 mImageArray[f][i].dirty = false;
2044
2045 mImageArray[f][i].surface->Release();
2046 mImageArray[f][i].surface = NULL;
2047 }
2048 }
2049 }
2050
2051 if (mTexture != NULL)
2052 {
2053 mTexture->Release();
2054 mTexture = NULL;
2055 dropTexture();
2056 }
2057
2058 mWidth = width << level;
2059 mImageArray[0][0].width = width << level;
2060 mHeight = width << level;
2061 mImageArray[0][0].height = width << level;
2062
2063 mImageArray[0][0].format = internalFormat;
2064 }
2065
2066 return !textureOkay;
2067}
2068
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002069void 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 +00002070{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002071 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002072
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002073 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002074 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002075 ERR("Failed to retrieve the render target.");
2076 return error(GL_OUT_OF_MEMORY);
2077 }
2078
2079 unsigned int faceindex = faceIndex(target);
2080 bool redefined = redefineTexture(level, internalFormat, width);
2081
2082 if (!isRenderableFormat())
2083 {
2084 copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002085 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00002086 else
2087 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002088 if (redefined)
2089 {
2090 convertToRenderTarget();
2091 pushTexture(mTexture, true);
2092 }
2093 else
2094 {
2095 needRenderTarget();
2096 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002097
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002098 ASSERT(width == height);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002099
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002100 if (width > 0 && level < levelCount())
2101 {
2102 RECT sourceRect;
2103 sourceRect.left = x;
2104 sourceRect.right = x + width;
2105 sourceRect.top = y;
2106 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002107
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002108 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002109
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002110 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
2111 dest->Release();
2112 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002113 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002114
2115 mImageArray[faceindex][level].width = width;
2116 mImageArray[faceindex][level].height = height;
2117 mImageArray[faceindex][level].format = internalFormat;
2118}
2119
2120IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
2121{
2122 unsigned int faceIndex;
2123
2124 if (faceIdentifier < 6)
2125 {
2126 faceIndex = faceIdentifier;
2127 }
2128 else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2129 {
2130 faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2131 }
2132 else
2133 {
2134 UNREACHABLE();
2135 faceIndex = 0;
2136 }
2137
2138 if (mTexture == NULL)
2139 {
2140 UNREACHABLE();
2141 return NULL;
2142 }
2143
2144 IDirect3DSurface9 *surface = NULL;
2145
2146 HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
2147
2148 return (SUCCEEDED(hr)) ? surface : NULL;
2149}
2150
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002151void 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 +00002152{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002153 GLsizei size = mImageArray[faceIndex(target)][level].width;
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002154
2155 if (xoffset + width > size || yoffset + height > size)
2156 {
2157 return error(GL_INVALID_VALUE);
2158 }
2159
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002160 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2161
2162 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002163 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002164 ERR("Failed to retrieve the render target.");
2165 return error(GL_OUT_OF_MEMORY);
2166 }
2167
2168 unsigned int faceindex = faceIndex(target);
2169 bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
2170
2171 if (!isRenderableFormat())
2172 {
2173 copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002174 }
2175 else
2176 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002177 if (redefined)
2178 {
2179 convertToRenderTarget();
2180 pushTexture(mTexture, true);
2181 }
2182 else
2183 {
2184 needRenderTarget();
2185 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002186
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002187 if (level < levelCount())
2188 {
2189 RECT sourceRect;
2190 sourceRect.left = x;
2191 sourceRect.right = x + width;
2192 sourceRect.top = y;
2193 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002194
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002195 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002196
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002197 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
2198 dest->Release();
2199 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00002200 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002201}
2202
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002203bool TextureCubeMap::isCubeComplete() const
2204{
2205 if (mImageArray[0][0].width == 0)
2206 {
2207 return false;
2208 }
2209
2210 for (unsigned int f = 1; f < 6; f++)
2211 {
2212 if (mImageArray[f][0].width != mImageArray[0][0].width
2213 || mImageArray[f][0].format != mImageArray[0][0].format)
2214 {
2215 return false;
2216 }
2217 }
2218
2219 return true;
2220}
2221
2222void TextureCubeMap::generateMipmaps()
2223{
2224 if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
2225 {
2226 return error(GL_INVALID_OPERATION);
2227 }
2228
2229 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2230 unsigned int q = log2(mImageArray[0][0].width);
2231 for (unsigned int f = 0; f < 6; f++)
2232 {
2233 for (unsigned int i = 1; i <= q; i++)
2234 {
2235 if (mImageArray[f][i].surface != NULL)
2236 {
2237 mImageArray[f][i].surface->Release();
2238 mImageArray[f][i].surface = NULL;
2239 }
2240
2241 mImageArray[f][i].dirty = false;
2242
2243 mImageArray[f][i].format = mImageArray[f][0].format;
2244 mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
2245 mImageArray[f][i].height = mImageArray[f][i].width;
2246 }
2247 }
2248
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002249 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002250
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00002251 if (mTexture == NULL)
2252 {
2253 return;
2254 }
2255
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002256 for (unsigned int f = 0; f < 6; f++)
2257 {
2258 for (unsigned int i = 1; i <= q; i++)
2259 {
2260 IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
2261 IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
2262
2263 if (upper != NULL && lower != NULL)
2264 {
2265 getBlitter()->boxFilter(upper, lower);
2266 }
2267
2268 if (upper != NULL) upper->Release();
2269 if (lower != NULL) lower->Release();
2270 }
2271 }
2272}
2273
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002274Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002275{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002276 if (!IsCubemapTextureTarget(target))
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002277 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002278 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002279 }
2280
2281 unsigned int face = faceIndex(target);
2282
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002283 if (mFaceProxies[face].get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002284 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002285 mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002286 }
2287
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002288 return mFaceProxies[face].get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002289}
2290
2291IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2292{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002293 ASSERT(IsCubemapTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002294
2295 needRenderTarget();
daniel@transgaming.come979ead2010-09-23 18:03:14 +00002296
2297 if (mTexture == NULL)
2298 {
2299 return NULL;
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00002300 }
2301
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002302 IDirect3DSurface9 *renderTarget = NULL;
2303 mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
2304
2305 return renderTarget;
2306}
2307
2308Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
enne@chromium.org0fa74632010-09-21 16:18:52 +00002309 : Colorbuffer(texture), mTexture(texture), mTarget(target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002310{
daniel@transgaming.comedc19182010-10-15 17:57:55 +00002311 ASSERT(IsTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002312}
2313
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002314void Texture::TextureColorbufferProxy::addRef() const
2315{
2316 mTexture->addRef();
2317}
2318
2319void Texture::TextureColorbufferProxy::release() const
2320{
2321 mTexture->release();
2322}
2323
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002324IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
2325{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002326 if (mRenderTarget) mRenderTarget->Release();
2327
2328 mRenderTarget = mTexture->getRenderTarget(mTarget);
2329
2330 return mRenderTarget;
2331}
2332
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002333int Texture::TextureColorbufferProxy::getWidth() const
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002334{
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002335 return mTexture->getWidth();
2336}
2337
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002338int Texture::TextureColorbufferProxy::getHeight() const
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002339{
2340 return mTexture->getHeight();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002341}
2342
daniel@transgaming.com01868132010-08-24 19:21:17 +00002343GLenum Texture::TextureColorbufferProxy::getFormat() const
2344{
2345 return mTexture->getFormat();
2346}
2347
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002348bool Texture::TextureColorbufferProxy::isFloatingPoint() const
2349{
2350 return mTexture->isFloatingPoint();
2351}
2352
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002353}