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.
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.
11
#include "libGLESv2/Texture.h"
18
#include "common/debug.h"
20
#include "libEGL/Display.h"
22
#include "libGLESv2/main.h"
23
#include "libGLESv2/mathutil.h"
24
#include "libGLESv2/utilities.h"
25
#include "libGLESv2/Blit.h"
26
#include "libGLESv2/Framebuffer.h"
30
unsigned int TextureStorage::mCurrentTextureSerial = 1;
32
static D3DFORMAT ConvertTextureFormatType(GLenum format, GLenum type)
34
if (IsDepthTexture(format))
38
else if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
39
format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
43
else if (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE)
47
else if (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
51
else if (type == GL_FLOAT)
53
return D3DFMT_A32B32G32R32F;
55
else if (type == GL_HALF_FLOAT_OES)
57
return D3DFMT_A16B16G16R16F;
59
else if (type == GL_UNSIGNED_BYTE)
61
if (format == GL_LUMINANCE && getContext()->supportsLuminanceTextures())
65
else if (format == GL_LUMINANCE_ALPHA && getContext()->supportsLuminanceAlphaTextures())
69
else if (format == GL_RGB)
71
return D3DFMT_X8R8G8B8;
74
return D3DFMT_A8R8G8B8;
77
return D3DFMT_A8R8G8B8;
80
static bool IsTextureFormatRenderable(D3DFORMAT format)
82
if (format == D3DFMT_INTZ)
96
case D3DFMT_A16B16G16R16F:
97
case D3DFMT_A32B32G32R32F:
106
static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
110
if (d3dfmt == D3DFMT_INTZ)
112
d3dusage |= D3DUSAGE_DEPTHSTENCIL;
114
else if(forceRenderable || (IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
116
d3dusage |= D3DUSAGE_RENDERTARGET;
126
mType = GL_UNSIGNED_BYTE;
132
mD3DPool = D3DPOOL_SYSTEMMEM;
133
mD3DFormat = D3DFMT_UNKNOWN;
144
bool Image::redefine(GLenum format, GLsizei width, GLsizei height, GLenum type, bool forceRelease)
146
if (mWidth != width ||
156
// compute the d3d format that will be used
157
mD3DFormat = ConvertTextureFormatType(mFormat, mType);
171
void Image::createSurface()
178
IDirect3DTexture9 *newTexture = NULL;
179
IDirect3DSurface9 *newSurface = NULL;
180
const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
181
const D3DFORMAT d3dFormat = getD3DFormat();
182
ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
184
if (mWidth != 0 && mHeight != 0)
186
int levelToFetch = 0;
187
GLsizei requestWidth = mWidth;
188
GLsizei requestHeight = mHeight;
189
if (IsCompressed(mFormat) && (mWidth % 4 != 0 || mHeight % 4 != 0))
191
bool isMult4 = false;
192
int upsampleCount = 0;
198
if (requestWidth % 4 == 0 && requestHeight % 4 == 0)
203
levelToFetch = upsampleCount;
206
HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat,
207
poolToUse, &newTexture, NULL);
211
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
212
ERR("Creating image surface failed.");
213
return error(GL_OUT_OF_MEMORY);
216
newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
217
newTexture->Release();
220
mSurface = newSurface;
222
mD3DPool = poolToUse;
225
HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
229
HRESULT result = D3DERR_INVALIDCALL;
233
result = mSurface->LockRect(lockedRect, rect, 0);
234
ASSERT(SUCCEEDED(result));
246
HRESULT result = mSurface->UnlockRect();
247
ASSERT(SUCCEEDED(result));
251
bool Image::isRenderableFormat() const
253
return IsTextureFormatRenderable(getD3DFormat());
256
D3DFORMAT Image::getD3DFormat() const
258
// this should only happen if the image hasn't been redefined first
259
// which would be a bug by the caller
260
ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
265
IDirect3DSurface9 *Image::getSurface()
272
void Image::setManagedSurface(IDirect3DSurface9 *surface)
276
D3DXLoadSurfaceFromSurface(surface, NULL, NULL, mSurface, NULL, NULL, D3DX_FILTER_BOX, 0);
280
D3DSURFACE_DESC desc;
281
surface->GetDesc(&desc);
282
ASSERT(desc.Pool == D3DPOOL_MANAGED);
285
mD3DPool = desc.Pool;
288
void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
290
IDirect3DSurface9 *sourceSurface = getSurface();
292
if (sourceSurface && sourceSurface != destSurface)
297
rect.right = xoffset + width;
298
rect.bottom = yoffset + height;
300
if (mD3DPool == D3DPOOL_MANAGED)
302
HRESULT result = D3DXLoadSurfaceFromSurface(destSurface, NULL, &rect, sourceSurface, NULL, &rect, D3DX_FILTER_BOX, 0);
303
ASSERT(SUCCEEDED(result));
307
// UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
308
POINT point = {rect.left, rect.top};
309
HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point);
310
ASSERT(SUCCEEDED(result));
315
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
316
// into the target pixel rectangle.
317
void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
318
GLint unpackAlignment, const void *input)
323
xoffset + width, yoffset + height
326
D3DLOCKED_RECT locked;
327
HRESULT result = lock(&locked, &lockRect);
333
GLsizei inputPitch = ComputePitch(width, mFormat, type, unpackAlignment);
337
case GL_UNSIGNED_BYTE:
343
loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
347
loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
351
loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
353
case GL_LUMINANCE_ALPHA:
354
loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
357
loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
362
loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
366
loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
370
loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
372
default: UNREACHABLE();
375
case GL_UNSIGNED_SHORT_5_6_5:
379
loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
381
default: UNREACHABLE();
384
case GL_UNSIGNED_SHORT_4_4_4_4:
388
loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
390
default: UNREACHABLE();
393
case GL_UNSIGNED_SHORT_5_5_5_1:
397
loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
399
default: UNREACHABLE();
405
// float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
407
loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
410
loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
412
case GL_LUMINANCE_ALPHA:
413
loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
416
loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
419
loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
421
default: UNREACHABLE();
424
case GL_HALF_FLOAT_OES:
427
// float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
429
loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
432
loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
434
case GL_LUMINANCE_ALPHA:
435
loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
438
loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
441
loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits);
443
default: UNREACHABLE();
446
default: UNREACHABLE();
452
void Image::loadAlphaData(GLsizei width, GLsizei height,
453
int inputPitch, const void *input, size_t outputPitch, void *output) const
455
const unsigned char *source = NULL;
456
unsigned char *dest = NULL;
458
for (int y = 0; y < height; y++)
460
source = static_cast<const unsigned char*>(input) + y * inputPitch;
461
dest = static_cast<unsigned char*>(output) + y * outputPitch;
462
for (int x = 0; x < width; x++)
467
dest[4 * x + 3] = source[x];
472
void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height,
473
int inputPitch, const void *input, size_t outputPitch, void *output) const
475
const unsigned char *source = NULL;
476
unsigned int *dest = NULL;
477
__m128i zeroWide = _mm_setzero_si128();
479
for (int y = 0; y < height; y++)
481
source = static_cast<const unsigned char*>(input) + y * inputPitch;
482
dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
485
// Make output writes aligned
486
for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
488
dest[x] = static_cast<unsigned int>(source[x]) << 24;
491
for (; x + 7 < width; x += 8)
493
__m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
494
// Interleave each byte to 16bit, make the lower byte to zero
495
sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
496
// Interleave each 16bit to 32bit, make the lower 16bit to zero
497
__m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
498
__m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
500
_mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
501
_mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
504
// Handle the remainder
505
for (; x < width; x++)
507
dest[x] = static_cast<unsigned int>(source[x]) << 24;
512
void Image::loadAlphaFloatData(GLsizei width, GLsizei height,
513
int inputPitch, const void *input, size_t outputPitch, void *output) const
515
const float *source = NULL;
518
for (int y = 0; y < height; y++)
520
source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
521
dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
522
for (int x = 0; x < width; x++)
527
dest[4 * x + 3] = source[x];
532
void Image::loadAlphaHalfFloatData(GLsizei width, GLsizei height,
533
int inputPitch, const void *input, size_t outputPitch, void *output) const
535
const unsigned short *source = NULL;
536
unsigned short *dest = NULL;
538
for (int y = 0; y < height; y++)
540
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
541
dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
542
for (int x = 0; x < width; x++)
547
dest[4 * x + 3] = source[x];
552
void Image::loadLuminanceData(GLsizei width, GLsizei height,
553
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
555
const unsigned char *source = NULL;
556
unsigned char *dest = NULL;
558
for (int y = 0; y < height; y++)
560
source = static_cast<const unsigned char*>(input) + y * inputPitch;
561
dest = static_cast<unsigned char*>(output) + y * outputPitch;
563
if (!native) // BGRA8 destination format
565
for (int x = 0; x < width; x++)
567
dest[4 * x + 0] = source[x];
568
dest[4 * x + 1] = source[x];
569
dest[4 * x + 2] = source[x];
570
dest[4 * x + 3] = 0xFF;
573
else // L8 destination format
575
memcpy(dest, source, width);
580
void Image::loadLuminanceFloatData(GLsizei width, GLsizei height,
581
int inputPitch, const void *input, size_t outputPitch, void *output) const
583
const float *source = NULL;
586
for (int y = 0; y < height; y++)
588
source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
589
dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
590
for (int x = 0; x < width; x++)
592
dest[4 * x + 0] = source[x];
593
dest[4 * x + 1] = source[x];
594
dest[4 * x + 2] = source[x];
595
dest[4 * x + 3] = 1.0f;
600
void Image::loadLuminanceHalfFloatData(GLsizei width, GLsizei height,
601
int inputPitch, const void *input, size_t outputPitch, void *output) const
603
const unsigned short *source = NULL;
604
unsigned short *dest = NULL;
606
for (int y = 0; y < height; y++)
608
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
609
dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
610
for (int x = 0; x < width; x++)
612
dest[4 * x + 0] = source[x];
613
dest[4 * x + 1] = source[x];
614
dest[4 * x + 2] = source[x];
615
dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
620
void Image::loadLuminanceAlphaData(GLsizei width, GLsizei height,
621
int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const
623
const unsigned char *source = NULL;
624
unsigned char *dest = NULL;
626
for (int y = 0; y < height; y++)
628
source = static_cast<const unsigned char*>(input) + y * inputPitch;
629
dest = static_cast<unsigned char*>(output) + y * outputPitch;
631
if (!native) // BGRA8 destination format
633
for (int x = 0; x < width; x++)
635
dest[4 * x + 0] = source[2*x+0];
636
dest[4 * x + 1] = source[2*x+0];
637
dest[4 * x + 2] = source[2*x+0];
638
dest[4 * x + 3] = source[2*x+1];
643
memcpy(dest, source, width * 2);
648
void Image::loadLuminanceAlphaFloatData(GLsizei width, GLsizei height,
649
int inputPitch, const void *input, size_t outputPitch, void *output) const
651
const float *source = NULL;
654
for (int y = 0; y < height; y++)
656
source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
657
dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
658
for (int x = 0; x < width; x++)
660
dest[4 * x + 0] = source[2*x+0];
661
dest[4 * x + 1] = source[2*x+0];
662
dest[4 * x + 2] = source[2*x+0];
663
dest[4 * x + 3] = source[2*x+1];
668
void Image::loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height,
669
int inputPitch, const void *input, size_t outputPitch, void *output) const
671
const unsigned short *source = NULL;
672
unsigned short *dest = NULL;
674
for (int y = 0; y < height; y++)
676
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
677
dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
678
for (int x = 0; x < width; x++)
680
dest[4 * x + 0] = source[2*x+0];
681
dest[4 * x + 1] = source[2*x+0];
682
dest[4 * x + 2] = source[2*x+0];
683
dest[4 * x + 3] = source[2*x+1];
688
void Image::loadRGBUByteData(GLsizei width, GLsizei height,
689
int inputPitch, const void *input, size_t outputPitch, void *output) const
691
const unsigned char *source = NULL;
692
unsigned char *dest = NULL;
694
for (int y = 0; y < height; y++)
696
source = static_cast<const unsigned char*>(input) + y * inputPitch;
697
dest = static_cast<unsigned char*>(output) + y * outputPitch;
698
for (int x = 0; x < width; x++)
700
dest[4 * x + 0] = source[x * 3 + 2];
701
dest[4 * x + 1] = source[x * 3 + 1];
702
dest[4 * x + 2] = source[x * 3 + 0];
703
dest[4 * x + 3] = 0xFF;
708
void Image::loadRGB565Data(GLsizei width, GLsizei height,
709
int inputPitch, const void *input, size_t outputPitch, void *output) const
711
const unsigned short *source = NULL;
712
unsigned char *dest = NULL;
714
for (int y = 0; y < height; y++)
716
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
717
dest = static_cast<unsigned char*>(output) + y * outputPitch;
718
for (int x = 0; x < width; x++)
720
unsigned short rgba = source[x];
721
dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
722
dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
723
dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
724
dest[4 * x + 3] = 0xFF;
729
void Image::loadRGBFloatData(GLsizei width, GLsizei height,
730
int inputPitch, const void *input, size_t outputPitch, void *output) const
732
const float *source = NULL;
735
for (int y = 0; y < height; y++)
737
source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
738
dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
739
for (int x = 0; x < width; x++)
741
dest[4 * x + 0] = source[x * 3 + 0];
742
dest[4 * x + 1] = source[x * 3 + 1];
743
dest[4 * x + 2] = source[x * 3 + 2];
744
dest[4 * x + 3] = 1.0f;
749
void Image::loadRGBHalfFloatData(GLsizei width, GLsizei height,
750
int inputPitch, const void *input, size_t outputPitch, void *output) const
752
const unsigned short *source = NULL;
753
unsigned short *dest = NULL;
755
for (int y = 0; y < height; y++)
757
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
758
dest = reinterpret_cast<unsigned short*>(static_cast<unsigned char*>(output) + y * outputPitch);
759
for (int x = 0; x < width; x++)
761
dest[4 * x + 0] = source[x * 3 + 0];
762
dest[4 * x + 1] = source[x * 3 + 1];
763
dest[4 * x + 2] = source[x * 3 + 2];
764
dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1
769
void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height,
770
int inputPitch, const void *input, size_t outputPitch, void *output) const
772
const unsigned int *source = NULL;
773
unsigned int *dest = NULL;
774
__m128i brMask = _mm_set1_epi32(0x00ff00ff);
776
for (int y = 0; y < height; y++)
778
source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
779
dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
782
// Make output writes aligned
783
for (x = 0; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
785
unsigned int rgba = source[x];
786
dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
789
for (; x + 3 < width; x += 4)
791
__m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
792
// Mask out g and a, which don't change
793
__m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
795
__m128i brComponents = _mm_and_si128(sourceData, brMask);
797
__m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
798
__m128i result = _mm_or_si128(gaComponents, brSwapped);
799
_mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
802
// Perform leftover writes
803
for (; x < width; x++)
805
unsigned int rgba = source[x];
806
dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
811
void Image::loadRGBAUByteData(GLsizei width, GLsizei height,
812
int inputPitch, const void *input, size_t outputPitch, void *output) const
814
const unsigned int *source = NULL;
815
unsigned int *dest = NULL;
816
for (int y = 0; y < height; y++)
818
source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
819
dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
821
for (int x = 0; x < width; x++)
823
unsigned int rgba = source[x];
824
dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
829
void Image::loadRGBA4444Data(GLsizei width, GLsizei height,
830
int inputPitch, const void *input, size_t outputPitch, void *output) const
832
const unsigned short *source = NULL;
833
unsigned char *dest = NULL;
835
for (int y = 0; y < height; y++)
837
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
838
dest = static_cast<unsigned char*>(output) + y * outputPitch;
839
for (int x = 0; x < width; x++)
841
unsigned short rgba = source[x];
842
dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4);
843
dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8);
844
dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12);
845
dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0);
850
void Image::loadRGBA5551Data(GLsizei width, GLsizei height,
851
int inputPitch, const void *input, size_t outputPitch, void *output) const
853
const unsigned short *source = NULL;
854
unsigned char *dest = NULL;
856
for (int y = 0; y < height; y++)
858
source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
859
dest = static_cast<unsigned char*>(output) + y * outputPitch;
860
for (int x = 0; x < width; x++)
862
unsigned short rgba = source[x];
863
dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3);
864
dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8);
865
dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
866
dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0;
871
void Image::loadRGBAFloatData(GLsizei width, GLsizei height,
872
int inputPitch, const void *input, size_t outputPitch, void *output) const
874
const float *source = NULL;
877
for (int y = 0; y < height; y++)
879
source = reinterpret_cast<const float*>(static_cast<const unsigned char*>(input) + y * inputPitch);
880
dest = reinterpret_cast<float*>(static_cast<unsigned char*>(output) + y * outputPitch);
881
memcpy(dest, source, width * 16);
885
void Image::loadRGBAHalfFloatData(GLsizei width, GLsizei height,
886
int inputPitch, const void *input, size_t outputPitch, void *output) const
888
const unsigned char *source = NULL;
889
unsigned char *dest = NULL;
891
for (int y = 0; y < height; y++)
893
source = static_cast<const unsigned char*>(input) + y * inputPitch;
894
dest = static_cast<unsigned char*>(output) + y * outputPitch;
895
memcpy(dest, source, width * 8);
899
void Image::loadBGRAData(GLsizei width, GLsizei height,
900
int inputPitch, const void *input, size_t outputPitch, void *output) const
902
const unsigned char *source = NULL;
903
unsigned char *dest = NULL;
905
for (int y = 0; y < height; y++)
907
source = static_cast<const unsigned char*>(input) + y * inputPitch;
908
dest = static_cast<unsigned char*>(output) + y * outputPitch;
909
memcpy(dest, source, width*4);
913
void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
915
ASSERT(xoffset % 4 == 0);
916
ASSERT(yoffset % 4 == 0);
920
xoffset + width, yoffset + height
923
D3DLOCKED_RECT locked;
924
HRESULT result = lock(&locked, &lockRect);
930
GLsizei inputSize = ComputeCompressedSize(width, height, mFormat);
931
GLsizei inputPitch = ComputeCompressedPitch(width, mFormat);
932
int rows = inputSize / inputPitch;
933
for (int i = 0; i < rows; ++i)
935
memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
941
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
942
void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
944
IDirect3DDevice9 *device = getDevice();
945
IDirect3DSurface9 *renderTargetData = NULL;
946
D3DSURFACE_DESC description;
947
renderTarget->GetDesc(&description);
949
HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
953
ERR("Could not create matching destination surface.");
954
return error(GL_OUT_OF_MEMORY);
957
result = device->GetRenderTargetData(renderTarget, renderTargetData);
961
ERR("GetRenderTargetData unexpectedly failed.");
962
renderTargetData->Release();
963
return error(GL_OUT_OF_MEMORY);
966
RECT sourceRect = {x, y, x + width, y + height};
967
RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
969
if (isRenderableFormat())
971
result = D3DXLoadSurfaceFromSurface(getSurface(), NULL, &destRect, renderTargetData, NULL, &sourceRect, D3DX_FILTER_BOX, 0);
975
ERR("Copying surfaces unexpectedly failed.");
976
renderTargetData->Release();
977
return error(GL_OUT_OF_MEMORY);
982
D3DLOCKED_RECT sourceLock = {0};
983
result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
987
ERR("Failed to lock the source surface (rectangle might be invalid).");
988
renderTargetData->Release();
989
return error(GL_OUT_OF_MEMORY);
992
D3DLOCKED_RECT destLock = {0};
993
result = lock(&destLock, &destRect);
997
ERR("Failed to lock the destination surface (rectangle might be invalid).");
998
renderTargetData->UnlockRect();
999
renderTargetData->Release();
1000
return error(GL_OUT_OF_MEMORY);
1003
if (destLock.pBits && sourceLock.pBits)
1005
unsigned char *source = (unsigned char*)sourceLock.pBits;
1006
unsigned char *dest = (unsigned char*)destLock.pBits;
1008
switch (description.Format)
1010
case D3DFMT_X8R8G8B8:
1011
case D3DFMT_A8R8G8B8:
1012
switch(getD3DFormat())
1015
for(int y = 0; y < height; y++)
1017
for(int x = 0; x < width; x++)
1019
dest[x] = source[x * 4 + 2];
1022
source += sourceLock.Pitch;
1023
dest += destLock.Pitch;
1027
for(int y = 0; y < height; y++)
1029
for(int x = 0; x < width; x++)
1031
dest[x * 2 + 0] = source[x * 4 + 2];
1032
dest[x * 2 + 1] = source[x * 4 + 3];
1035
source += sourceLock.Pitch;
1036
dest += destLock.Pitch;
1044
switch(getD3DFormat())
1047
for(int y = 0; y < height; y++)
1049
for(int x = 0; x < width; x++)
1051
unsigned char red = source[x * 2 + 1] & 0xF8;
1052
dest[x] = red | (red >> 5);
1055
source += sourceLock.Pitch;
1056
dest += destLock.Pitch;
1063
case D3DFMT_A1R5G5B5:
1064
switch(getD3DFormat())
1067
for(int y = 0; y < height; y++)
1069
for(int x = 0; x < width; x++)
1071
unsigned char red = source[x * 2 + 1] & 0x7C;
1072
dest[x] = (red << 1) | (red >> 4);
1075
source += sourceLock.Pitch;
1076
dest += destLock.Pitch;
1080
for(int y = 0; y < height; y++)
1082
for(int x = 0; x < width; x++)
1084
unsigned char red = source[x * 2 + 1] & 0x7C;
1085
dest[x * 2 + 0] = (red << 1) | (red >> 4);
1086
dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
1089
source += sourceLock.Pitch;
1090
dest += destLock.Pitch;
1103
renderTargetData->UnlockRect();
1106
renderTargetData->Release();
1111
TextureStorage::TextureStorage(DWORD usage)
1113
mD3DPool(getDisplay()->getTexturePool(usage)),
1114
mTextureSerial(issueTextureSerial())
1118
TextureStorage::~TextureStorage()
1122
bool TextureStorage::isRenderTarget() const
1124
return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
1127
bool TextureStorage::isManaged() const
1129
return (mD3DPool == D3DPOOL_MANAGED);
1132
D3DPOOL TextureStorage::getPool() const
1137
DWORD TextureStorage::getUsage() const
1142
unsigned int TextureStorage::getTextureSerial() const
1144
return mTextureSerial;
1147
unsigned int TextureStorage::issueTextureSerial()
1149
return mCurrentTextureSerial++;
1152
Texture::Texture(GLuint id) : RefCountObject(id)
1154
mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
1155
mMagFilter = GL_LINEAR;
1158
mDirtyParameters = true;
1161
mDirtyImages = true;
1170
// Returns true on successful filter state update (valid enum parameter)
1171
bool Texture::setMinFilter(GLenum filter)
1177
case GL_NEAREST_MIPMAP_NEAREST:
1178
case GL_LINEAR_MIPMAP_NEAREST:
1179
case GL_NEAREST_MIPMAP_LINEAR:
1180
case GL_LINEAR_MIPMAP_LINEAR:
1182
if (mMinFilter != filter)
1184
mMinFilter = filter;
1185
mDirtyParameters = true;
1194
// Returns true on successful filter state update (valid enum parameter)
1195
bool Texture::setMagFilter(GLenum filter)
1202
if (mMagFilter != filter)
1204
mMagFilter = filter;
1205
mDirtyParameters = true;
1214
// Returns true on successful wrap state update (valid enum parameter)
1215
bool Texture::setWrapS(GLenum wrap)
1220
case GL_CLAMP_TO_EDGE:
1221
case GL_MIRRORED_REPEAT:
1226
mDirtyParameters = true;
1235
// Returns true on successful wrap state update (valid enum parameter)
1236
bool Texture::setWrapT(GLenum wrap)
1241
case GL_CLAMP_TO_EDGE:
1242
case GL_MIRRORED_REPEAT:
1247
mDirtyParameters = true;
1256
// Returns true on successful usage state update (valid enum parameter)
1257
bool Texture::setUsage(GLenum usage)
1262
case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
1270
GLenum Texture::getMinFilter() const
1275
GLenum Texture::getMagFilter() const
1280
GLenum Texture::getWrapS() const
1285
GLenum Texture::getWrapT() const
1290
GLenum Texture::getUsage() const
1295
void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image)
1299
image->loadData(0, 0, image->getWidth(), image->getHeight(), image->getType(), unpackAlignment, pixels);
1300
mDirtyImages = true;
1304
void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image)
1308
image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels);
1309
mDirtyImages = true;
1313
bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image)
1317
image->loadData(xoffset, yoffset, width, height, type, unpackAlignment, pixels);
1318
mDirtyImages = true;
1324
bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image)
1328
image->loadCompressedData(xoffset, yoffset, width, height, pixels);
1329
mDirtyImages = true;
1335
IDirect3DBaseTexture9 *Texture::getTexture()
1337
if (!isSamplerComplete())
1342
// ensure the underlying texture is created
1343
if (getStorage(false) == NULL)
1350
return getBaseTexture();
1353
bool Texture::hasDirtyParameters() const
1355
return mDirtyParameters;
1358
bool Texture::hasDirtyImages() const
1360
return mDirtyImages;
1363
void Texture::resetDirty()
1365
mDirtyParameters = false;
1366
mDirtyImages = false;
1369
unsigned int Texture::getTextureSerial()
1371
TextureStorage *texture = getStorage(false);
1372
return texture ? texture->getTextureSerial() : 0;
1375
unsigned int Texture::getRenderTargetSerial(GLenum target)
1377
TextureStorage *texture = getStorage(true);
1378
return texture ? texture->getRenderTargetSerial(target) : 0;
1381
bool Texture::isImmutable() const
1386
GLint Texture::creationLevels(GLsizei width, GLsizei height) const
1388
if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture())
1390
return 0; // Maximum number of levels
1394
// OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
1399
GLint Texture::creationLevels(GLsizei size) const
1401
return creationLevels(size, size);
1404
int Texture::levelCount() const
1406
return getBaseTexture() ? getBaseTexture()->GetLevelCount() : 0;
1409
Blit *Texture::getBlitter()
1411
Context *context = getContext();
1412
return context->getBlitter();
1415
bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
1423
result = D3DXLoadSurfaceFromSurface(dest, NULL, NULL, source, NULL, NULL, D3DX_FILTER_BOX, 0);
1427
egl::Display *display = getDisplay();
1428
IDirect3DDevice9 *device = display->getDevice();
1430
display->endScene();
1431
result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
1436
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1444
TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial())
1446
mTexture = surfaceTexture;
1449
TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height)
1450
: TextureStorage(usage), mRenderTargetSerial(RenderbufferStorage::issueSerial())
1453
// if the width or height is not positive this should be treated as an incomplete texture
1454
// we handle that here by skipping the d3d texture creation
1455
if (width > 0 && height > 0)
1457
IDirect3DDevice9 *device = getDevice();
1458
HRESULT result = device->CreateTexture(width, height, levels, getUsage(), format, getPool(), &mTexture, NULL);
1462
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
1463
error(GL_OUT_OF_MEMORY);
1468
TextureStorage2D::~TextureStorage2D()
1472
mTexture->Release();
1476
// Increments refcount on surface.
1477
// caller must Release() the returned surface
1478
IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level)
1480
IDirect3DSurface9 *surface = NULL;
1484
HRESULT result = mTexture->GetSurfaceLevel(level, &surface);
1485
ASSERT(SUCCEEDED(result));
1491
IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const
1496
unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const
1498
return mRenderTargetSerial;
1501
Texture2D::Texture2D(GLuint id) : Texture(id)
1505
mColorbufferProxy = NULL;
1509
Texture2D::~Texture2D()
1511
mColorbufferProxy = NULL;
1518
mSurface->setBoundTexture(NULL);
1523
// We need to maintain a count of references to renderbuffers acting as
1524
// proxies for this texture, so that we do not attempt to use a pointer
1525
// to a renderbuffer proxy which has been deleted.
1526
void Texture2D::addProxyRef(const Renderbuffer *proxy)
1531
void Texture2D::releaseProxy(const Renderbuffer *proxy)
1536
if (mProxyRefs == 0)
1537
mColorbufferProxy = NULL;
1540
GLenum Texture2D::getTarget() const
1542
return GL_TEXTURE_2D;
1545
GLsizei Texture2D::getWidth(GLint level) const
1547
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1548
return mImageArray[level].getWidth();
1553
GLsizei Texture2D::getHeight(GLint level) const
1555
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1556
return mImageArray[level].getHeight();
1561
GLenum Texture2D::getInternalFormat(GLint level) const
1563
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1564
return mImageArray[level].getFormat();
1569
D3DFORMAT Texture2D::getD3DFormat(GLint level) const
1571
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1572
return mImageArray[level].getD3DFormat();
1574
return D3DFMT_UNKNOWN;
1577
void Texture2D::redefineImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
1581
bool redefined = mImageArray[level].redefine(format, width, height, type, false);
1583
if (mTexStorage && redefined)
1585
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1587
mImageArray[i].markDirty();
1592
mDirtyImages = true;
1596
void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
1598
redefineImage(level, format, width, height, type);
1600
Texture::setImage(unpackAlignment, pixels, &mImageArray[level]);
1603
void Texture2D::bindTexImage(egl::Surface *surface)
1609
switch(surface->getFormat())
1611
case D3DFMT_A8R8G8B8:
1614
case D3DFMT_X8R8G8B8:
1622
mImageArray[0].redefine(format, surface->getWidth(), surface->getHeight(), GL_UNSIGNED_BYTE, true);
1625
mTexStorage = new TextureStorage2D(surface->getOffscreenTexture());
1627
mDirtyImages = true;
1629
mSurface->setBoundTexture(this);
1632
void Texture2D::releaseTexImage()
1636
mSurface->setBoundTexture(NULL);
1645
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1647
mImageArray[i].redefine(GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, true);
1652
void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
1654
redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
1656
Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]);
1659
void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
1661
ASSERT(mImageArray[level].getSurface() != NULL);
1663
if (level < levelCount())
1665
IDirect3DSurface9 *destLevel = mTexStorage->getSurfaceLevel(level);
1669
Image *image = &mImageArray[level];
1670
image->updateSurface(destLevel, xoffset, yoffset, width, height);
1672
destLevel->Release();
1678
void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
1680
if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level]))
1682
commitRect(level, xoffset, yoffset, width, height);
1686
void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
1688
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level]))
1690
commitRect(level, xoffset, yoffset, width, height);
1694
void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1696
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1700
ERR("Failed to retrieve the render target.");
1701
return error(GL_OUT_OF_MEMORY);
1704
redefineImage(level, format, width, height, GL_UNSIGNED_BYTE);
1706
if (!mImageArray[level].isRenderableFormat())
1708
mImageArray[level].copy(0, 0, x, y, width, height, renderTarget);
1709
mDirtyImages = true;
1713
if (!mTexStorage || !mTexStorage->isRenderTarget())
1715
convertToRenderTarget();
1718
mImageArray[level].markClean();
1720
if (width != 0 && height != 0 && level < levelCount())
1723
sourceRect.left = x;
1724
sourceRect.right = x + width;
1726
sourceRect.bottom = y + height;
1728
IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
1732
getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
1738
renderTarget->Release();
1741
void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
1743
if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight())
1745
return error(GL_INVALID_VALUE);
1748
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
1752
ERR("Failed to retrieve the render target.");
1753
return error(GL_OUT_OF_MEMORY);
1756
if (!mImageArray[level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
1758
mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget);
1759
mDirtyImages = true;
1763
if (!mTexStorage || !mTexStorage->isRenderTarget())
1765
convertToRenderTarget();
1770
if (level < levelCount())
1773
sourceRect.left = x;
1774
sourceRect.right = x + width;
1776
sourceRect.bottom = y + height;
1779
IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
1783
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0].getFormat(), xoffset, yoffset, dest);
1789
renderTarget->Release();
1792
void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
1794
GLenum format = gl::ExtractFormat(internalformat);
1795
GLenum type = gl::ExtractType(internalformat);
1796
D3DFORMAT d3dfmt = ConvertTextureFormatType(format, type);
1797
DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
1800
mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
1803
for (int level = 0; level < levels; level++)
1805
mImageArray[level].redefine(format, width, height, type, true);
1806
width = std::max(1, width >> 1);
1807
height = std::max(1, height >> 1);
1810
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1812
mImageArray[level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
1815
if (mTexStorage->isManaged())
1817
int levels = levelCount();
1819
for (int level = 0; level < levels; level++)
1821
IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level);
1822
mImageArray[level].setManagedSurface(surface);
1827
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
1828
bool Texture2D::isSamplerComplete() const
1830
GLsizei width = mImageArray[0].getWidth();
1831
GLsizei height = mImageArray[0].getHeight();
1833
if (width <= 0 || height <= 0)
1838
bool mipmapping = false;
1846
case GL_NEAREST_MIPMAP_NEAREST:
1847
case GL_LINEAR_MIPMAP_NEAREST:
1848
case GL_NEAREST_MIPMAP_LINEAR:
1849
case GL_LINEAR_MIPMAP_LINEAR:
1852
default: UNREACHABLE();
1855
if ((getInternalFormat(0) == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
1856
(getInternalFormat(0) == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
1858
if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
1864
bool npotSupport = getContext()->supportsNonPower2Texture();
1868
if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) ||
1869
(getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height)))
1879
if (!isPow2(width) || !isPow2(height))
1885
if (!isMipmapComplete())
1894
// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
1895
bool Texture2D::isMipmapComplete() const
1902
GLsizei width = mImageArray[0].getWidth();
1903
GLsizei height = mImageArray[0].getHeight();
1905
if (width <= 0 || height <= 0)
1910
int q = log2(std::max(width, height));
1912
for (int level = 1; level <= q; level++)
1914
if (mImageArray[level].getFormat() != mImageArray[0].getFormat())
1919
if (mImageArray[level].getType() != mImageArray[0].getType())
1924
if (mImageArray[level].getWidth() != std::max(1, width >> level))
1929
if (mImageArray[level].getHeight() != std::max(1, height >> level))
1938
bool Texture2D::isCompressed(GLint level) const
1940
return IsCompressed(getInternalFormat(level));
1943
bool Texture2D::isDepth(GLint level) const
1945
return IsDepthTexture(getInternalFormat(level));
1948
IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const
1950
return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
1953
// Constructs a Direct3D 9 texture resource from the texture images
1954
void Texture2D::createTexture()
1956
GLsizei width = mImageArray[0].getWidth();
1957
GLsizei height = mImageArray[0].getHeight();
1958
GLint levels = creationLevels(width, height);
1959
D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat();
1960
DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
1963
mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
1965
if (mTexStorage->isManaged())
1967
int levels = levelCount();
1969
for (int level = 0; level < levels; level++)
1971
IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level);
1972
mImageArray[level].setManagedSurface(surface);
1976
mDirtyImages = true;
1979
void Texture2D::updateTexture()
1981
int levels = levelCount();
1983
for (int level = 0; level < levels; level++)
1985
Image *image = &mImageArray[level];
1987
if (image->isDirty())
1989
commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight());
1994
void Texture2D::convertToRenderTarget()
1996
TextureStorage2D *newTexStorage = NULL;
1998
if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0)
2000
GLsizei width = mImageArray[0].getWidth();
2001
GLsizei height = mImageArray[0].getHeight();
2002
GLint levels = creationLevels(width, height);
2003
D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat();
2004
DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true);
2006
newTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height);
2008
if (mTexStorage != NULL)
2010
int levels = levelCount();
2011
for (int i = 0; i < levels; i++)
2013
IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i);
2014
IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i);
2016
if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
2018
delete newTexStorage;
2019
if (source) source->Release();
2020
if (dest) dest->Release();
2021
return error(GL_OUT_OF_MEMORY);
2024
if (source) source->Release();
2025
if (dest) dest->Release();
2031
mTexStorage = newTexStorage;
2033
mDirtyImages = true;
2036
void Texture2D::generateMipmaps()
2038
if (!getContext()->supportsNonPower2Texture())
2040
if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight()))
2042
return error(GL_INVALID_OPERATION);
2046
// Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2047
unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight()));
2048
for (unsigned int i = 1; i <= q; i++)
2050
redefineImage(i, mImageArray[0].getFormat(),
2051
std::max(mImageArray[0].getWidth() >> i, 1),
2052
std::max(mImageArray[0].getHeight() >> i, 1),
2053
mImageArray[0].getType());
2056
if (mTexStorage && mTexStorage->isRenderTarget())
2058
for (unsigned int i = 1; i <= q; i++)
2060
IDirect3DSurface9 *upper = mTexStorage->getSurfaceLevel(i - 1);
2061
IDirect3DSurface9 *lower = mTexStorage->getSurfaceLevel(i);
2063
if (upper != NULL && lower != NULL)
2065
getBlitter()->boxFilter(upper, lower);
2068
if (upper != NULL) upper->Release();
2069
if (lower != NULL) lower->Release();
2071
mImageArray[i].markClean();
2076
for (unsigned int i = 1; i <= q; i++)
2078
if (mImageArray[i].getSurface() == NULL)
2080
return error(GL_OUT_OF_MEMORY);
2083
if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[i].getSurface(), NULL, NULL, mImageArray[i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
2085
ERR(" failed to load filter %d to %d.", i - 1, i);
2088
mImageArray[i].markDirty();
2093
Renderbuffer *Texture2D::getRenderbuffer(GLenum target)
2095
if (target != GL_TEXTURE_2D)
2097
return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2100
if (mColorbufferProxy == NULL)
2102
mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture2D(this, target));
2105
return mColorbufferProxy;
2108
// Increments refcount on surface.
2109
// caller must Release() the returned surface
2110
IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target)
2112
ASSERT(target == GL_TEXTURE_2D);
2114
// ensure the underlying texture is created
2115
if (getStorage(true) == NULL)
2122
// ensure this is NOT a depth texture
2127
return mTexStorage->getSurfaceLevel(0);
2130
// Increments refcount on surface.
2131
// caller must Release() the returned surface
2132
IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target)
2134
ASSERT(target == GL_TEXTURE_2D);
2136
// ensure the underlying texture is created
2137
if (getStorage(true) == NULL)
2144
// ensure this is actually a depth texture
2149
return mTexStorage->getSurfaceLevel(0);
2152
TextureStorage *Texture2D::getStorage(bool renderTarget)
2154
if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
2158
convertToRenderTarget();
2169
TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size)
2170
: TextureStorage(usage), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials())
2173
// if the size is not positive this should be treated as an incomplete texture
2174
// we handle that here by skipping the d3d texture creation
2177
IDirect3DDevice9 *device = getDevice();
2178
HRESULT result = device->CreateCubeTexture(size, levels, getUsage(), format, getPool(), &mTexture, NULL);
2182
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
2183
error(GL_OUT_OF_MEMORY);
2188
TextureStorageCubeMap::~TextureStorageCubeMap()
2192
mTexture->Release();
2196
// Increments refcount on surface.
2197
// caller must Release() the returned surface
2198
IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level)
2200
IDirect3DSurface9 *surface = NULL;
2204
HRESULT result = mTexture->GetCubeMapSurface(es2dx::ConvertCubeFace(faceTarget), level, &surface);
2205
ASSERT(SUCCEEDED(result));
2211
IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const
2216
unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const
2218
return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target);
2221
TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id)
2224
for (int i = 0; i < 6; i++)
2226
mFaceProxies[i] = NULL;
2227
mFaceProxyRefs[i] = 0;
2231
TextureCubeMap::~TextureCubeMap()
2233
for (int i = 0; i < 6; i++)
2235
mFaceProxies[i] = NULL;
2242
// We need to maintain a count of references to renderbuffers acting as
2243
// proxies for this texture, so that the texture is not deleted while
2244
// proxy references still exist. If the reference count drops to zero,
2245
// we set our proxy pointer NULL, so that a new attempt at referencing
2246
// will cause recreation.
2247
void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
2249
for (int i = 0; i < 6; i++)
2251
if (mFaceProxies[i] == proxy)
2252
mFaceProxyRefs[i]++;
2256
void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
2258
for (int i = 0; i < 6; i++)
2260
if (mFaceProxies[i] == proxy)
2262
if (mFaceProxyRefs[i] > 0)
2263
mFaceProxyRefs[i]--;
2265
if (mFaceProxyRefs[i] == 0)
2266
mFaceProxies[i] = NULL;
2271
GLenum TextureCubeMap::getTarget() const
2273
return GL_TEXTURE_CUBE_MAP;
2276
GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
2278
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2279
return mImageArray[faceIndex(target)][level].getWidth();
2284
GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
2286
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2287
return mImageArray[faceIndex(target)][level].getHeight();
2292
GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
2294
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2295
return mImageArray[faceIndex(target)][level].getFormat();
2300
D3DFORMAT TextureCubeMap::getD3DFormat(GLenum target, GLint level) const
2302
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2303
return mImageArray[faceIndex(target)][level].getD3DFormat();
2305
return D3DFMT_UNKNOWN;
2308
void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2310
setImage(0, level, width, height, format, type, unpackAlignment, pixels);
2313
void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2315
setImage(1, level, width, height, format, type, unpackAlignment, pixels);
2318
void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2320
setImage(2, level, width, height, format, type, unpackAlignment, pixels);
2323
void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2325
setImage(3, level, width, height, format, type, unpackAlignment, pixels);
2328
void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2330
setImage(4, level, width, height, format, type, unpackAlignment, pixels);
2333
void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2335
setImage(5, level, width, height, format, type, unpackAlignment, pixels);
2338
void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
2340
redefineImage(faceIndex(face), level, format, width, height, GL_UNSIGNED_BYTE);
2342
Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]);
2345
void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
2347
ASSERT(mImageArray[face][level].getSurface() != NULL);
2349
if (level < levelCount())
2351
IDirect3DSurface9 *destLevel = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
2352
ASSERT(destLevel != NULL);
2354
if (destLevel != NULL)
2356
Image *image = &mImageArray[face][level];
2357
image->updateSurface(destLevel, xoffset, yoffset, width, height);
2359
destLevel->Release();
2365
void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2367
if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level]))
2369
commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
2373
void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
2375
if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level]))
2377
commitRect(faceIndex(target), level, xoffset, yoffset, width, height);
2381
// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
2382
bool TextureCubeMap::isSamplerComplete() const
2384
int size = mImageArray[0][0].getWidth();
2394
case GL_NEAREST_MIPMAP_NEAREST:
2395
case GL_LINEAR_MIPMAP_NEAREST:
2396
case GL_NEAREST_MIPMAP_LINEAR:
2397
case GL_LINEAR_MIPMAP_LINEAR:
2405
if ((getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) ||
2406
(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES && !getContext()->supportsFloat16LinearFilter()))
2408
if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST))
2414
if (!isPow2(size) && !getContext()->supportsNonPower2Texture())
2416
if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping)
2424
if (!isCubeComplete())
2431
if (!isMipmapCubeComplete()) // Also tests for isCubeComplete()
2440
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
2441
bool TextureCubeMap::isCubeComplete() const
2443
if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth())
2448
for (unsigned int face = 1; face < 6; face++)
2450
if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() ||
2451
mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() ||
2452
mImageArray[face][0].getFormat() != mImageArray[0][0].getFormat() ||
2453
mImageArray[face][0].getType() != mImageArray[0][0].getType())
2462
bool TextureCubeMap::isMipmapCubeComplete() const
2469
if (!isCubeComplete())
2474
GLsizei size = mImageArray[0][0].getWidth();
2478
for (int face = 0; face < 6; face++)
2480
for (int level = 1; level <= q; level++)
2482
if (mImageArray[face][level].getFormat() != mImageArray[0][0].getFormat())
2487
if (mImageArray[face][level].getType() != mImageArray[0][0].getType())
2492
if (mImageArray[face][level].getWidth() != std::max(1, size >> level))
2502
bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
2504
return IsCompressed(getInternalFormat(target, level));
2507
IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const
2509
return mTexStorage ? mTexStorage->getBaseTexture() : NULL;
2512
// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one
2513
void TextureCubeMap::createTexture()
2515
GLsizei size = mImageArray[0][0].getWidth();
2516
GLint levels = creationLevels(size, 0);
2517
D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat();
2518
DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
2521
mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
2523
if (mTexStorage->isManaged())
2525
int levels = levelCount();
2527
for (int face = 0; face < 6; face++)
2529
for (int level = 0; level < levels; level++)
2531
IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
2532
mImageArray[face][level].setManagedSurface(surface);
2537
mDirtyImages = true;
2540
void TextureCubeMap::updateTexture()
2542
for (int face = 0; face < 6; face++)
2544
int levels = levelCount();
2545
for (int level = 0; level < levels; level++)
2547
Image *image = &mImageArray[face][level];
2549
if (image->isDirty())
2551
commitRect(face, level, 0, 0, image->getWidth(), image->getHeight());
2557
void TextureCubeMap::convertToRenderTarget()
2559
TextureStorageCubeMap *newTexStorage = NULL;
2561
if (mImageArray[0][0].getWidth() != 0)
2563
GLsizei size = mImageArray[0][0].getWidth();
2564
GLint levels = creationLevels(size, 0);
2565
D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat();
2566
DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true);
2568
newTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
2570
if (mTexStorage != NULL)
2572
int levels = levelCount();
2573
for (int f = 0; f < 6; f++)
2575
for (int i = 0; i < levels; i++)
2577
IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2578
IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2580
if (!copyToRenderTarget(dest, source, mTexStorage->isManaged()))
2582
delete newTexStorage;
2583
if (source) source->Release();
2584
if (dest) dest->Release();
2585
return error(GL_OUT_OF_MEMORY);
2588
if (source) source->Release();
2589
if (dest) dest->Release();
2596
mTexStorage = newTexStorage;
2598
mDirtyImages = true;
2601
void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels)
2603
redefineImage(faceIndex, level, format, width, height, type);
2605
Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]);
2608
unsigned int TextureCubeMap::faceIndex(GLenum face)
2610
META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
2611
META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
2612
META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
2613
META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
2614
META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
2616
return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2619
void TextureCubeMap::redefineImage(int face, GLint level, GLenum format, GLsizei width, GLsizei height, GLenum type)
2621
bool redefined = mImageArray[face][level].redefine(format, width, height, type, false);
2623
if (mTexStorage && redefined)
2625
for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
2627
for (int f = 0; f < 6; f++)
2629
mImageArray[f][i].markDirty();
2636
mDirtyImages = true;
2640
void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
2642
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2646
ERR("Failed to retrieve the render target.");
2647
return error(GL_OUT_OF_MEMORY);
2650
unsigned int faceindex = faceIndex(target);
2651
redefineImage(faceindex, level, format, width, height, GL_UNSIGNED_BYTE);
2653
if (!mImageArray[faceindex][level].isRenderableFormat())
2655
mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
2656
mDirtyImages = true;
2660
if (!mTexStorage || !mTexStorage->isRenderTarget())
2662
convertToRenderTarget();
2665
mImageArray[faceindex][level].markClean();
2667
ASSERT(width == height);
2669
if (width > 0 && level < levelCount())
2672
sourceRect.left = x;
2673
sourceRect.right = x + width;
2675
sourceRect.bottom = y + height;
2677
IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
2681
getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
2687
renderTarget->Release();
2690
void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
2692
GLsizei size = mImageArray[faceIndex(target)][level].getWidth();
2694
if (xoffset + width > size || yoffset + height > size)
2696
return error(GL_INVALID_VALUE);
2699
IDirect3DSurface9 *renderTarget = source->getRenderTarget();
2703
ERR("Failed to retrieve the render target.");
2704
return error(GL_OUT_OF_MEMORY);
2707
unsigned int faceindex = faceIndex(target);
2709
if (!mImageArray[faceindex][level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete()))
2711
mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget);
2712
mDirtyImages = true;
2716
if (!mTexStorage || !mTexStorage->isRenderTarget())
2718
convertToRenderTarget();
2723
if (level < levelCount())
2726
sourceRect.left = x;
2727
sourceRect.right = x + width;
2729
sourceRect.bottom = y + height;
2731
IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
2735
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0][0].getFormat(), xoffset, yoffset, dest);
2741
renderTarget->Release();
2744
void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
2746
GLenum format = gl::ExtractFormat(internalformat);
2747
GLenum type = gl::ExtractType(internalformat);
2748
D3DFORMAT d3dfmt = ConvertTextureFormatType(format, type);
2749
DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false);
2752
mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size);
2755
for (int level = 0; level < levels; level++)
2757
for (int face = 0; face < 6; face++)
2759
mImageArray[face][level].redefine(format, size, size, type, true);
2760
size = std::max(1, size >> 1);
2764
for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
2766
for (int face = 0; face < 6; face++)
2768
mImageArray[face][level].redefine(GL_NONE, 0, 0, GL_UNSIGNED_BYTE, true);
2772
if (mTexStorage->isManaged())
2774
int levels = levelCount();
2776
for (int face = 0; face < 6; face++)
2778
for (int level = 0; level < levels; level++)
2780
IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
2781
mImageArray[face][level].setManagedSurface(surface);
2787
void TextureCubeMap::generateMipmaps()
2789
if (!isCubeComplete())
2791
return error(GL_INVALID_OPERATION);
2794
if (!getContext()->supportsNonPower2Texture())
2796
if (!isPow2(mImageArray[0][0].getWidth()))
2798
return error(GL_INVALID_OPERATION);
2802
// Purge array levels 1 through q and reset them to represent the generated mipmap levels.
2803
unsigned int q = log2(mImageArray[0][0].getWidth());
2804
for (unsigned int f = 0; f < 6; f++)
2806
for (unsigned int i = 1; i <= q; i++)
2808
redefineImage(f, i, mImageArray[f][0].getFormat(),
2809
std::max(mImageArray[f][0].getWidth() >> i, 1),
2810
std::max(mImageArray[f][0].getWidth() >> i, 1),
2811
mImageArray[f][0].getType());
2815
if (mTexStorage && mTexStorage->isRenderTarget())
2817
for (unsigned int f = 0; f < 6; f++)
2819
for (unsigned int i = 1; i <= q; i++)
2821
IDirect3DSurface9 *upper = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i-1);
2822
IDirect3DSurface9 *lower = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i);
2824
if (upper != NULL && lower != NULL)
2826
getBlitter()->boxFilter(upper, lower);
2829
if (upper != NULL) upper->Release();
2830
if (lower != NULL) lower->Release();
2832
mImageArray[f][i].markClean();
2838
for (unsigned int f = 0; f < 6; f++)
2840
for (unsigned int i = 1; i <= q; i++)
2842
if (mImageArray[f][i].getSurface() == NULL)
2844
return error(GL_OUT_OF_MEMORY);
2847
if (FAILED(D3DXLoadSurfaceFromSurface(mImageArray[f][i].getSurface(), NULL, NULL, mImageArray[f][i - 1].getSurface(), NULL, NULL, D3DX_FILTER_BOX, 0)))
2849
ERR(" failed to load filter %d to %d.", i - 1, i);
2852
mImageArray[f][i].markDirty();
2858
Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)
2860
if (!IsCubemapTextureTarget(target))
2862
return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL);
2865
unsigned int face = faceIndex(target);
2867
if (mFaceProxies[face] == NULL)
2869
mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTextureCubeMap(this, target));
2872
return mFaceProxies[face];
2875
// Increments refcount on surface.
2876
// caller must Release() the returned surface
2877
IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target)
2879
ASSERT(IsCubemapTextureTarget(target));
2881
// ensure the underlying texture is created
2882
if (getStorage(true) == NULL)
2889
return mTexStorage->getCubeMapSurface(target, 0);
2892
TextureStorage *TextureCubeMap::getStorage(bool renderTarget)
2894
if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget()))
2898
convertToRenderTarget();