blob: c9701d70135f8a54480fac9224a90adf11c2ba4b [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:
apatrick@chromium.org9c857952010-11-16 18:27:58 +0000194 case D3DFMT_X8R8G8B8:
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000195 case D3DFMT_A16B16G16R16F:
196 case D3DFMT_A32B32G32R32F:
197 return true;
198 default:
199 UNREACHABLE();
200 }
201
202 return false;
203}
204
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205// Selects an internal Direct3D 9 format for storing an Image
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000206D3DFORMAT Texture::selectFormat(GLenum format, GLenum type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207{
daniel@transgaming.com01868132010-08-24 19:21:17 +0000208 if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
209 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
210 {
211 return D3DFMT_DXT1;
212 }
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000213 else if (type == GL_FLOAT)
214 {
215 return D3DFMT_A32B32G32R32F;
216 }
217 else if (type == GL_HALF_FLOAT_OES)
218 {
219 return D3DFMT_A16B16G16R16F;
220 }
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000221 else if (type == GL_UNSIGNED_BYTE)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000222 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000223 if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
224 {
225 return D3DFMT_L8;
226 }
227 else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
228 {
229 return D3DFMT_A8L8;
230 }
apatrick@chromium.org9c857952010-11-16 18:27:58 +0000231 else if (format == GL_RGB)
232 {
233 return D3DFMT_X8R8G8B8;
234 }
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000235
daniel@transgaming.com01868132010-08-24 19:21:17 +0000236 return D3DFMT_A8R8G8B8;
237 }
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000238
239 return D3DFMT_A8R8G8B8;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240}
241
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000242// 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 +0000243// into the target pixel rectangle at output with outputPitch bytes in between each line.
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000244void Texture::loadImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000245 GLint unpackAlignment, const void *input, size_t outputPitch, void *output, D3DSURFACE_DESC *description) const
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000246{
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000247 GLsizei inputPitch = ComputePitch(width, format, type, unpackAlignment);
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000248
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000249 switch (type)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000250 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000251 case GL_UNSIGNED_BYTE:
252 switch (format)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000253 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000254 case GL_ALPHA:
255 loadAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
256 break;
257 case GL_LUMINANCE:
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000258 loadLuminanceImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_L8);
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000259 break;
260 case GL_LUMINANCE_ALPHA:
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000261 loadLuminanceAlphaImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output, description->Format == D3DFMT_A8L8);
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000262 break;
263 case GL_RGB:
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000264 loadRGBUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
265 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000266 case GL_RGBA:
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000267 loadRGBAUByteImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
268 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000269 case GL_BGRA_EXT:
270 loadBGRAImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000271 break;
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000272 default: UNREACHABLE();
273 }
274 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000275 case GL_UNSIGNED_SHORT_5_6_5:
276 switch (format)
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000277 {
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000278 case GL_RGB:
279 loadRGB565ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000280 break;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000281 default: UNREACHABLE();
282 }
283 break;
284 case GL_UNSIGNED_SHORT_4_4_4_4:
285 switch (format)
286 {
287 case GL_RGBA:
288 loadRGBA4444ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
289 break;
290 default: UNREACHABLE();
291 }
292 break;
293 case GL_UNSIGNED_SHORT_5_5_5_1:
294 switch (format)
295 {
296 case GL_RGBA:
297 loadRGBA5551ImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
298 break;
299 default: UNREACHABLE();
300 }
301 break;
302 case GL_FLOAT:
303 switch (format)
304 {
305 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
306 case GL_ALPHA:
307 loadAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
308 break;
309 case GL_LUMINANCE:
310 loadLuminanceFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
311 break;
312 case GL_LUMINANCE_ALPHA:
313 loadLuminanceAlphaFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
314 break;
315 case GL_RGB:
316 loadRGBFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
317 break;
318 case GL_RGBA:
319 loadRGBAFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
320 break;
321 default: UNREACHABLE();
322 }
323 break;
324 case GL_HALF_FLOAT_OES:
325 switch (format)
326 {
327 // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
328 case GL_ALPHA:
329 loadAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
330 break;
331 case GL_LUMINANCE:
332 loadLuminanceHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
333 break;
334 case GL_LUMINANCE_ALPHA:
335 loadLuminanceAlphaHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
336 break;
337 case GL_RGB:
338 loadRGBHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
339 break;
340 case GL_RGBA:
341 loadRGBAHalfFloatImageData(xoffset, yoffset, width, height, inputPitch, input, outputPitch, output);
342 break;
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000343 default: UNREACHABLE();
344 }
345 break;
346 default: UNREACHABLE();
347 }
348}
349
350void Texture::loadAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
351 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
352{
353 const unsigned char *source = NULL;
354 unsigned char *dest = NULL;
355
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000356 for (int y = 0; y < height; y++)
357 {
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000358 source = static_cast<const unsigned char*>(input) + y * inputPitch;
359 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000360 for (int x = 0; x < width; x++)
361 {
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000362 dest[4 * x + 0] = 0;
363 dest[4 * x + 1] = 0;
364 dest[4 * x + 2] = 0;
365 dest[4 * x + 3] = source[x];
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000366 }
367 }
368}
369
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000370void Texture::loadAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
371 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
372{
373 const float *source = NULL;
374 float *dest = NULL;
375
376 for (int y = 0; y < height; y++)
377 {
378 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
379 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
380 for (int x = 0; x < width; x++)
381 {
382 dest[4 * x + 0] = 0;
383 dest[4 * x + 1] = 0;
384 dest[4 * x + 2] = 0;
385 dest[4 * x + 3] = source[x];
386 }
387 }
388}
389
390void Texture::loadAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
391 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
392{
393 const unsigned short *source = NULL;
394 unsigned short *dest = NULL;
395
396 for (int y = 0; y < height; y++)
397 {
398 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
399 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
400 for (int x = 0; x < width; x++)
401 {
402 dest[4 * x + 0] = 0;
403 dest[4 * x + 1] = 0;
404 dest[4 * x + 2] = 0;
405 dest[4 * x + 3] = source[x];
406 }
407 }
408}
409
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000410void Texture::loadLuminanceImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000411 size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000412{
413 const unsigned char *source = NULL;
414 unsigned char *dest = NULL;
415
416 for (int y = 0; y < height; y++)
417 {
418 source = static_cast<const unsigned char*>(input) + y * inputPitch;
419 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000420
421 if (!native) // BGRA8 destination format
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000422 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000423 for (int x = 0; x < width; x++)
424 {
425 dest[4 * x + 0] = source[x];
426 dest[4 * x + 1] = source[x];
427 dest[4 * x + 2] = source[x];
428 dest[4 * x + 3] = 0xFF;
429 }
430 }
431 else // L8 destination format
432 {
433 memcpy(dest, source, width);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000434 }
435 }
436}
437
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000438void Texture::loadLuminanceFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
439 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
440{
441 const float *source = NULL;
442 float *dest = NULL;
443
444 for (int y = 0; y < height; y++)
445 {
446 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
447 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
448 for (int x = 0; x < width; x++)
449 {
450 dest[4 * x + 0] = source[x];
451 dest[4 * x + 1] = source[x];
452 dest[4 * x + 2] = source[x];
453 dest[4 * x + 3] = 1.0f;
454 }
455 }
456}
457
458void Texture::loadLuminanceHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
459 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
460{
461 const unsigned short *source = NULL;
462 unsigned short *dest = NULL;
463
464 for (int y = 0; y < height; y++)
465 {
466 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
467 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
468 for (int x = 0; x < width; x++)
469 {
470 dest[4 * x + 0] = source[x];
471 dest[4 * x + 1] = source[x];
472 dest[4 * x + 2] = source[x];
473 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
474 }
475 }
476}
477
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000478void Texture::loadLuminanceAlphaImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000479 size_t inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000480{
481 const unsigned char *source = NULL;
482 unsigned char *dest = NULL;
483
484 for (int y = 0; y < height; y++)
485 {
486 source = static_cast<const unsigned char*>(input) + y * inputPitch;
487 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000488
489 if (!native) // BGRA8 destination format
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000490 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000491 for (int x = 0; x < width; x++)
492 {
493 dest[4 * x + 0] = source[2*x+0];
494 dest[4 * x + 1] = source[2*x+0];
495 dest[4 * x + 2] = source[2*x+0];
496 dest[4 * x + 3] = source[2*x+1];
497 }
498 }
499 else
500 {
501 memcpy(dest, source, width * 2);
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000502 }
503 }
504}
505
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000506void Texture::loadLuminanceAlphaFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
507 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
508{
509 const float *source = NULL;
510 float *dest = NULL;
511
512 for (int y = 0; y < height; y++)
513 {
514 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
515 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
516 for (int x = 0; x < width; x++)
517 {
518 dest[4 * x + 0] = source[2*x+0];
519 dest[4 * x + 1] = source[2*x+0];
520 dest[4 * x + 2] = source[2*x+0];
521 dest[4 * x + 3] = source[2*x+1];
522 }
523 }
524}
525
526void Texture::loadLuminanceAlphaHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
527 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
528{
529 const unsigned short *source = NULL;
530 unsigned short *dest = NULL;
531
532 for (int y = 0; y < height; y++)
533 {
534 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
535 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
536 for (int x = 0; x < width; x++)
537 {
538 dest[4 * x + 0] = source[2*x+0];
539 dest[4 * x + 1] = source[2*x+0];
540 dest[4 * x + 2] = source[2*x+0];
541 dest[4 * x + 3] = source[2*x+1];
542 }
543 }
544}
545
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000546void Texture::loadRGBUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
547 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
548{
549 const unsigned char *source = NULL;
550 unsigned char *dest = NULL;
551
552 for (int y = 0; y < height; y++)
553 {
554 source = static_cast<const unsigned char*>(input) + y * inputPitch;
555 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
556 for (int x = 0; x < width; x++)
557 {
558 dest[4 * x + 0] = source[x * 3 + 2];
559 dest[4 * x + 1] = source[x * 3 + 1];
560 dest[4 * x + 2] = source[x * 3 + 0];
561 dest[4 * x + 3] = 0xFF;
562 }
563 }
564}
565
566void Texture::loadRGB565ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
567 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
568{
569 const unsigned short *source = NULL;
570 unsigned char *dest = NULL;
571
572 for (int y = 0; y < height; y++)
573 {
574 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
575 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
576 for (int x = 0; x < width; x++)
577 {
578 unsigned short rgba = source[x];
579 dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
580 dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
581 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
582 dest[4 * x + 3] = 0xFF;
583 }
584 }
585}
586
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000587void Texture::loadRGBFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
588 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
589{
590 const float *source = NULL;
591 float *dest = NULL;
592
593 for (int y = 0; y < height; y++)
594 {
595 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
596 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
597 for (int x = 0; x < width; x++)
598 {
599 dest[4 * x + 0] = source[x * 3 + 0];
600 dest[4 * x + 1] = source[x * 3 + 1];
601 dest[4 * x + 2] = source[x * 3 + 2];
602 dest[4 * x + 3] = 1.0f;
603 }
604 }
605}
606
607void Texture::loadRGBHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
608 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
609{
610 const unsigned short *source = NULL;
611 unsigned short *dest = NULL;
612
613 for (int y = 0; y < height; y++)
614 {
615 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
616 dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8);
617 for (int x = 0; x < width; x++)
618 {
619 dest[4 * x + 0] = source[x * 3 + 0];
620 dest[4 * x + 1] = source[x * 3 + 1];
621 dest[4 * x + 2] = source[x * 3 + 2];
622 dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
623 }
624 }
625}
626
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000627void Texture::loadRGBAUByteImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
628 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
629{
630 const unsigned char *source = NULL;
631 unsigned char *dest = NULL;
632
633 for (int y = 0; y < height; y++)
634 {
635 source = static_cast<const unsigned char*>(input) + y * inputPitch;
636 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
637 for (int x = 0; x < width; x++)
638 {
639 dest[4 * x + 0] = source[x * 4 + 2];
640 dest[4 * x + 1] = source[x * 4 + 1];
641 dest[4 * x + 2] = source[x * 4 + 0];
642 dest[4 * x + 3] = source[x * 4 + 3];
643 }
644 }
645}
646
647void Texture::loadRGBA4444ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
648 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
649{
650 const unsigned short *source = NULL;
651 unsigned char *dest = NULL;
652
653 for (int y = 0; y < height; y++)
654 {
655 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
656 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
657 for (int x = 0; x < width; x++)
658 {
659 unsigned short rgba = source[x];
660 dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
661 dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
662 dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
663 dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
664 }
665 }
666}
667
668void Texture::loadRGBA5551ImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
669 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
670{
671 const unsigned short *source = NULL;
672 unsigned char *dest = NULL;
673
674 for (int y = 0; y < height; y++)
675 {
676 source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
677 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
678 for (int x = 0; x < width; x++)
679 {
680 unsigned short rgba = source[x];
681 dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
682 dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
683 dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
684 dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
685 }
686 }
687}
688
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000689void Texture::loadRGBAFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
690 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
691{
692 const float *source = NULL;
693 float *dest = NULL;
694
695 for (int y = 0; y < height; y++)
696 {
697 source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
698 dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 16);
699 memcpy(dest, source, width * 16);
700 }
701}
702
703void Texture::loadRGBAHalfFloatImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
704 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
705{
706 const unsigned char *source = NULL;
707 unsigned char *dest = NULL;
708
709 for (int y = 0; y < height; y++)
710 {
711 source = static_cast<const unsigned char*>(input) + y * inputPitch;
712 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 8;
713 memcpy(dest, source, width * 8);
714 }
715}
716
daniel@transgaming.com1ac37d82010-08-24 19:21:31 +0000717void Texture::loadBGRAImageData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
718 size_t inputPitch, const void *input, size_t outputPitch, void *output) const
719{
720 const unsigned char *source = NULL;
721 unsigned char *dest = NULL;
722
723 for (int y = 0; y < height; y++)
724 {
725 source = static_cast<const unsigned char*>(input) + y * inputPitch;
726 dest = static_cast<unsigned char*>(output) + (y + yoffset) * outputPitch + xoffset * 4;
727 memcpy(dest, source, width*4);
728 }
729}
730
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000731void Texture::createSurface(GLsizei width, GLsizei height, GLenum format, GLenum type, Image *img)
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000732{
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000733 IDirect3DTexture9 *newTexture = NULL;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000734 IDirect3DSurface9 *newSurface = NULL;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000735
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +0000736 if (width != 0 && height != 0)
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000737 {
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000738 int levelToFetch = 0;
739 GLsizei requestWidth = width;
740 GLsizei requestHeight = height;
741 if (IsCompressed(format) && (width % 4 != 0 || height % 4 != 0))
742 {
743 bool isMult4 = false;
744 int upsampleCount = 0;
745 while (!isMult4)
746 {
747 requestWidth <<= 1;
748 requestHeight <<= 1;
749 upsampleCount++;
750 if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
751 {
752 isMult4 = true;
753 }
754 }
755 levelToFetch = upsampleCount;
756 }
757
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000758 HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, selectFormat(format, type),
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000759 D3DPOOL_SYSTEMMEM, &newTexture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +0000760
761 if (FAILED(result))
762 {
763 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
764 return error(GL_OUT_OF_MEMORY);
765 }
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000766
daniel@transgaming.com1dcea9f2010-08-24 19:21:27 +0000767 newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
daniel@transgaming.comf5cde482010-08-24 19:21:11 +0000768 newTexture->Release();
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000769 }
770
771 if (img->surface) img->surface->Release();
772 img->surface = newSurface;
773
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000774 img->width = width;
775 img->height = height;
776 img->format = format;
daniel@transgaming.com01868132010-08-24 19:21:17 +0000777}
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000778
daniel@transgaming.com01868132010-08-24 19:21:17 +0000779void Texture::setImage(GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *img)
780{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000781 createSurface(width, height, format, type, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000782
783 if (pixels != NULL && img->surface != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000785 D3DSURFACE_DESC description;
786 img->surface->GetDesc(&description);
787
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000788 D3DLOCKED_RECT locked;
daniel@transgaming.com01868132010-08-24 19:21:17 +0000789 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000790
791 ASSERT(SUCCEEDED(result));
792
793 if (SUCCEEDED(result))
794 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000795 loadImageData(0, 0, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000796 img->surface->UnlockRect();
797 }
798
799 img->dirty = true;
800 }
801
802 mDirtyMetaData = true;
803}
804
805void Texture::setCompressedImage(GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
806{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000807 createSurface(width, height, format, GL_UNSIGNED_BYTE, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000808
809 if (pixels != NULL && img->surface != NULL)
810 {
811 D3DLOCKED_RECT locked;
812 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
813
814 ASSERT(SUCCEEDED(result));
815
816 if (SUCCEEDED(result))
817 {
818 memcpy(locked.pBits, pixels, imageSize);
819 img->surface->UnlockRect();
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000820 }
821
822 img->dirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000823 }
824
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000825 mDirtyMetaData = true;
826}
827
daniel@transgaming.com31273552010-08-04 13:42:44 +0000828bool 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 +0000829{
daniel@transgaming.com31273552010-08-04 13:42:44 +0000830 if (width + xoffset > img->width || height + yoffset > img->height)
831 {
832 error(GL_INVALID_VALUE);
833 return false;
834 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000835
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000836 if (!img->surface)
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000837 {
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000838 createSurface(img->width, img->height, format, type, img);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +0000839 }
840
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000841 if (pixels != NULL && img->surface != NULL)
842 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000843 D3DSURFACE_DESC description;
844 img->surface->GetDesc(&description);
845
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000846 D3DLOCKED_RECT locked;
847 HRESULT result = img->surface->LockRect(&locked, NULL, 0);
848
849 ASSERT(SUCCEEDED(result));
850
851 if (SUCCEEDED(result))
852 {
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +0000853 loadImageData(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, locked.Pitch, locked.pBits, &description);
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000854 img->surface->UnlockRect();
855 }
856
857 img->dirty = true;
858 }
859
daniel@transgaming.com31273552010-08-04 13:42:44 +0000860 return true;
daniel@transgaming.com29d27002010-03-11 19:41:22 +0000861}
862
daniel@transgaming.com01868132010-08-24 19:21:17 +0000863bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *img)
864{
865 if (width + xoffset > img->width || height + yoffset > img->height)
866 {
867 error(GL_INVALID_VALUE);
868 return false;
869 }
870
871 if (format != getFormat())
872 {
873 error(GL_INVALID_OPERATION);
874 return false;
875 }
876
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000877 if (!img->surface)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000878 {
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000879 createSurface(img->width, img->height, format, GL_UNSIGNED_BYTE, img);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000880 }
881
daniel@transgaming.comd3958d72010-09-22 17:13:54 +0000882 if (pixels != NULL && img->surface != NULL)
883 {
884 RECT updateRegion;
885 updateRegion.left = xoffset;
886 updateRegion.right = xoffset + width;
887 updateRegion.bottom = yoffset + height;
888 updateRegion.top = yoffset;
889
890 D3DLOCKED_RECT locked;
891 HRESULT result = img->surface->LockRect(&locked, &updateRegion, 0);
892
893 ASSERT(SUCCEEDED(result));
894
895 if (SUCCEEDED(result))
896 {
897 GLsizei inputPitch = ComputeCompressedPitch(width, format);
898 int rows = imageSize / inputPitch;
899 for (int i = 0; i < rows; ++i)
900 {
901 memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)pixels + i * inputPitch), inputPitch);
902 }
903 img->surface->UnlockRect();
904 }
905
906 img->dirty = true;
907 }
908
daniel@transgaming.com01868132010-08-24 19:21:17 +0000909 return true;
910}
911
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +0000912// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats
913void Texture::copyNonRenderable(Image *image, GLenum internalFormat, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
914{
915 IDirect3DDevice9 *device = getDevice();
916 IDirect3DSurface9 *surface = NULL;
917 D3DSURFACE_DESC description;
918 renderTarget->GetDesc(&description);
919
920 HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &surface, NULL);
921
922 if (!SUCCEEDED(result))
923 {
924 ERR("Could not create matching destination surface.");
925 return error(GL_OUT_OF_MEMORY);
926 }
927
928 result = device->GetRenderTargetData(renderTarget, surface);
929
930 if (!SUCCEEDED(result))
931 {
932 ERR("GetRenderTargetData unexpectedly failed.");
933 surface->Release();
934 return error(GL_OUT_OF_MEMORY);
935 }
936
937 D3DLOCKED_RECT sourceLock = {0};
938 RECT sourceRect = {x, y, x + width, y + height};
939 result = surface->LockRect(&sourceLock, &sourceRect, 0);
940
941 if (FAILED(result))
942 {
943 ERR("Failed to lock the source surface (rectangle might be invalid).");
944 surface->UnlockRect();
945 surface->Release();
946 return error(GL_OUT_OF_MEMORY);
947 }
948
949 if (!image->surface)
950 {
951 createSurface(width, height, internalFormat, mType, image);
952 }
953
954 if (image->surface == NULL)
955 {
956 ERR("Failed to create an image surface.");
957 surface->UnlockRect();
958 surface->Release();
959 return error(GL_OUT_OF_MEMORY);
960 }
961
962 D3DLOCKED_RECT destLock = {0};
963 RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
964 result = image->surface->LockRect(&destLock, &destRect, 0);
965
966 if (FAILED(result))
967 {
968 ERR("Failed to lock the destination surface (rectangle might be invalid).");
969 surface->UnlockRect();
970 surface->Release();
971 return error(GL_OUT_OF_MEMORY);
972 }
973
974 if (destLock.pBits && sourceLock.pBits)
975 {
976 unsigned char *source = (unsigned char*)sourceLock.pBits;
977 unsigned char *dest = (unsigned char*)destLock.pBits;
978
979 switch (description.Format)
980 {
981 case D3DFMT_X8R8G8B8:
982 case D3DFMT_A8R8G8B8:
983 switch(getD3DFormat())
984 {
985 case D3DFMT_L8:
986 for(int y = 0; y < height; y++)
987 {
988 for(int x = 0; x < height; x++)
989 {
990 dest[x] = source[x * 4 + 2];
991 }
992
993 source += sourceLock.Pitch;
994 dest += destLock.Pitch;
995 }
996 break;
997 case D3DFMT_A8L8:
998 for(int y = 0; y < height; y++)
999 {
1000 for(int x = 0; x < height; x++)
1001 {
1002 dest[x * 2 + 0] = source[x * 4 + 2];
1003 dest[x * 2 + 1] = source[x * 4 + 3];
1004 }
1005
1006 source += sourceLock.Pitch;
1007 dest += destLock.Pitch;
1008 }
1009 break;
1010 default:
1011 UNREACHABLE();
1012 }
1013 break;
daniel@transgaming.comfe5141e2010-10-18 12:18:12 +00001014 case D3DFMT_R5G6B5:
1015 switch(getD3DFormat())
1016 {
1017 case D3DFMT_L8:
1018 for(int y = 0; y < height; y++)
1019 {
1020 for(int x = 0; x < height; x++)
1021 {
1022 unsigned char red = source[x * 2 + 1] & 0xF8;
1023 dest[x] = red | (red >> 5);
1024 }
1025
1026 source += sourceLock.Pitch;
1027 dest += destLock.Pitch;
1028 }
1029 break;
1030 default:
1031 UNREACHABLE();
1032 }
1033 break;
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001034 default:
1035 UNREACHABLE();
1036 }
1037
1038 image->dirty = true;
1039 mDirtyMetaData = true;
1040 }
1041
1042 image->surface->UnlockRect();
1043 surface->UnlockRect();
1044 surface->Release();
1045}
1046
enne@chromium.org0fa74632010-09-21 16:18:52 +00001047D3DFORMAT Texture::getD3DFormat() const
1048{
1049 return selectFormat(getFormat(), mType);
1050}
1051
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001052IDirect3DBaseTexture9 *Texture::getTexture()
1053{
1054 if (!isComplete())
1055 {
1056 return NULL;
1057 }
1058
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001059 if (mDirtyMetaData)
1060 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001061 mBaseTexture = createTexture();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001062 mIsRenderable = false;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001063 }
1064
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001065 if (mDirtyMetaData || dirtyImageData())
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001066 {
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001067 updateTexture();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001068 }
1069
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001070 mDirtyMetaData = false;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001071 ASSERT(!dirtyImageData());
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001072
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001073 return mBaseTexture;
1074}
1075
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001076bool Texture::isDirty() const
1077{
1078 return (mDirty || mDirtyMetaData || dirtyImageData());
1079}
1080
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001081// Returns the top-level texture surface as a render target
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001082void Texture::needRenderTarget()
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001083{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001084 if (!mIsRenderable)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001085 {
1086 mBaseTexture = convertToRenderTarget();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001087 mIsRenderable = true;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001088 }
1089
1090 if (dirtyImageData())
1091 {
1092 updateTexture();
1093 }
1094
1095 mDirtyMetaData = false;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001096}
1097
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001098void Texture::dropTexture()
1099{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001100 if (mBaseTexture)
1101 {
1102 mBaseTexture = NULL;
1103 }
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001104
1105 mIsRenderable = false;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001106}
1107
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001108void Texture::pushTexture(IDirect3DBaseTexture9 *newTexture, bool renderable)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001109{
1110 mBaseTexture = newTexture;
1111 mDirtyMetaData = false;
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001112 mIsRenderable = renderable;
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001113 mDirty = true;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001114}
1115
1116
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001117GLint Texture::creationLevels(GLsizei width, GLsizei height, GLint maxlevel) const
1118{
1119 if (isPow2(width) && isPow2(height))
1120 {
1121 return maxlevel;
1122 }
1123 else
1124 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001125 // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1126 return 1;
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001127 }
1128}
1129
1130GLint Texture::creationLevels(GLsizei size, GLint maxlevel) const
1131{
1132 return creationLevels(size, size, maxlevel);
1133}
1134
1135int Texture::levelCount() const
1136{
1137 return mBaseTexture ? mBaseTexture->GetLevelCount() : 0;
1138}
1139
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001140Texture2D::Texture2D(GLuint id) : Texture(id)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001141{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001142 mTexture = NULL;
1143}
1144
1145Texture2D::~Texture2D()
1146{
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001147 mColorbufferProxy.set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001149 if (mTexture)
1150 {
1151 mTexture->Release();
1152 mTexture = NULL;
1153 }
1154}
1155
1156GLenum Texture2D::getTarget() const
1157{
1158 return GL_TEXTURE_2D;
1159}
1160
daniel@transgaming.com01868132010-08-24 19:21:17 +00001161GLenum Texture2D::getFormat() const
1162{
1163 return mImageArray[0].format;
1164}
1165
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001166// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
1167// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels.
1168// Call this when a particular level of the texture must be defined with a specific format, width and height.
1169//
daniel@transgaming.com11cb68c2010-10-15 17:57:40 +00001170// 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 +00001171// 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 +00001172bool Texture2D::redefineTexture(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001173{
1174 bool widthOkay = (mWidth >> level == width);
1175 bool heightOkay = (mHeight >> level == height);
1176
1177 bool sizeOkay = ((widthOkay && heightOkay)
1178 || (widthOkay && mHeight >> level == 0 && height == 1)
1179 || (heightOkay && mWidth >> level == 0 && width == 1));
1180
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001181 bool typeOkay = (type == mType);
1182
1183 bool textureOkay = (sizeOkay && typeOkay && internalFormat == mImageArray[0].format);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001184
1185 if (!textureOkay)
1186 {
1187 TRACE("Redefining 2D texture (%d, 0x%04X, %d, %d => 0x%04X, %d, %d).", level,
1188 mImageArray[0].format, mWidth, mHeight,
1189 internalFormat, width, height);
1190
1191 // Purge all the levels and the texture.
1192
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001193 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001194 {
1195 if (mImageArray[i].surface != NULL)
1196 {
1197 mImageArray[i].dirty = false;
1198
1199 mImageArray[i].surface->Release();
1200 mImageArray[i].surface = NULL;
1201 }
1202 }
1203
1204 if (mTexture != NULL)
1205 {
1206 mTexture->Release();
1207 mTexture = NULL;
1208 dropTexture();
1209 }
1210
1211 mWidth = width << level;
1212 mHeight = height << level;
1213 mImageArray[0].format = internalFormat;
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001214 mType = type;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001215 }
1216
1217 return !textureOkay;
1218}
1219
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001220void 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 +00001221{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001222 redefineTexture(level, internalFormat, width, height, type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001223
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001224 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001225}
1226
daniel@transgaming.com01868132010-08-24 19:21:17 +00001227void Texture2D::setCompressedImage(GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1228{
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001229 redefineTexture(level, internalFormat, width, height, GL_UNSIGNED_BYTE);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001230
1231 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[level]);
1232}
1233
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001234void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1235{
1236 ASSERT(mImageArray[level].surface != NULL);
1237
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001238 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001239 {
1240 IDirect3DSurface9 *destLevel = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001241 HRESULT result = mTexture->GetSurfaceLevel(level, &destLevel);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001242
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001243 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001244
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001245 if (SUCCEEDED(result))
1246 {
1247 Image *img = &mImageArray[level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001248
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001249 RECT sourceRect;
1250 sourceRect.left = xoffset;
1251 sourceRect.top = yoffset;
1252 sourceRect.right = xoffset + width;
1253 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001254
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001255 POINT destPoint;
1256 destPoint.x = xoffset;
1257 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001258
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001259 result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
1260 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001261
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001262 destLevel->Release();
1263
1264 img->dirty = false;
1265 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001266 }
1267}
1268
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001269void 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 +00001270{
daniel@transgaming.com31273552010-08-04 13:42:44 +00001271 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1272 {
1273 commitRect(level, xoffset, yoffset, width, height);
1274 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001275}
1276
daniel@transgaming.com01868132010-08-24 19:21:17 +00001277void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1278{
1279 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1280 {
1281 commitRect(level, xoffset, yoffset, width, height);
1282 }
1283}
1284
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001285void Texture2D::copyImage(GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, RenderbufferStorage *source)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001286{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001287 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1288
1289 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001290 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001291 ERR("Failed to retrieve the render target.");
1292 return error(GL_OUT_OF_MEMORY);
1293 }
1294
1295 bool redefined = redefineTexture(level, internalFormat, width, height, mType);
1296
1297 if (!isRenderableFormat())
1298 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001299 copyNonRenderable(&mImageArray[level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001300 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001301 else
1302 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001303 if (redefined)
1304 {
1305 convertToRenderTarget();
1306 pushTexture(mTexture, true);
1307 }
1308 else
1309 {
1310 needRenderTarget();
1311 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001312
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001313 if (width != 0 && height != 0 && level < levelCount())
1314 {
1315 RECT sourceRect;
1316 sourceRect.left = x;
1317 sourceRect.right = x + width;
1318 sourceRect.top = y;
1319 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001320
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001321 IDirect3DSurface9 *dest;
1322 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001323
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001324 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
1325 dest->Release();
1326 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001327 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001328
1329 mImageArray[level].width = width;
1330 mImageArray[level].height = height;
1331 mImageArray[level].format = internalFormat;
1332}
1333
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001334void 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 +00001335{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001336 if (xoffset + width > mImageArray[level].width || yoffset + height > mImageArray[level].height)
1337 {
1338 return error(GL_INVALID_VALUE);
1339 }
1340
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001341 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1342
1343 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001344 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001345 ERR("Failed to retrieve the render target.");
1346 return error(GL_OUT_OF_MEMORY);
1347 }
1348
1349 bool redefined = redefineTexture(0, mImageArray[0].format, mImageArray[0].width, mImageArray[0].height, mType);
1350
1351 if (!isRenderableFormat())
1352 {
1353 copyNonRenderable(&mImageArray[level], getFormat(), xoffset, yoffset, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001354 }
1355 else
1356 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001357 if (redefined)
1358 {
1359 convertToRenderTarget();
1360 pushTexture(mTexture, true);
1361 }
1362 else
1363 {
1364 needRenderTarget();
1365 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001366
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001367 if (level < levelCount())
1368 {
1369 RECT sourceRect;
1370 sourceRect.left = x;
1371 sourceRect.right = x + width;
1372 sourceRect.top = y;
1373 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001374
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001375 IDirect3DSurface9 *dest;
1376 HRESULT hr = mTexture->GetSurfaceLevel(level, &dest);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001377
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00001378 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0].format, xoffset, yoffset, dest);
1379 dest->Release();
1380 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001381 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001382}
1383
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001384// Tests for GL texture object completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1385bool Texture2D::isComplete() const
1386{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001387 GLsizei width = mImageArray[0].width;
1388 GLsizei height = mImageArray[0].height;
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001389
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001390 if (width <= 0 || height <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001391 {
1392 return false;
1393 }
1394
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001395 bool mipmapping = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001396
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001397 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001398 {
1399 case GL_NEAREST:
1400 case GL_LINEAR:
1401 mipmapping = false;
1402 break;
1403 case GL_NEAREST_MIPMAP_NEAREST:
1404 case GL_LINEAR_MIPMAP_NEAREST:
1405 case GL_NEAREST_MIPMAP_LINEAR:
1406 case GL_LINEAR_MIPMAP_LINEAR:
1407 mipmapping = true;
1408 break;
1409 default: UNREACHABLE();
1410 }
1411
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001412 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1413 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1414 {
1415 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1416 {
1417 return false;
1418 }
1419 }
1420
1421
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001422 if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width))
1423 || (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1424 {
1425 return false;
1426 }
1427
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001428 if (mipmapping)
1429 {
daniel@transgaming.com4c03fa62010-06-24 13:02:16 +00001430 if (!isPow2(width) || !isPow2(height))
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001431 {
1432 return false;
1433 }
1434
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001435 int q = log2(std::max(width, height));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001436
1437 for (int level = 1; level <= q; level++)
1438 {
1439 if (mImageArray[level].format != mImageArray[0].format)
1440 {
1441 return false;
1442 }
1443
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001444 if (mImageArray[level].width != std::max(1, width >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001445 {
1446 return false;
1447 }
1448
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001449 if (mImageArray[level].height != std::max(1, height >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001450 {
1451 return false;
1452 }
1453 }
1454 }
1455
1456 return true;
1457}
1458
daniel@transgaming.com01868132010-08-24 19:21:17 +00001459bool Texture2D::isCompressed() const
1460{
1461 return IsCompressed(getFormat());
1462}
1463
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001464// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001465IDirect3DBaseTexture9 *Texture2D::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001466{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001467 IDirect3DTexture9 *texture;
1468
1469 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001470 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001471
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001472 HRESULT result = device->CreateTexture(mWidth, mHeight, creationLevels(mWidth, mHeight, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001473
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001474 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001475 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001476 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001477 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001478 }
1479
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001480 if (mTexture) mTexture->Release();
1481 mTexture = texture;
1482 return texture;
1483}
1484
1485void Texture2D::updateTexture()
1486{
1487 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001488
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001489 int levels = levelCount();
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001490
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001491 for (int level = 0; level < levels; level++)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001492 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001493 if (mImageArray[level].dirty)
1494 {
1495 IDirect3DSurface9 *levelSurface = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001496 HRESULT result = mTexture->GetSurfaceLevel(level, &levelSurface);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001497
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001498 ASSERT(SUCCEEDED(result));
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001499
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001500 if (SUCCEEDED(result))
1501 {
1502 result = device->UpdateSurface(mImageArray[level].surface, NULL, levelSurface, NULL);
1503 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001504
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001505 levelSurface->Release();
1506
1507 mImageArray[level].dirty = false;
1508 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001509 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001510 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001511}
1512
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001513IDirect3DBaseTexture9 *Texture2D::convertToRenderTarget()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001514{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001515 IDirect3DTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001516
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001517 if (mWidth != 0 && mHeight != 0)
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001518 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001519 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001520 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001521 D3DFORMAT format = selectFormat(mImageArray[0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001522
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001523 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 +00001524
1525 if (FAILED(result))
1526 {
1527 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1528 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1529 }
1530
1531 if (mTexture != NULL)
1532 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001533 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001534 for (int i = 0; i < levels; i++)
1535 {
1536 IDirect3DSurface9 *source;
1537 result = mTexture->GetSurfaceLevel(i, &source);
1538
1539 if (FAILED(result))
1540 {
1541 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1542
1543 texture->Release();
1544
1545 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1546 }
1547
1548 IDirect3DSurface9 *dest;
1549 result = texture->GetSurfaceLevel(i, &dest);
1550
1551 if (FAILED(result))
1552 {
1553 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1554
1555 texture->Release();
1556 source->Release();
1557
1558 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1559 }
1560
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001561 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001562 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1563
1564 if (FAILED(result))
1565 {
1566 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1567
1568 texture->Release();
1569 source->Release();
1570 dest->Release();
1571
1572 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1573 }
1574
1575 source->Release();
1576 dest->Release();
1577 }
1578 }
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001579 }
1580
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001581 if (mTexture != NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001582 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001583 mTexture->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001584 }
1585
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001586 mTexture = texture;
1587 return mTexture;
1588}
1589
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001590bool Texture2D::dirtyImageData() const
1591{
1592 int q = log2(std::max(mWidth, mHeight));
1593
1594 for (int i = 0; i <= q; i++)
1595 {
1596 if (mImageArray[i].dirty) return true;
1597 }
1598
1599 return false;
1600}
1601
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001602void Texture2D::generateMipmaps()
1603{
1604 if (!isPow2(mImageArray[0].width) || !isPow2(mImageArray[0].height))
1605 {
1606 return error(GL_INVALID_OPERATION);
1607 }
1608
1609 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
1610 unsigned int q = log2(std::max(mWidth, mHeight));
1611 for (unsigned int i = 1; i <= q; i++)
1612 {
1613 if (mImageArray[i].surface != NULL)
1614 {
1615 mImageArray[i].surface->Release();
1616 mImageArray[i].surface = NULL;
1617 }
1618
1619 mImageArray[i].dirty = false;
1620
1621 mImageArray[i].format = mImageArray[0].format;
1622 mImageArray[i].width = std::max(mImageArray[0].width >> i, 1);
1623 mImageArray[i].height = std::max(mImageArray[0].height >> i, 1);
1624 }
1625
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001626 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001627
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00001628 if (mTexture == NULL)
1629 {
1630 return;
1631 }
1632
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00001633 for (unsigned int i = 1; i <= q; i++)
1634 {
1635 IDirect3DSurface9 *upper = NULL;
1636 IDirect3DSurface9 *lower = NULL;
1637
1638 mTexture->GetSurfaceLevel(i-1, &upper);
1639 mTexture->GetSurfaceLevel(i, &lower);
1640
1641 if (upper != NULL && lower != NULL)
1642 {
1643 getBlitter()->boxFilter(upper, lower);
1644 }
1645
1646 if (upper != NULL) upper->Release();
1647 if (lower != NULL) lower->Release();
1648 }
1649}
1650
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001651Renderbuffer *Texture2D::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001652{
1653 if (target != GL_TEXTURE_2D)
1654 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001655 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001656 }
1657
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001658 if (mColorbufferProxy.get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001659 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001660 mColorbufferProxy.set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001661 }
1662
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001663 return mColorbufferProxy.get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001664}
1665
1666IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
1667{
1668 ASSERT(target == GL_TEXTURE_2D);
1669
1670 needRenderTarget();
1671
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00001672 if (mTexture == NULL)
1673 {
1674 return NULL;
1675 }
1676
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001677 IDirect3DSurface9 *renderTarget = NULL;
1678 mTexture->GetSurfaceLevel(0, &renderTarget);
1679
1680 return renderTarget;
1681}
1682
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001683TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001685 mTexture = NULL;
1686}
1687
1688TextureCubeMap::~TextureCubeMap()
1689{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001690 for (int i = 0; i < 6; i++)
1691 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001692 mFaceProxies[i].set(NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001693 }
1694
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001695 if (mTexture)
1696 {
1697 mTexture->Release();
1698 mTexture = NULL;
1699 }
1700}
1701
1702GLenum TextureCubeMap::getTarget() const
1703{
1704 return GL_TEXTURE_CUBE_MAP;
1705}
1706
daniel@transgaming.com01868132010-08-24 19:21:17 +00001707GLenum TextureCubeMap::getFormat() const
1708{
1709 return mImageArray[0][0].format;
1710}
1711
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001712void 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 +00001713{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001714 setImage(0, 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::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 +00001718{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001719 setImage(1, 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::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 +00001723{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001724 setImage(2, 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::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 +00001728{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001729 setImage(3, 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::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 +00001733{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001734 setImage(4, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001735}
1736
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001737void 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 +00001738{
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00001739 setImage(5, level, internalFormat, width, height, format, type, unpackAlignment, pixels);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001740}
1741
daniel@transgaming.com01868132010-08-24 19:21:17 +00001742void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1743{
1744 redefineTexture(level, internalFormat, width);
1745
1746 Texture::setCompressedImage(width, height, internalFormat, imageSize, pixels, &mImageArray[faceIndex(face)][level]);
1747}
1748
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001749void TextureCubeMap::commitRect(GLenum faceTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1750{
1751 int face = faceIndex(faceTarget);
1752
1753 ASSERT(mImageArray[face][level].surface != NULL);
1754
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001755 if (level < levelCount())
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001756 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001757 IDirect3DSurface9 *destLevel = getCubeMapSurface(face, level);
1758 ASSERT(destLevel != NULL);
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001759
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001760 if (destLevel != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001761 {
1762 Image *img = &mImageArray[face][level];
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001763
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001764 RECT sourceRect;
1765 sourceRect.left = xoffset;
1766 sourceRect.top = yoffset;
1767 sourceRect.right = xoffset + width;
1768 sourceRect.bottom = yoffset + height;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001769
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001770 POINT destPoint;
1771 destPoint.x = xoffset;
1772 destPoint.y = yoffset;
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001773
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001774 HRESULT result = getDevice()->UpdateSurface(img->surface, &sourceRect, destLevel, &destPoint);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001775 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001776
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001777 destLevel->Release();
1778
1779 img->dirty = false;
1780 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001781 }
1782}
1783
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001784void 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 +00001785{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001786 if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com31273552010-08-04 13:42:44 +00001787 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001788 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com31273552010-08-04 13:42:44 +00001789 }
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001790}
1791
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001792void 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 +00001793{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001794 if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
daniel@transgaming.com01868132010-08-24 19:21:17 +00001795 {
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00001796 commitRect(target, level, xoffset, yoffset, width, height);
daniel@transgaming.com01868132010-08-24 19:21:17 +00001797 }
1798}
1799
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001800// 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 +00001801bool TextureCubeMap::isComplete() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001802{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001803 int size = mImageArray[0][0].width;
1804
1805 if (size <= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001806 {
1807 return false;
1808 }
1809
1810 bool mipmapping;
1811
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001812 switch (mMinFilter)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001813 {
1814 case GL_NEAREST:
1815 case GL_LINEAR:
1816 mipmapping = false;
1817 break;
1818 case GL_NEAREST_MIPMAP_NEAREST:
1819 case GL_LINEAR_MIPMAP_NEAREST:
1820 case GL_NEAREST_MIPMAP_LINEAR:
1821 case GL_LINEAR_MIPMAP_LINEAR:
1822 mipmapping = true;
1823 break;
1824 default: UNREACHABLE();
1825 }
1826
1827 for (int face = 0; face < 6; face++)
1828 {
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001829 if (mImageArray[face][0].width != size || mImageArray[face][0].height != size)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001830 {
1831 return false;
1832 }
1833 }
1834
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001835 if ((getFormat() == GL_FLOAT && !getContext()->supportsFloatLinearFilter()) ||
1836 (getFormat() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatLinearFilter()))
1837 {
1838 if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1839 {
1840 return false;
1841 }
1842 }
1843
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001844 if (mipmapping)
1845 {
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001846 if (!isPow2(size) && (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE))
1847 {
1848 return false;
1849 }
1850
daniel@transgaming.com93a81472010-04-20 18:52:58 +00001851 int q = log2(size);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001852
1853 for (int face = 0; face < 6; face++)
1854 {
1855 for (int level = 1; level <= q; level++)
1856 {
1857 if (mImageArray[face][level].format != mImageArray[0][0].format)
1858 {
1859 return false;
1860 }
1861
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001862 if (mImageArray[face][level].width != std::max(1, size >> level))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001863 {
1864 return false;
1865 }
1866
daniel@transgaming.comd99bd452010-04-22 13:35:25 +00001867 ASSERT(mImageArray[face][level].height == mImageArray[face][level].width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001868 }
1869 }
1870 }
1871
1872 return true;
1873}
1874
daniel@transgaming.com01868132010-08-24 19:21:17 +00001875bool TextureCubeMap::isCompressed() const
1876{
1877 return IsCompressed(getFormat());
1878}
1879
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001880// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001881IDirect3DBaseTexture9 *TextureCubeMap::createTexture()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001882{
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001883 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001884 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001885
1886 IDirect3DCubeTexture9 *texture;
1887
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001888 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), 0, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001889
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001890 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001891 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001892 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001893 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001894 }
1895
daniel@transgaming.com00c75962010-03-11 20:36:15 +00001896 if (mTexture) mTexture->Release();
1897
1898 mTexture = texture;
1899 return mTexture;
1900}
1901
1902void TextureCubeMap::updateTexture()
1903{
1904 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905
daniel@transgaming.com29d27002010-03-11 19:41:22 +00001906 for (int face = 0; face < 6; face++)
1907 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001908 int levels = levelCount();
1909 for (int level = 0; level < levels; level++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001910 {
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001911 Image *img = &mImageArray[face][level];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001912
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001913 if (img->dirty)
1914 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001915 IDirect3DSurface9 *levelSurface = getCubeMapSurface(face, level);
1916 ASSERT(levelSurface != NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001917
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001918 if (levelSurface != NULL)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001919 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00001920 HRESULT result = device->UpdateSurface(img->surface, NULL, levelSurface, NULL);
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001921 ASSERT(SUCCEEDED(result));
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001922
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001923 levelSurface->Release();
1924
1925 img->dirty = false;
1926 }
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00001927 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001928 }
1929 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001930}
1931
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001932IDirect3DBaseTexture9 *TextureCubeMap::convertToRenderTarget()
1933{
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001934 IDirect3DCubeTexture9 *texture = NULL;
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001935
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001936 if (mWidth != 0)
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001937 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001938 egl::Display *display = getDisplay();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001939 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00001940 D3DFORMAT format = selectFormat(mImageArray[0][0].format, mType);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001941
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001942 HRESULT result = device->CreateCubeTexture(mWidth, creationLevels(mWidth, 0), D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, &texture, NULL);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001943
1944 if (FAILED(result))
1945 {
1946 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1947 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1948 }
1949
1950 if (mTexture != NULL)
1951 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00001952 int levels = levelCount();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001953 for (int f = 0; f < 6; f++)
1954 {
1955 for (int i = 0; i < levels; i++)
1956 {
1957 IDirect3DSurface9 *source;
1958 result = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &source);
1959
1960 if (FAILED(result))
1961 {
1962 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1963
1964 texture->Release();
1965
1966 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1967 }
1968
1969 IDirect3DSurface9 *dest;
1970 result = texture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(f), i, &dest);
1971
1972 if (FAILED(result))
1973 {
1974 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1975
1976 texture->Release();
1977 source->Release();
1978
1979 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1980 }
1981
daniel@transgaming.comae072af2010-05-05 18:47:28 +00001982 display->endScene();
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00001983 result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1984
1985 if (FAILED(result))
1986 {
1987 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1988
1989 texture->Release();
1990 source->Release();
1991 dest->Release();
1992
1993 return error(GL_OUT_OF_MEMORY, (IDirect3DBaseTexture9*)NULL);
1994 }
1995 }
1996 }
1997 }
daniel@transgaming.com7051b972010-03-21 04:31:07 +00001998 }
1999
2000 if (mTexture != NULL)
2001 {
daniel@transgaming.com7051b972010-03-21 04:31:07 +00002002 mTexture->Release();
2003 }
2004
2005 mTexture = texture;
2006 return mTexture;
2007}
2008
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002009void 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 +00002010{
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002011 redefineTexture(level, internalFormat, width);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002012
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002013 Texture::setImage(width, height, format, type, unpackAlignment, pixels, &mImageArray[face][level]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002014}
daniel@transgaming.com00c75962010-03-11 20:36:15 +00002015
2016unsigned int TextureCubeMap::faceIndex(GLenum face)
2017{
2018 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2019 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2020 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2021 META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2022 META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2023
2024 return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2025}
2026
daniel@transgaming.com842f7a42010-03-21 04:31:03 +00002027bool TextureCubeMap::dirtyImageData() const
2028{
2029 int q = log2(mWidth);
2030
2031 for (int f = 0; f < 6; f++)
2032 {
2033 for (int i = 0; i <= q; i++)
2034 {
2035 if (mImageArray[f][i].dirty) return true;
2036 }
2037 }
2038
2039 return false;
2040}
2041
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002042// While OpenGL doesn't check texture consistency until draw-time, D3D9 requires a complete texture
2043// for render-to-texture (such as CopyTexImage). We have no way of keeping individual inconsistent levels & faces.
2044// Call this when a particular level of the texture must be defined with a specific format, width and height.
2045//
2046// Returns true if the existing texture was unsuitable had to be destroyed. If so, it will also set
2047// a new size for the texture by working backwards from the given size.
2048bool TextureCubeMap::redefineTexture(GLint level, GLenum internalFormat, GLsizei width)
2049{
2050 // Are these settings compatible with level 0?
2051 bool sizeOkay = (mImageArray[0][0].width >> level == width);
2052
2053 bool textureOkay = (sizeOkay && internalFormat == mImageArray[0][0].format);
2054
2055 if (!textureOkay)
2056 {
2057 TRACE("Redefining cube texture (%d, 0x%04X, %d => 0x%04X, %d).", level,
2058 mImageArray[0][0].format, mImageArray[0][0].width,
2059 internalFormat, width);
2060
2061 // Purge all the levels and the texture.
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00002062 for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002063 {
2064 for (int f = 0; f < 6; f++)
2065 {
2066 if (mImageArray[f][i].surface != NULL)
2067 {
2068 mImageArray[f][i].dirty = false;
2069
2070 mImageArray[f][i].surface->Release();
2071 mImageArray[f][i].surface = NULL;
2072 }
2073 }
2074 }
2075
2076 if (mTexture != NULL)
2077 {
2078 mTexture->Release();
2079 mTexture = NULL;
2080 dropTexture();
2081 }
2082
2083 mWidth = width << level;
2084 mImageArray[0][0].width = width << level;
2085 mHeight = width << level;
2086 mImageArray[0][0].height = width << level;
2087
2088 mImageArray[0][0].format = internalFormat;
2089 }
2090
2091 return !textureOkay;
2092}
2093
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002094void 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 +00002095{
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002096 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002097
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002098 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002099 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002100 ERR("Failed to retrieve the render target.");
2101 return error(GL_OUT_OF_MEMORY);
2102 }
2103
2104 unsigned int faceindex = faceIndex(target);
2105 bool redefined = redefineTexture(level, internalFormat, width);
2106
2107 if (!isRenderableFormat())
2108 {
2109 copyNonRenderable(&mImageArray[faceindex][level], internalFormat, 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002110 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00002111 else
2112 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002113 if (redefined)
2114 {
2115 convertToRenderTarget();
2116 pushTexture(mTexture, true);
2117 }
2118 else
2119 {
2120 needRenderTarget();
2121 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002122
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002123 ASSERT(width == height);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002124
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002125 if (width > 0 && level < levelCount())
2126 {
2127 RECT sourceRect;
2128 sourceRect.left = x;
2129 sourceRect.right = x + width;
2130 sourceRect.top = y;
2131 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002132
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002133 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002134
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002135 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, internalFormat, 0, 0, dest);
2136 dest->Release();
2137 }
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002138 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002139
2140 mImageArray[faceindex][level].width = width;
2141 mImageArray[faceindex][level].height = height;
2142 mImageArray[faceindex][level].format = internalFormat;
2143}
2144
2145IDirect3DSurface9 *TextureCubeMap::getCubeMapSurface(unsigned int faceIdentifier, unsigned int level)
2146{
2147 unsigned int faceIndex;
2148
2149 if (faceIdentifier < 6)
2150 {
2151 faceIndex = faceIdentifier;
2152 }
2153 else if (faceIdentifier >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && faceIdentifier <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
2154 {
2155 faceIndex = faceIdentifier - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2156 }
2157 else
2158 {
2159 UNREACHABLE();
2160 faceIndex = 0;
2161 }
2162
2163 if (mTexture == NULL)
2164 {
2165 UNREACHABLE();
2166 return NULL;
2167 }
2168
2169 IDirect3DSurface9 *surface = NULL;
2170
2171 HRESULT hr = mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex), level, &surface);
2172
2173 return (SUCCEEDED(hr)) ? surface : NULL;
2174}
2175
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002176void 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 +00002177{
daniel@transgaming.com3f85fbb2010-10-15 17:58:05 +00002178 GLsizei size = mImageArray[faceIndex(target)][level].width;
daniel@transgaming.com34dc3e82010-04-15 20:45:02 +00002179
2180 if (xoffset + width > size || yoffset + height > size)
2181 {
2182 return error(GL_INVALID_VALUE);
2183 }
2184
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002185 IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2186
2187 if (!renderTarget)
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002188 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002189 ERR("Failed to retrieve the render target.");
2190 return error(GL_OUT_OF_MEMORY);
2191 }
2192
2193 unsigned int faceindex = faceIndex(target);
2194 bool redefined = redefineTexture(0, mImageArray[0][0].format, mImageArray[0][0].width);
2195
2196 if (!isRenderableFormat())
2197 {
2198 copyNonRenderable(&mImageArray[faceindex][level], getFormat(), 0, 0, x, y, width, height, renderTarget);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002199 }
2200 else
2201 {
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002202 if (redefined)
2203 {
2204 convertToRenderTarget();
2205 pushTexture(mTexture, true);
2206 }
2207 else
2208 {
2209 needRenderTarget();
2210 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002211
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002212 if (level < levelCount())
2213 {
2214 RECT sourceRect;
2215 sourceRect.left = x;
2216 sourceRect.right = x + width;
2217 sourceRect.top = y;
2218 sourceRect.bottom = y + height;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002219
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002220 IDirect3DSurface9 *dest = getCubeMapSurface(target, level);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002221
daniel@transgaming.com4c5142c2010-10-15 17:58:27 +00002222 getBlitter()->formatConvert(source->getRenderTarget(), sourceRect, mImageArray[0][0].format, xoffset, yoffset, dest);
2223 dest->Release();
2224 }
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +00002225 }
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002226}
2227
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002228bool TextureCubeMap::isCubeComplete() const
2229{
2230 if (mImageArray[0][0].width == 0)
2231 {
2232 return false;
2233 }
2234
2235 for (unsigned int f = 1; f < 6; f++)
2236 {
2237 if (mImageArray[f][0].width != mImageArray[0][0].width
2238 || mImageArray[f][0].format != mImageArray[0][0].format)
2239 {
2240 return false;
2241 }
2242 }
2243
2244 return true;
2245}
2246
2247void TextureCubeMap::generateMipmaps()
2248{
2249 if (!isPow2(mImageArray[0][0].width) || !isCubeComplete())
2250 {
2251 return error(GL_INVALID_OPERATION);
2252 }
2253
2254 // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2255 unsigned int q = log2(mImageArray[0][0].width);
2256 for (unsigned int f = 0; f < 6; f++)
2257 {
2258 for (unsigned int i = 1; i <= q; i++)
2259 {
2260 if (mImageArray[f][i].surface != NULL)
2261 {
2262 mImageArray[f][i].surface->Release();
2263 mImageArray[f][i].surface = NULL;
2264 }
2265
2266 mImageArray[f][i].dirty = false;
2267
2268 mImageArray[f][i].format = mImageArray[f][0].format;
2269 mImageArray[f][i].width = std::max(mImageArray[f][0].width >> i, 1);
2270 mImageArray[f][i].height = mImageArray[f][i].width;
2271 }
2272 }
2273
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002274 needRenderTarget();
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002275
apatrick@chromium.org9398a6b2010-09-20 19:07:49 +00002276 if (mTexture == NULL)
2277 {
2278 return;
2279 }
2280
daniel@transgaming.com8fd99e22010-04-20 18:52:00 +00002281 for (unsigned int f = 0; f < 6; f++)
2282 {
2283 for (unsigned int i = 1; i <= q; i++)
2284 {
2285 IDirect3DSurface9 *upper = getCubeMapSurface(f, i-1);
2286 IDirect3DSurface9 *lower = getCubeMapSurface(f, i);
2287
2288 if (upper != NULL && lower != NULL)
2289 {
2290 getBlitter()->boxFilter(upper, lower);
2291 }
2292
2293 if (upper != NULL) upper->Release();
2294 if (lower != NULL) lower->Release();
2295 }
2296 }
2297}
2298
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002299Renderbuffer *TextureCubeMap::getColorbuffer(GLenum target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002300{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002301 if (!IsCubemapTextureTarget(target))
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002302 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002303 return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002304 }
2305
2306 unsigned int face = faceIndex(target);
2307
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002308 if (mFaceProxies[face].get() == NULL)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002309 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002310 mFaceProxies[face].set(new Renderbuffer(id(), new TextureColorbufferProxy(this, target)));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002311 }
2312
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00002313 return mFaceProxies[face].get();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002314}
2315
2316IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2317{
daniel@transgaming.com19ffc242010-05-04 03:35:21 +00002318 ASSERT(IsCubemapTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002319
2320 needRenderTarget();
daniel@transgaming.come979ead2010-09-23 18:03:14 +00002321
2322 if (mTexture == NULL)
2323 {
2324 return NULL;
apatrick@chromium.org4d5962c2010-09-20 19:02:30 +00002325 }
2326
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002327 IDirect3DSurface9 *renderTarget = NULL;
2328 mTexture->GetCubeMapSurface(static_cast<D3DCUBEMAP_FACES>(faceIndex(target)), 0, &renderTarget);
2329
2330 return renderTarget;
2331}
2332
2333Texture::TextureColorbufferProxy::TextureColorbufferProxy(Texture *texture, GLenum target)
enne@chromium.org0fa74632010-09-21 16:18:52 +00002334 : Colorbuffer(texture), mTexture(texture), mTarget(target)
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002335{
daniel@transgaming.comedc19182010-10-15 17:57:55 +00002336 ASSERT(IsTextureTarget(target));
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002337}
2338
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002339void Texture::TextureColorbufferProxy::addRef() const
2340{
2341 mTexture->addRef();
2342}
2343
2344void Texture::TextureColorbufferProxy::release() const
2345{
2346 mTexture->release();
2347}
2348
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002349IDirect3DSurface9 *Texture::TextureColorbufferProxy::getRenderTarget()
2350{
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002351 if (mRenderTarget) mRenderTarget->Release();
2352
2353 mRenderTarget = mTexture->getRenderTarget(mTarget);
2354
2355 return mRenderTarget;
2356}
2357
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002358int Texture::TextureColorbufferProxy::getWidth() const
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002359{
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002360 return mTexture->getWidth();
2361}
2362
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002363int Texture::TextureColorbufferProxy::getHeight() const
daniel@transgaming.com866f3182010-05-20 19:28:22 +00002364{
2365 return mTexture->getHeight();
daniel@transgaming.com93a81472010-04-20 18:52:58 +00002366}
2367
daniel@transgaming.com01868132010-08-24 19:21:17 +00002368GLenum Texture::TextureColorbufferProxy::getFormat() const
2369{
2370 return mTexture->getFormat();
2371}
2372
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002373bool Texture::TextureColorbufferProxy::isFloatingPoint() const
2374{
2375 return mTexture->isFloatingPoint();
2376}
2377
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002378}