blob: abf236048e01c9af361ad14e360faa0d3c56a6e7 [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;
daniel@transgaming.comfe5141e2010-10-18 12:18:12 +00001009 case D3DFMT_R5G6B5:
1010 switch(getD3DFormat())
1011 {
1012 case D3DFMT_L8:
1013 for(int y = 0; y < height; y++)
1014 {
1015 for(int x = 0; x < height; x++)
1016 {
1017 unsigned char red = source[x * 2 + 1] & 0xF8;
1018 dest[x] = red | (red >> 5);
1019 }
1020
1021 source += sourceLock.Pitch;
1022 dest += destLock.Pitch;
1023 }
1024 break;
1025 default:
1026 UNREACHABLE();
1027 }
1028 break;
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001029 default:
1030 UNREACHABLE();
1031 }
1032
1033 image->dirty = true;
1034 mDirtyMetaData = true;
1035 }
1036
1037 image->surface->UnlockRect();
1038 surface->UnlockRect();
1039 surface->Release();
1040}
1041
enne@chromium.org0fa74632010-09-21 16:18:52 +00001042D3DFORMAT Texture::getD3DFormat() const
1043{
1044 return selectFormat(getFormat(), mType);
1045}
1046
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001047IDirect3DBaseTexture9 *Texture::getTexture()
1048{
1049 if (!isComplete())
1050 {
1051 return NULL;
1052 }
1053
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001054 if (mDirtyMetaData)
1055 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001056 mBaseTexture = createTexture();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001057 mIsRenderable = false;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001058 }
1059
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001060 if (mDirtyMetaData || dirtyImageData())
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001061 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001062 updateTexture();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001063 }
1064
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001065 mDirtyMetaData = false;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001066 ASSERT(!dirtyImageData());
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001067
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001068 return mBaseTexture;
1069}
1070
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001071bool Texture::isDirty() const
1072{
1073 return (mDirty || mDirtyMetaData || dirtyImageData());
1074}
1075
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001076// Returns the top-level texture surface as a render target
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001077void Texture::needRenderTarget()
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001078{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001079 if (!mIsRenderable)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001080 {
1081 mBaseTexture = convertToRenderTarget();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001082 mIsRenderable = true;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001083 }
1084
1085 if (dirtyImageData())
1086 {
1087 updateTexture();
1088 }
1089
1090 mDirtyMetaData = false;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001091}
1092
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001093void Texture::dropTexture()
1094{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001095 if (mBaseTexture)
1096 {
1097 mBaseTexture = NULL;
1098 }
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001099
1100 mIsRenderable = false;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001101}
1102
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001103void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001104{
1105 mBaseTexture = newTexture;
1106 mDirtyMetaData = false;
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001107 mIsRenderable = renderable;
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001108 mDirty = true;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001109}
1110
1111
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001112GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
1113{
1114 if (isPow2(width) && isPow2(height))
1115 {
1116 return maxlevel;
1117 }
1118 else
1119 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001120 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1121 return 1;
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001122 }
1123}
1124
1125GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
1126{
1127 return creationLevels(size, size, maxlevel);
1128}
1129
1130int Texture::levelCount() const
1131{
1132 return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
1133}
1134
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001135Texture2D::Texture2D(GLuint id) : Texture(id)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001136{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001137 mTexture = NULL;
1138}
1139
1140Texture2D::~Texture2D()
1141{
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001142 mColorbufferProxy.set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001143
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001144 if (mTexture)
1145 {
1146 mTexture->Release();
1147 mTexture = NULL;
1148 }
1149}
1150
1151GLenum Texture2D::getTarget() const
1152{
1153 return GL_TEXTURE_2D;
1154}
1155
daniel@transgaming.com01868132010-08-24 19:21:17 +00001156GLenum Texture2D::getFormat() const
1157{
1158 return mImageArray[0].format;
1159}
1160
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001161// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
1162// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
1163// Call this when a particular level of the texture must be defined with a specific format, width and height.
1164//
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +00001165// 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 +00001166// 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 +00001167bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001168{
1169 bool widthOkay = (mWidth >> level == width);
1170 bool heightOkay = (mHeight >> level == height);
1171
1172 bool sizeOkay = ((widthOkay && heightOkay)
1173 || (widthOkay && mHeight >> level == 0 && height == 1)
1174 || (heightOkay && mWidth >> level == 0 && width == 1));
1175
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001176 bool typeOkay = (type == mType);
1177
1178 bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001179
1180 if (!textureOkay)
1181 {
1182 TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
1183 mImageArray[0].format, mWidth, mHeight,
1184 internalFormat, width, height);
1185
1186 // Purge all the levels and the texture.
1187
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001188 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001189 {
1190 if (mImageArray[i].surface != NULL)
1191 {
1192 mImageArray[i].dirty = false;
1193
1194 mImageArray[i].surface->Release();
1195 mImageArray[i].surface = NULL;
1196 }
1197 }
1198
1199 if (mTexture != NULL)
1200 {
1201 mTexture->Release();
1202 mTexture = NULL;
1203 dropTexture();
1204 }
1205
1206 mWidth = width << level;
1207 mHeight = height << level;
1208 mImageArray[0].format = internalFormat;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001209 mType = type;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001210 }
1211
1212 return !textureOkay;
1213}
1214
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001215void 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 +00001216{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001217 redefineTexture(level, internalFormat, width, height, type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001218
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001219 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001220}
1221
daniel@transgaming.com01868132010-08-24 19:21:17 +00001222void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1223{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001224 redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001225
1226 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
1227}
1228
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001229void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1230{
1231 ASSERT(mImageArray[level].surface != NULL);
1232
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001233 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001234 {
1235 IDirect3DSurface9 *destLevel = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001236 HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001237
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001238 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001239
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001240 if (SUCCEEDED(result))
1241 {
1242 Image *img = &mImageArray[level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001243
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001244 RECT sourceRect;
1245 sourceRect.left = xoffset;
1246 sourceRect.top = yoffset;
1247 sourceRect.right = xoffset + width;
1248 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001249
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001250 POINT destPoint;
1251 destPoint.x = xoffset;
1252 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001253
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001254 result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
1255 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001256
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001257 destLevel->Release();
1258
1259 img->dirty = false;
1260 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001261 }
1262}
1263
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001264void 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 +00001265{
daniel@transgaming.com31273552010-08-04 13:42:44 +00001266 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1267 {
1268 commitRect(level, xoffset, yoffset, width, height);
1269 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001270}
1271
daniel@transgaming.com01868132010-08-24 19:21:17 +00001272void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1273{
1274 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1275 {
1276 commitRect(level, xoffset, yoffset, width, height);
1277 }
1278}
1279
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001280void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001281{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001282 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1283
1284 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001285 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001286 ERR("Failed to retrieve the render target.");
1287 return error(GL_OUT_OF_MEMORY);
1288 }
1289
1290 bool redefined = redefineTexture(level, internalFormat, width, height, mType);
1291
1292 if (!isRenderableFormat())
1293 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001294 copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001295 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001296 else
1297 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001298 if (redefined)
1299 {
1300 convertToRenderTarget();
1301 pushTexture(mTexture, true);
1302 }
1303 else
1304 {
1305 needRenderTarget();
1306 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001307
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001308 if (width != 0 && height != 0 && level < levelCount())
1309 {
1310 RECT sourceRect;
1311 sourceRect.left = x;
1312 sourceRect.right = x + width;
1313 sourceRect.top = y;
1314 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001315
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001316 IDirect3DSurface9 *dest;
1317 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001318
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001319 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
1320 dest->Release();
1321 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001322 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001323
1324 mImageArray[level].width = width;
1325 mImageArray[level].height = height;
1326 mImageArray[level].format = internalFormat;
1327}
1328
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001329void 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 +00001330{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001331 if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
1332 {
1333 return error(GL_INVALID_VALUE);
1334 }
1335
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001336 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1337
1338 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001339 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001340 ERR("Failed to retrieve the render target.");
1341 return error(GL_OUT_OF_MEMORY);
1342 }
1343
1344 bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
1345
1346 if (!isRenderableFormat())
1347 {
1348 copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001349 }
1350 else
1351 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001352 if (redefined)
1353 {
1354 convertToRenderTarget();
1355 pushTexture(mTexture, true);
1356 }
1357 else
1358 {
1359 needRenderTarget();
1360 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001361
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001362 if (level < levelCount())
1363 {
1364 RECT sourceRect;
1365 sourceRect.left = x;
1366 sourceRect.right = x + width;
1367 sourceRect.top = y;
1368 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001369
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001370 IDirect3DSurface9 *dest;
1371 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001372
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001373 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
1374 dest->Release();
1375 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001376 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001377}
1378
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001379// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1380bool Texture2D::isComplete() const
1381{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001382 GLsizei width = mImageArray[0].width;
1383 GLsizei height = mImageArray[0].height;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001384
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001385 if (width <= 0 || height <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001386 {
1387 return false;
1388 }
1389
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001390 bool mipmapping = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001391
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001392 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001393 {
1394 case GL_NEAREST:
1395 case GL_LINEAR:
1396 mipmapping = false;
1397 break;
1398 case GL_NEAREST_MIPMAP_NEAREST:
1399 case GL_LINEAR_MIPMAP_NEAREST:
1400 case GL_NEAREST_MIPMAP_LINEAR:
1401 case GL_LINEAR_MIPMAP_LINEAR:
1402 mipmapping = true;
1403 break;
1404 default: UNREACHABLE();
1405 }
1406
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001407 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1408 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1409 {
1410 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1411 {
1412 return false;
1413 }
1414 }
1415
1416
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001417 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
1418 || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1419 {
1420 return false;
1421 }
1422
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001423 if (mipmapping)
1424 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001425 if (!isPow2(width) || !isPow2(height))
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001426 {
1427 return false;
1428 }
1429
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001430 int q = log2(std::max(width, height));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001431
1432 for (int level = 1; level <= q; level++)
1433 {
1434 if (mImageArray[level].format != mImageArray[0].format)
1435 {
1436 return false;
1437 }
1438
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001439 if (mImageArray[level].width != std::max(1, width >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001440 {
1441 return false;
1442 }
1443
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001444 if (mImageArray[level].height != std::max(1, height >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001445 {
1446 return false;
1447 }
1448 }
1449 }
1450
1451 return true;
1452}
1453
daniel@transgaming.com01868132010-08-24 19:21:17 +00001454bool Texture2D::isCompressed() const
1455{
1456 return IsCompressed(getFormat());
1457}
1458
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001459// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001460IDirect3DBaseTexture9 *Texture2D::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001461{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001462 IDirect3DTexture9 *texture;
1463
1464 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001465 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001466
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001467 HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001468
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001469 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001470 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001471 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001472 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001473 }
1474
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001475 if (mTexture) mTexture->Release();
1476 mTexture = texture;
1477 return texture;
1478}
1479
1480void Texture2D::updateTexture()
1481{
1482 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001483
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001484 int levels = levelCount();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001485
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001486 for (int level = 0; level < levels; level++)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001487 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001488 if (mImageArray[level].dirty)
1489 {
1490 IDirect3DSurface9 *levelSurface = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001491 HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001492
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001493 ASSERT(SUCCEEDED(result));
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001494
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001495 if (SUCCEEDED(result))
1496 {
1497 result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
1498 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001499
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001500 levelSurface->Release();
1501
1502 mImageArray[level].dirty = false;
1503 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001504 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001505 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001506}
1507
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001508IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001509{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001510 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001511
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001512 if (mWidth != 0 && mHeight != 0)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001513 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001514 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001515 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001516 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001517
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001518 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 +00001519
1520 if (FAILED(result))
1521 {
1522 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1523 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1524 }
1525
1526 if (mTexture != NULL)
1527 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001528 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001529 for (int i = 0; i < levels; i++)
1530 {
1531 IDirect3DSurface9 *source;
1532 result = mTexture->GetSurfaceLevel(i, &source);
1533
1534 if (FAILED(result))
1535 {
1536 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1537
1538 texture->Release();
1539
1540 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1541 }
1542
1543 IDirect3DSurface9 *dest;
1544 result = texture->GetSurfaceLevel(i, &dest);
1545
1546 if (FAILED(result))
1547 {
1548 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1549
1550 texture->Release();
1551 source->Release();
1552
1553 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1554 }
1555
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001556 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001557 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1558
1559 if (FAILED(result))
1560 {
1561 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1562
1563 texture->Release();
1564 source->Release();
1565 dest->Release();
1566
1567 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1568 }
1569
1570 source->Release();
1571 dest->Release();
1572 }
1573 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001574 }
1575
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001576 if (mTexture != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001577 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001578 mTexture->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001579 }
1580
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001581 mTexture = texture;
1582 return mTexture;
1583}
1584
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001585bool Texture2D::dirtyImageData() const
1586{
1587 int q = log2(std::max(mWidth, mHeight));
1588
1589 for (int i = 0; i <= q; i++)
1590 {
1591 if (mImageArray[i].dirty) return true;
1592 }
1593
1594 return false;
1595}
1596
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001597void Texture2D::generateMipmaps()
1598{
1599 if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
1600 {
1601 return error(GL_INVALID_OPERATION);
1602 }
1603
1604 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1605 unsigned int q = log2(std::max(mWidth, mHeight));
1606 for (unsigned int i = 1; i <= q; i++)
1607 {
1608 if (mImageArray[i].surface != NULL)
1609 {
1610 mImageArray[i].surface->Release();
1611 mImageArray[i].surface = NULL;
1612 }
1613
1614 mImageArray[i].dirty = false;
1615
1616 mImageArray[i].format = mImageArray[0].format;
1617 mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
1618 mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
1619 }
1620
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001621 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001622
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00001623 if (mTexture == NULL)
1624 {
1625 return;
1626 }
1627
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001628 for (unsigned int i = 1; i <= q; i++)
1629 {
1630 IDirect3DSurface9 *upper = NULL;
1631 IDirect3DSurface9 *lower = NULL;
1632
1633 mTexture->GetSurfaceLevel(i-1, &upper);
1634 mTexture->GetSurfaceLevel(i, &lower);
1635
1636 if (upper != NULL && lower != NULL)
1637 {
1638 getBlitter()->boxFilter(upper, lower);
1639 }
1640
1641 if (upper != NULL) upper->Release();
1642 if (lower != NULL) lower->Release();
1643 }
1644}
1645
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001646Renderbuffer *Texture2D::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001647{
1648 if (target != GL_TEXTURE_2D)
1649 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001650 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001651 }
1652
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001653 if (mColorbufferProxy.get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001654 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001655 mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001656 }
1657
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001658 return mColorbufferProxy.get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001659}
1660
1661IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
1662{
1663 ASSERT(target == GL_TEXTURE_2D);
1664
1665 needRenderTarget();
1666
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00001667 if (mTexture == NULL)
1668 {
1669 return NULL;
1670 }
1671
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001672 IDirect3DSurface9 *renderTarget = NULL;
1673 mTexture->GetSurfaceLevel(0, &renderTarget);
1674
1675 return renderTarget;
1676}
1677
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001678TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001679{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001680 mTexture = NULL;
1681}
1682
1683TextureCubeMap::~TextureCubeMap()
1684{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001685 for (int i = 0; i < 6; i++)
1686 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001687 mFaceProxies[i].set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001688 }
1689
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690 if (mTexture)
1691 {
1692 mTexture->Release();
1693 mTexture = NULL;
1694 }
1695}
1696
1697GLenum TextureCubeMap::getTarget() const
1698{
1699 return GL_TEXTURE_CUBE_MAP;
1700}
1701
daniel@transgaming.com01868132010-08-24 19:21:17 +00001702GLenum TextureCubeMap::getFormat() const
1703{
1704 return mImageArray[0][0].format;
1705}
1706
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001707void 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 +00001708{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001709 setImage(0, 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::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 +00001713{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001714 setImage(1, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001715}
1716
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001717void 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 +00001718{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001719 setImage(2, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001720}
1721
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001722void 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 +00001723{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001724 setImage(3, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001725}
1726
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001727void 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 +00001728{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001729 setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730}
1731
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001732void 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 +00001733{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001734 setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001735}
1736
daniel@transgaming.com01868132010-08-24 19:21:17 +00001737void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1738{
1739 redefineTexture(level, internalFormat, width);
1740
1741 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
1742}
1743
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001744void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1745{
1746 int face = faceIndex(faceTarget);
1747
1748 ASSERT(mImageArray[face][level].surface != NULL);
1749
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001750 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001751 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001752 IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
1753 ASSERT(destLevel != NULL);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001754
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001755 if (destLevel != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001756 {
1757 Image *img = &mImageArray[face][level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001758
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001759 RECT sourceRect;
1760 sourceRect.left = xoffset;
1761 sourceRect.top = yoffset;
1762 sourceRect.right = xoffset + width;
1763 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001764
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001765 POINT destPoint;
1766 destPoint.x = xoffset;
1767 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001768
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001769 HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001770 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001771
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001772 destLevel->Release();
1773
1774 img->dirty = false;
1775 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001776 }
1777}
1778
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001779void 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 +00001780{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001781 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com31273552010-08-04 13:42:44 +00001782 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001783 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com31273552010-08-04 13:42:44 +00001784 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001785}
1786
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001787void 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 +00001788{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001789 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com01868132010-08-24 19:21:17 +00001790 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001791 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001792 }
1793}
1794
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001795// 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 +00001796bool TextureCubeMap::isComplete() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001798 int size = mImageArray[0][0].width;
1799
1800 if (size <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001801 {
1802 return false;
1803 }
1804
1805 bool mipmapping;
1806
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001807 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001808 {
1809 case GL_NEAREST:
1810 case GL_LINEAR:
1811 mipmapping = false;
1812 break;
1813 case GL_NEAREST_MIPMAP_NEAREST:
1814 case GL_LINEAR_MIPMAP_NEAREST:
1815 case GL_NEAREST_MIPMAP_LINEAR:
1816 case GL_LINEAR_MIPMAP_LINEAR:
1817 mipmapping = true;
1818 break;
1819 default: UNREACHABLE();
1820 }
1821
1822 for (int face = 0; face < 6; face++)
1823 {
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001824 if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001825 {
1826 return false;
1827 }
1828 }
1829
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001830 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1831 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1832 {
1833 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1834 {
1835 return false;
1836 }
1837 }
1838
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001839 if (mipmapping)
1840 {
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001841 if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
1842 {
1843 return false;
1844 }
1845
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001846 int q = log2(size);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001847
1848 for (int face = 0; face < 6; face++)
1849 {
1850 for (int level = 1; level <= q; level++)
1851 {
1852 if (mImageArray[face][level].format != mImageArray[0][0].format)
1853 {
1854 return false;
1855 }
1856
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001857 if (mImageArray[face][level].width != std::max(1, size >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001858 {
1859 return false;
1860 }
1861
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001862 ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001863 }
1864 }
1865 }
1866
1867 return true;
1868}
1869
daniel@transgaming.com01868132010-08-24 19:21:17 +00001870bool TextureCubeMap::isCompressed() const
1871{
1872 return IsCompressed(getFormat());
1873}
1874
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001875// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001876IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001877{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001878 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001879 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001880
1881 IDirect3DCubeTexture9 *texture;
1882
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001883 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001884
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001885 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001886 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001887 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001888 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001889 }
1890
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001891 if (mTexture) mTexture->Release();
1892
1893 mTexture = texture;
1894 return mTexture;
1895}
1896
1897void TextureCubeMap::updateTexture()
1898{
1899 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001900
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001901 for (int face = 0; face < 6; face++)
1902 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001903 int levels = levelCount();
1904 for (int level = 0; level < levels; level++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001906 Image *img = &mImageArray[face][level];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001907
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001908 if (img->dirty)
1909 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001910 IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
1911 ASSERT(levelSurface != NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001912
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001913 if (levelSurface != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001914 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001915 HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001916 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001917
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001918 levelSurface->Release();
1919
1920 img->dirty = false;
1921 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001922 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001923 }
1924 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001925}
1926
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001927IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
1928{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001929 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001930
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001931 if (mWidth != 0)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001932 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001933 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001934 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001935 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001936
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001937 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001938
1939 if (FAILED(result))
1940 {
1941 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1942 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1943 }
1944
1945 if (mTexture != NULL)
1946 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001947 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001948 for (int f = 0; f < 6; f++)
1949 {
1950 for (int i = 0; i < levels; i++)
1951 {
1952 IDirect3DSurface9 *source;
1953 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
1954
1955 if (FAILED(result))
1956 {
1957 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1958
1959 texture->Release();
1960
1961 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1962 }
1963
1964 IDirect3DSurface9 *dest;
1965 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
1966
1967 if (FAILED(result))
1968 {
1969 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1970
1971 texture->Release();
1972 source->Release();
1973
1974 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1975 }
1976
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001977 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001978 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1979
1980 if (FAILED(result))
1981 {
1982 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1983
1984 texture->Release();
1985 source->Release();
1986 dest->Release();
1987
1988 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1989 }
1990 }
1991 }
1992 }
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001993 }
1994
1995 if (mTexture != NULL)
1996 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001997 mTexture->Release();
1998 }
1999
2000 mTexture = texture;
2001 return mTexture;
2002}
2003
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002004void 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 +00002005{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002006 redefineTexture(level, internalFormat, width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002007
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002008 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002009}
daniel@transgaming.com00c75962010-03-11 20:36:15 +00002010
2011unsigned int TextureCubeMap::faceIndex(GLenum face)
2012{
2013 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2014 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2015 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2016 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2017 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2018
2019 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2020}
2021
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00002022bool TextureCubeMap::dirtyImageData() const
2023{
2024 int q = log2(mWidth);
2025
2026 for (int f = 0; f < 6; f++)
2027 {
2028 for (int i = 0; i <= q; i++)
2029 {
2030 if (mImageArray[f][i].dirty) return true;
2031 }
2032 }
2033
2034 return false;
2035}
2036
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002037// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
2038// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
2039// Call this when a particular level of the texture must be defined with a specific format, width and height.
2040//
2041// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
2042// a new size for the texture by working backwards from the given size.
2043bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
2044{
2045 // Are these settings compatible with level 0?
2046 bool sizeOkay = (mImageArray[0][0].width >> level == width);
2047
2048 bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
2049
2050 if (!textureOkay)
2051 {
2052 TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
2053 mImageArray[0][0].format, mImageArray[0][0].width,
2054 internalFormat, width);
2055
2056 // Purge all the levels and the texture.
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00002057 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002058 {
2059 for (int f = 0; f < 6; f++)
2060 {
2061 if (mImageArray[f][i].surface != NULL)
2062 {
2063 mImageArray[f][i].dirty = false;
2064
2065 mImageArray[f][i].surface->Release();
2066 mImageArray[f][i].surface = NULL;
2067 }
2068 }
2069 }
2070
2071 if (mTexture != NULL)
2072 {
2073 mTexture->Release();
2074 mTexture = NULL;
2075 dropTexture();
2076 }
2077
2078 mWidth = width << level;
2079 mImageArray[0][0].width = width << level;
2080 mHeight = width << level;
2081 mImageArray[0][0].height = width << level;
2082
2083 mImageArray[0][0].format = internalFormat;
2084 }
2085
2086 return !textureOkay;
2087}
2088
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002089void 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 +00002090{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002091 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002092
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002093 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002094 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002095 ERR("Failed to retrieve the render target.");
2096 return error(GL_OUT_OF_MEMORY);
2097 }
2098
2099 unsigned int faceindex = faceIndex(target);
2100 bool redefined = redefineTexture(level, internalFormat, width);
2101
2102 if (!isRenderableFormat())
2103 {
2104 copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002105 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00002106 else
2107 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002108 if (redefined)
2109 {
2110 convertToRenderTarget();
2111 pushTexture(mTexture, true);
2112 }
2113 else
2114 {
2115 needRenderTarget();
2116 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002117
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002118 ASSERT(width == height);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002119
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002120 if (width > 0 && level < levelCount())
2121 {
2122 RECT sourceRect;
2123 sourceRect.left = x;
2124 sourceRect.right = x + width;
2125 sourceRect.top = y;
2126 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002127
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002128 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002129
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002130 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
2131 dest->Release();
2132 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002133 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002134
2135 mImageArray[faceindex][level].width = width;
2136 mImageArray[faceindex][level].height = height;
2137 mImageArray[faceindex][level].format = internalFormat;
2138}
2139
2140IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
2141{
2142 unsigned int faceIndex;
2143
2144 if (faceIdentifier < 6)
2145 {
2146 faceIndex = faceIdentifier;
2147 }
2148 else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2149 {
2150 faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2151 }
2152 else
2153 {
2154 UNREACHABLE();
2155 faceIndex = 0;
2156 }
2157
2158 if (mTexture == NULL)
2159 {
2160 UNREACHABLE();
2161 return NULL;
2162 }
2163
2164 IDirect3DSurface9 *surface = NULL;
2165
2166 HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
2167
2168 return (SUCCEEDED(hr)) ? surface : NULL;
2169}
2170
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002171void 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 +00002172{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002173 GLsizei size = mImageArray[faceIndex(target)][level].width;
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002174
2175 if (xoffset + width > size || yoffset + height > size)
2176 {
2177 return error(GL_INVALID_VALUE);
2178 }
2179
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002180 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2181
2182 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002183 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002184 ERR("Failed to retrieve the render target.");
2185 return error(GL_OUT_OF_MEMORY);
2186 }
2187
2188 unsigned int faceindex = faceIndex(target);
2189 bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
2190
2191 if (!isRenderableFormat())
2192 {
2193 copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002194 }
2195 else
2196 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002197 if (redefined)
2198 {
2199 convertToRenderTarget();
2200 pushTexture(mTexture, true);
2201 }
2202 else
2203 {
2204 needRenderTarget();
2205 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002206
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002207 if (level < levelCount())
2208 {
2209 RECT sourceRect;
2210 sourceRect.left = x;
2211 sourceRect.right = x + width;
2212 sourceRect.top = y;
2213 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002214
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002215 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002216
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002217 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
2218 dest->Release();
2219 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00002220 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002221}
2222
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002223bool TextureCubeMap::isCubeComplete() const
2224{
2225 if (mImageArray[0][0].width == 0)
2226 {
2227 return false;
2228 }
2229
2230 for (unsigned int f = 1; f < 6; f++)
2231 {
2232 if (mImageArray[f][0].width != mImageArray[0][0].width
2233 || mImageArray[f][0].format != mImageArray[0][0].format)
2234 {
2235 return false;
2236 }
2237 }
2238
2239 return true;
2240}
2241
2242void TextureCubeMap::generateMipmaps()
2243{
2244 if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
2245 {
2246 return error(GL_INVALID_OPERATION);
2247 }
2248
2249 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2250 unsigned int q = log2(mImageArray[0][0].width);
2251 for (unsigned int f = 0; f < 6; f++)
2252 {
2253 for (unsigned int i = 1; i <= q; i++)
2254 {
2255 if (mImageArray[f][i].surface != NULL)
2256 {
2257 mImageArray[f][i].surface->Release();
2258 mImageArray[f][i].surface = NULL;
2259 }
2260
2261 mImageArray[f][i].dirty = false;
2262
2263 mImageArray[f][i].format = mImageArray[f][0].format;
2264 mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
2265 mImageArray[f][i].height = mImageArray[f][i].width;
2266 }
2267 }
2268
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002269 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002270
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00002271 if (mTexture == NULL)
2272 {
2273 return;
2274 }
2275
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002276 for (unsigned int f = 0; f < 6; f++)
2277 {
2278 for (unsigned int i = 1; i <= q; i++)
2279 {
2280 IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
2281 IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
2282
2283 if (upper != NULL && lower != NULL)
2284 {
2285 getBlitter()->boxFilter(upper, lower);
2286 }
2287
2288 if (upper != NULL) upper->Release();
2289 if (lower != NULL) lower->Release();
2290 }
2291 }
2292}
2293
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002294Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002295{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002296 if (!IsCubemapTextureTarget(target))
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002297 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002298 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002299 }
2300
2301 unsigned int face = faceIndex(target);
2302
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002303 if (mFaceProxies[face].get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002304 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002305 mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002306 }
2307
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002308 return mFaceProxies[face].get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002309}
2310
2311IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2312{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002313 ASSERT(IsCubemapTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002314
2315 needRenderTarget();
daniel@transgaming.come979ead2010-09-23 18:03:14 +00002316
2317 if (mTexture == NULL)
2318 {
2319 return NULL;
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00002320 }
2321
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002322 IDirect3DSurface9 *renderTarget = NULL;
2323 mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
2324
2325 return renderTarget;
2326}
2327
2328Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
enne@chromium.org0fa74632010-09-21 16:18:52 +00002329 : Colorbuffer(texture), mTexture(texture), mTarget(target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002330{
daniel@transgaming.comedc19182010-10-15 17:57:55 +00002331 ASSERT(IsTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002332}
2333
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002334void Texture::TextureColorbufferProxy::addRef() const
2335{
2336 mTexture->addRef();
2337}
2338
2339void Texture::TextureColorbufferProxy::release() const
2340{
2341 mTexture->release();
2342}
2343
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002344IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
2345{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002346 if (mRenderTarget) mRenderTarget->Release();
2347
2348 mRenderTarget = mTexture->getRenderTarget(mTarget);
2349
2350 return mRenderTarget;
2351}
2352
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002353int Texture::TextureColorbufferProxy::getWidth() const
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002354{
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002355 return mTexture->getWidth();
2356}
2357
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002358int Texture::TextureColorbufferProxy::getHeight() const
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002359{
2360 return mTexture->getHeight();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002361}
2362
daniel@transgaming.com01868132010-08-24 19:21:17 +00002363GLenum Texture::TextureColorbufferProxy::getFormat() const
2364{
2365 return mTexture->getFormat();
2366}
2367
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002368bool Texture::TextureColorbufferProxy::isFloatingPoint() const
2369{
2370 return mTexture->isFloatingPoint();
2371}
2372
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002373}