1 // SwiftShader Software Renderer
\r
3 // Copyright(c) 2005-2013 TransGaming Inc.
\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
\r
6 // transcribed, stored in a retrieval system, translated into any human or computer
\r
7 // language by any means, or disclosed to third parties without the explicit written
\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
\r
9 // or implied, including but not limited to any patent rights, are granted to you.
\r
12 // Texture.cpp: Implements the Texture class and its derived classes
\r
13 // Texture2D, TextureCubeMap, Texture3D and Texture2DArray. Implements GL texture objects
\r
14 // and related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
\r
16 #include "Texture.h"
\r
19 #include "mathutil.h"
\r
20 #include "Framebuffer.h"
\r
21 #include "Device.hpp"
\r
22 #include "libEGL/Display.h"
\r
23 #include "libEGL/Surface.h"
\r
24 #include "common/debug.h"
\r
26 #include <algorithm>
\r
31 Texture::Texture(GLuint name) : egl::Texture(name)
\r
33 mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
\r
34 mMagFilter = GL_LINEAR;
\r
38 mMaxAnisotropy = 1.0f;
\r
40 mCompareFunc = GL_LEQUAL;
\r
41 mCompareMode = GL_NONE;
\r
42 mImmutableFormat = GL_FALSE;
\r
43 mImmutableLevels = 0;
\r
48 mSwizzleG = GL_GREEN;
\r
49 mSwizzleB = GL_BLUE;
\r
50 mSwizzleA = GL_ALPHA;
\r
52 resource = new sw::Resource(0);
\r
57 resource->destruct();
\r
60 sw::Resource *Texture::getResource() const
\r
65 // Returns true on successful filter state update (valid enum parameter)
\r
66 bool Texture::setMinFilter(GLenum filter)
\r
70 case GL_NEAREST_MIPMAP_NEAREST:
\r
71 case GL_LINEAR_MIPMAP_NEAREST:
\r
72 case GL_NEAREST_MIPMAP_LINEAR:
\r
73 case GL_LINEAR_MIPMAP_LINEAR:
\r
74 if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
\r
81 mMinFilter = filter;
\r
88 // Returns true on successful filter state update (valid enum parameter)
\r
89 bool Texture::setMagFilter(GLenum filter)
\r
95 mMagFilter = filter;
\r
102 // Returns true on successful wrap state update (valid enum parameter)
\r
103 bool Texture::setWrapS(GLenum wrap)
\r
108 case GL_MIRRORED_REPEAT:
\r
109 if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
\r
114 case GL_CLAMP_TO_EDGE:
\r
122 // Returns true on successful wrap state update (valid enum parameter)
\r
123 bool Texture::setWrapT(GLenum wrap)
\r
128 case GL_MIRRORED_REPEAT:
\r
129 if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
\r
134 case GL_CLAMP_TO_EDGE:
\r
142 // Returns true on successful wrap state update (valid enum parameter)
\r
143 bool Texture::setWrapR(GLenum wrap)
\r
148 case GL_MIRRORED_REPEAT:
\r
149 if(getTarget() == GL_TEXTURE_EXTERNAL_OES)
\r
154 case GL_CLAMP_TO_EDGE:
\r
162 // Returns true on successful max anisotropy update (valid anisotropy value)
\r
163 bool Texture::setMaxAnisotropy(float textureMaxAnisotropy)
\r
165 textureMaxAnisotropy = std::min(textureMaxAnisotropy, MAX_TEXTURE_MAX_ANISOTROPY);
\r
167 if(textureMaxAnisotropy < 1.0f)
\r
172 if(mMaxAnisotropy != textureMaxAnisotropy)
\r
174 mMaxAnisotropy = textureMaxAnisotropy;
\r
180 bool Texture::setBaseLevel(GLint baseLevel)
\r
182 mBaseLevel = baseLevel;
\r
186 bool Texture::setCompareFunc(GLenum compareFunc)
\r
188 switch(compareFunc)
\r
198 mCompareFunc = compareFunc;
\r
205 bool Texture::setCompareMode(GLenum compareMode)
\r
207 switch(compareMode)
\r
209 case GL_COMPARE_REF_TO_TEXTURE:
\r
211 mCompareMode = compareMode;
\r
218 void Texture::makeImmutable(GLsizei levels)
\r
220 mImmutableFormat = GL_TRUE;
\r
221 mImmutableLevels = levels;
\r
224 bool Texture::setMaxLevel(GLint maxLevel)
\r
226 mMaxLevel = maxLevel;
\r
230 bool Texture::setMaxLOD(GLfloat maxLOD)
\r
236 bool Texture::setMinLOD(GLfloat minLOD)
\r
242 bool Texture::setSwizzleR(GLenum swizzleR)
\r
252 mSwizzleR = swizzleR;
\r
259 bool Texture::setSwizzleG(GLenum swizzleG)
\r
269 mSwizzleG = swizzleG;
\r
276 bool Texture::setSwizzleB(GLenum swizzleB)
\r
286 mSwizzleB = swizzleB;
\r
293 bool Texture::setSwizzleA(GLenum swizzleA)
\r
303 mSwizzleA = swizzleA;
\r
310 GLenum Texture::getMinFilter() const
\r
315 GLenum Texture::getMagFilter() const
\r
320 GLenum Texture::getWrapS() const
\r
325 GLenum Texture::getWrapT() const
\r
330 GLenum Texture::getWrapR() const
\r
335 GLfloat Texture::getMaxAnisotropy() const
\r
337 return mMaxAnisotropy;
\r
340 GLint Texture::getBaseLevel() const
\r
344 GLenum Texture::getCompareFunc() const
\r
346 return mCompareFunc;
\r
348 GLenum Texture::getCompareMode() const
\r
350 return mCompareMode;
\r
352 GLboolean Texture::getImmutableFormat() const
\r
354 return mImmutableFormat;
\r
356 GLsizei Texture::getImmutableLevels() const
\r
358 return mImmutableLevels;
\r
360 GLint Texture::getMaxLevel() const
\r
364 GLfloat Texture::getMaxLOD() const
\r
368 GLfloat Texture::getMinLOD() const
\r
372 GLenum Texture::getSwizzleR() const
\r
376 GLenum Texture::getSwizzleG() const
\r
380 GLenum Texture::getSwizzleB() const
\r
384 GLenum Texture::getSwizzleA() const
\r
389 GLsizei Texture::getDepth(GLenum target, GLint level) const
\r
394 egl::Image *Texture::createSharedImage(GLenum target, unsigned int level)
\r
396 egl::Image *image = getRenderTarget(target, level); // Increments reference count
\r
400 image->markShared();
\r
406 void Texture::setImage(GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels, egl::Image *image)
\r
408 if(pixels && image)
\r
410 GLsizei depth = (getTarget() == GL_TEXTURE_3D_OES || getTarget() == GL_TEXTURE_2D_ARRAY) ? image->getDepth() : 1;
\r
411 image->loadImageData(0, 0, 0, image->getWidth(), image->getHeight(), depth, format, type, unpackInfo, pixels);
\r
415 void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, egl::Image *image)
\r
417 if(pixels && image)
\r
419 GLsizei depth = (getTarget() == GL_TEXTURE_3D_OES || getTarget() == GL_TEXTURE_2D_ARRAY) ? image->getDepth() : 1;
\r
420 image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), depth, imageSize, pixels);
\r
424 void Texture::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels, egl::Image *image)
\r
428 return error(GL_INVALID_OPERATION);
\r
431 if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight() || depth + zoffset > image->getDepth())
\r
433 return error(GL_INVALID_VALUE);
\r
436 if(IsCompressed(image->getFormat(), egl::getClientVersion()))
\r
438 return error(GL_INVALID_OPERATION);
\r
441 if(format != image->getFormat())
\r
443 return error(GL_INVALID_OPERATION);
\r
448 image->loadImageData(xoffset, yoffset, zoffset, width, height, depth, format, type, unpackInfo, pixels);
\r
452 void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels, egl::Image *image)
\r
456 return error(GL_INVALID_OPERATION);
\r
459 if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight() || depth + zoffset > image->getDepth())
\r
461 return error(GL_INVALID_VALUE);
\r
464 if(format != image->getFormat())
\r
466 return error(GL_INVALID_OPERATION);
\r
471 image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, imageSize, pixels);
\r
475 bool Texture::copy(egl::Image *source, const sw::SliceRect &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zoffset, egl::Image *dest)
\r
477 Device *device = getDevice();
\r
479 sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), zoffset);
\r
480 bool success = device->stretchRect(source, &sourceRect, dest, &destRect, false);
\r
484 return error(GL_OUT_OF_MEMORY, false);
\r
490 bool Texture::isMipmapFiltered() const
\r
497 case GL_NEAREST_MIPMAP_NEAREST:
\r
498 case GL_LINEAR_MIPMAP_NEAREST:
\r
499 case GL_NEAREST_MIPMAP_LINEAR:
\r
500 case GL_LINEAR_MIPMAP_LINEAR:
\r
502 default: UNREACHABLE(mMinFilter);
\r
508 Texture2D::Texture2D(GLuint name) : Texture(name)
\r
510 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
512 image[i] = nullptr;
\r
515 mSurface = nullptr;
\r
517 mColorbufferProxy = nullptr;
\r
521 Texture2D::~Texture2D()
\r
523 resource->lock(sw::DESTRUCT);
\r
525 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
529 image[i]->unbind(this);
\r
530 image[i] = nullptr;
\r
534 resource->unlock();
\r
538 mSurface->setBoundTexture(nullptr);
\r
539 mSurface = nullptr;
\r
542 mColorbufferProxy = nullptr;
\r
545 // We need to maintain a count of references to renderbuffers acting as
\r
546 // proxies for this texture, so that we do not attempt to use a pointer
\r
547 // to a renderbuffer proxy which has been deleted.
\r
548 void Texture2D::addProxyRef(const Renderbuffer *proxy)
\r
553 void Texture2D::releaseProxy(const Renderbuffer *proxy)
\r
560 if(mProxyRefs == 0)
\r
562 mColorbufferProxy = nullptr;
\r
566 void Texture2D::sweep()
\r
568 int imageCount = 0;
\r
570 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
572 if(image[i] && image[i]->isChildOf(this))
\r
574 if(!image[i]->hasSingleReference())
\r
583 if(imageCount == referenceCount)
\r
589 GLenum Texture2D::getTarget() const
\r
591 return GL_TEXTURE_2D;
\r
594 GLsizei Texture2D::getWidth(GLenum target, GLint level) const
\r
596 ASSERT(target == GL_TEXTURE_2D);
\r
597 return image[level] ? image[level]->getWidth() : 0;
\r
600 GLsizei Texture2D::getHeight(GLenum target, GLint level) const
\r
602 ASSERT(target == GL_TEXTURE_2D);
\r
603 return image[level] ? image[level]->getHeight() : 0;
\r
606 GLenum Texture2D::getFormat(GLenum target, GLint level) const
\r
608 ASSERT(target == GL_TEXTURE_2D);
\r
609 return image[level] ? image[level]->getFormat() : GL_NONE;
\r
612 GLenum Texture2D::getType(GLenum target, GLint level) const
\r
614 ASSERT(target == GL_TEXTURE_2D);
\r
615 return image[level] ? image[level]->getType() : GL_NONE;
\r
618 sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
\r
620 ASSERT(target == GL_TEXTURE_2D);
\r
621 return image[level] ? image[level]->getInternalFormat() : sw::FORMAT_NULL;
\r
624 int Texture2D::getLevelCount() const
\r
626 ASSERT(isSamplerComplete());
\r
629 while(levels < MIPMAP_LEVELS && image[levels])
\r
637 void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
641 image[level]->release();
\r
644 image[level] = new egl::Image(this, width, height, format, type);
\r
648 return error(GL_OUT_OF_MEMORY);
\r
651 Texture::setImage(format, type, unpackInfo, pixels, image[level]);
\r
654 void Texture2D::bindTexImage(egl::Surface *surface)
\r
658 switch(surface->getInternalFormat())
\r
660 case sw::FORMAT_A8R8G8B8:
\r
661 format = GL_BGRA_EXT;
\r
663 case sw::FORMAT_A8B8G8R8:
\r
666 case sw::FORMAT_X8B8G8R8:
\r
667 case sw::FORMAT_X8R8G8B8:
\r
675 for(int level = 0; level < MIPMAP_LEVELS; level++)
\r
679 image[level]->release();
\r
680 image[level] = nullptr;
\r
684 image[0] = surface->getRenderTarget();
\r
686 mSurface = surface;
\r
687 mSurface->setBoundTexture(this);
\r
690 void Texture2D::releaseTexImage()
\r
692 for(int level = 0; level < MIPMAP_LEVELS; level++)
\r
696 image[level]->release();
\r
697 image[level] = nullptr;
\r
702 void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
\r
706 image[level]->release();
\r
709 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
710 image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
714 return error(GL_OUT_OF_MEMORY);
\r
717 Texture::setCompressedImage(imageSize, pixels, image[level]);
\r
720 void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
722 Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpackInfo, pixels, image[level]);
\r
725 void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
\r
727 Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, image[level]);
\r
730 void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
\r
732 egl::Image *renderTarget = source->getRenderTarget(0);
\r
736 ERR("Failed to retrieve the render target.");
\r
737 return error(GL_OUT_OF_MEMORY);
\r
742 image[level]->release();
\r
745 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
746 image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
750 return error(GL_OUT_OF_MEMORY);
\r
753 if(width != 0 && height != 0)
\r
755 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
759 ERR("Failed to retrieve the source colorbuffer.");
\r
763 sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
\r
764 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
766 copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, 0, image[level]);
\r
769 renderTarget->release();
\r
772 void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
\r
776 return error(GL_INVALID_OPERATION);
\r
779 if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight() || zoffset != 0)
\r
781 return error(GL_INVALID_VALUE);
\r
784 egl::Image *renderTarget = source->getRenderTarget(0);
\r
788 ERR("Failed to retrieve the render target.");
\r
789 return error(GL_OUT_OF_MEMORY);
\r
792 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
796 ERR("Failed to retrieve the source colorbuffer.");
\r
800 sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
\r
801 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
803 copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
\r
805 renderTarget->release();
\r
808 void Texture2D::setImage(egl::Image *sharedImage)
\r
810 if (sharedImage == image[0])
\r
815 sharedImage->addRef();
\r
819 image[0]->release();
\r
822 image[0] = sharedImage;
\r
825 // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
\r
826 bool Texture2D::isSamplerComplete() const
\r
833 GLsizei width = image[0]->getWidth();
\r
834 GLsizei height = image[0]->getHeight();
\r
836 if(width <= 0 || height <= 0)
\r
841 if(isMipmapFiltered())
\r
843 if(!isMipmapComplete())
\r
852 // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
\r
853 bool Texture2D::isMipmapComplete() const
\r
855 GLsizei width = image[mBaseLevel]->getWidth();
\r
856 GLsizei height = image[mBaseLevel]->getHeight();
\r
858 int q = std::min(log2(std::max(width, height)), mMaxLevel);
\r
860 for(int level = mBaseLevel + 1; level <= q; level++)
\r
867 if(image[level]->getFormat() != image[0]->getFormat())
\r
872 if(image[level]->getType() != image[0]->getType())
\r
877 if(image[level]->getWidth() != std::max(1, width >> level))
\r
882 if(image[level]->getHeight() != std::max(1, height >> level))
\r
891 bool Texture2D::isCompressed(GLenum target, GLint level) const
\r
893 return IsCompressed(getFormat(target, level), egl::getClientVersion());
\r
896 bool Texture2D::isDepth(GLenum target, GLint level) const
\r
898 return IsDepthTexture(getFormat(target, level));
\r
901 void Texture2D::generateMipmaps()
\r
905 return; // FIXME: error?
\r
908 unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight()));
\r
910 for(unsigned int i = 1; i <= q; i++)
\r
914 image[i]->release();
\r
917 image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), image[0]->getFormat(), image[0]->getType());
\r
921 return error(GL_OUT_OF_MEMORY);
\r
924 getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true);
\r
928 egl::Image *Texture2D::getImage(unsigned int level)
\r
930 return image[level];
\r
933 Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level, GLint layer)
\r
935 if(target != GL_TEXTURE_2D)
\r
937 return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr);
\r
940 if(!mColorbufferProxy)
\r
942 mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this, level));
\r
945 return mColorbufferProxy;
\r
948 egl::Image *Texture2D::getRenderTarget(GLenum target, unsigned int level)
\r
950 ASSERT(target == GL_TEXTURE_2D);
\r
951 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
955 image[level]->addRef();
\r
958 return image[level];
\r
961 bool Texture2D::isShared(GLenum target, unsigned int level) const
\r
963 ASSERT(target == GL_TEXTURE_2D);
\r
964 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
966 if(mSurface) // Bound to an EGLSurface
\r
976 return image[level]->isShared();
\r
979 TextureCubeMap::TextureCubeMap(GLuint name) : Texture(name)
\r
981 for(int f = 0; f < 6; f++)
\r
983 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
985 image[f][i] = nullptr;
\r
989 for(int f = 0; f < 6; f++)
\r
991 mFaceProxies[f] = nullptr;
\r
992 mFaceProxyRefs[f] = 0;
\r
996 TextureCubeMap::~TextureCubeMap()
\r
998 resource->lock(sw::DESTRUCT);
\r
1000 for(int f = 0; f < 6; f++)
\r
1002 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
1006 image[f][i]->unbind(this);
\r
1007 image[f][i] = nullptr;
\r
1012 resource->unlock();
\r
1014 for(int i = 0; i < 6; i++)
\r
1016 mFaceProxies[i] = nullptr;
\r
1020 // We need to maintain a count of references to renderbuffers acting as
\r
1021 // proxies for this texture, so that the texture is not deleted while
\r
1022 // proxy references still exist. If the reference count drops to zero,
\r
1023 // we set our proxy pointer null, so that a new attempt at referencing
\r
1024 // will cause recreation.
\r
1025 void TextureCubeMap::addProxyRef(const Renderbuffer *proxy)
\r
1027 for(int f = 0; f < 6; f++)
\r
1029 if(mFaceProxies[f] == proxy)
\r
1031 mFaceProxyRefs[f]++;
\r
1036 void TextureCubeMap::releaseProxy(const Renderbuffer *proxy)
\r
1038 for(int f = 0; f < 6; f++)
\r
1040 if(mFaceProxies[f] == proxy)
\r
1042 if(mFaceProxyRefs[f] > 0)
\r
1044 mFaceProxyRefs[f]--;
\r
1047 if(mFaceProxyRefs[f] == 0)
\r
1049 mFaceProxies[f] = nullptr;
\r
1055 void TextureCubeMap::sweep()
\r
1057 int imageCount = 0;
\r
1059 for(int f = 0; f < 6; f++)
\r
1061 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
1063 if(image[f][i] && image[f][i]->isChildOf(this))
\r
1065 if(!image[f][i]->hasSingleReference())
\r
1075 if(imageCount == referenceCount)
\r
1081 GLenum TextureCubeMap::getTarget() const
\r
1083 return GL_TEXTURE_CUBE_MAP;
\r
1086 GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
\r
1088 int face = CubeFaceIndex(target);
\r
1089 return image[face][level] ? image[face][level]->getWidth() : 0;
\r
1092 GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
\r
1094 int face = CubeFaceIndex(target);
\r
1095 return image[face][level] ? image[face][level]->getHeight() : 0;
\r
1098 GLenum TextureCubeMap::getFormat(GLenum target, GLint level) const
\r
1100 int face = CubeFaceIndex(target);
\r
1101 return image[face][level] ? image[face][level]->getFormat() : 0;
\r
1104 GLenum TextureCubeMap::getType(GLenum target, GLint level) const
\r
1106 int face = CubeFaceIndex(target);
\r
1107 return image[face][level] ? image[face][level]->getType() : 0;
\r
1110 sw::Format TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
\r
1112 int face = CubeFaceIndex(target);
\r
1113 return image[face][level] ? image[face][level]->getInternalFormat() : sw::FORMAT_NULL;
\r
1116 int TextureCubeMap::getLevelCount() const
\r
1118 ASSERT(isSamplerComplete());
\r
1121 while(levels < MIPMAP_LEVELS && image[0][levels])
\r
1129 void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels)
\r
1131 int face = CubeFaceIndex(target);
\r
1133 if(image[face][level])
\r
1135 image[face][level]->release();
\r
1138 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
1139 image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
1141 if(!image[face][level])
\r
1143 return error(GL_OUT_OF_MEMORY);
\r
1146 Texture::setCompressedImage(imageSize, pixels, image[face][level]);
\r
1149 void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
1151 Texture::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpackInfo, pixels, image[CubeFaceIndex(target)][level]);
\r
1154 void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels)
\r
1156 Texture::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, image[CubeFaceIndex(target)][level]);
\r
1159 // Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86.
\r
1160 bool TextureCubeMap::isSamplerComplete() const
\r
1162 for(int face = 0; face < 6; face++)
\r
1164 if(!image[face][0])
\r
1170 int size = image[0][0]->getWidth();
\r
1177 if(!isMipmapFiltered())
\r
1179 if(!isCubeComplete())
\r
1186 if(!isMipmapCubeComplete()) // Also tests for isCubeComplete()
\r
1195 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
\r
1196 bool TextureCubeMap::isCubeComplete() const
\r
1198 if(image[0][mBaseLevel]->getWidth() <= 0 || image[0][mBaseLevel]->getHeight() != image[0][mBaseLevel]->getWidth())
\r
1203 for(unsigned int face = 1; face < 6; face++)
\r
1205 if(image[face][mBaseLevel]->getWidth() != image[0][mBaseLevel]->getWidth() ||
\r
1206 image[face][mBaseLevel]->getWidth() != image[0][mBaseLevel]->getHeight() ||
\r
1207 image[face][mBaseLevel]->getFormat() != image[0][mBaseLevel]->getFormat() ||
\r
1208 image[face][mBaseLevel]->getType() != image[0][mBaseLevel]->getType())
\r
1217 bool TextureCubeMap::isMipmapCubeComplete() const
\r
1219 if(!isCubeComplete())
\r
1224 GLsizei size = image[0][mBaseLevel]->getWidth();
\r
1225 int q = std::min(log2(size), mMaxLevel);
\r
1227 for(int face = 0; face < 6; face++)
\r
1229 for(int level = mBaseLevel + 1; level <= q; level++)
\r
1231 if(!image[face][level])
\r
1236 if(image[face][level]->getFormat() != image[0][mBaseLevel]->getFormat())
\r
1241 if(image[face][level]->getType() != image[0][mBaseLevel]->getType())
\r
1246 if(image[face][level]->getWidth() != std::max(1, size >> level))
\r
1256 bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
\r
1258 return IsCompressed(getFormat(target, level), egl::getClientVersion());
\r
1261 bool TextureCubeMap::isDepth(GLenum target, GLint level) const
\r
1263 return IsDepthTexture(getFormat(target, level));
\r
1266 void TextureCubeMap::releaseTexImage()
\r
1268 UNREACHABLE(0); // Cube maps cannot have an EGL surface bound as an image
\r
1271 void TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
1273 int face = CubeFaceIndex(target);
\r
1275 if(image[face][level])
\r
1277 image[face][level]->release();
\r
1280 image[face][level] = new egl::Image(this, width, height, format, type);
\r
1282 if(!image[face][level])
\r
1284 return error(GL_OUT_OF_MEMORY);
\r
1287 Texture::setImage(format, type, unpackInfo, pixels, image[face][level]);
\r
1290 void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
\r
1292 egl::Image *renderTarget = source->getRenderTarget(0);
\r
1296 ERR("Failed to retrieve the render target.");
\r
1297 return error(GL_OUT_OF_MEMORY);
\r
1300 int face = CubeFaceIndex(target);
\r
1302 if(image[face][level])
\r
1304 image[face][level]->release();
\r
1307 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
1308 image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
1310 if(!image[face][level])
\r
1312 return error(GL_OUT_OF_MEMORY);
\r
1315 if(width != 0 && height != 0)
\r
1317 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
1321 ERR("Failed to retrieve the source colorbuffer.");
\r
1325 sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
\r
1326 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
1328 copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, 0, image[face][level]);
\r
1331 renderTarget->release();
\r
1334 egl::Image *TextureCubeMap::getImage(int face, unsigned int level)
\r
1336 return image[face][level];
\r
1339 egl::Image *TextureCubeMap::getImage(GLenum face, unsigned int level)
\r
1341 return image[CubeFaceIndex(face)][level];
\r
1344 void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
\r
1346 int face = CubeFaceIndex(target);
\r
1348 if(!image[face][level])
\r
1350 return error(GL_INVALID_OPERATION);
\r
1353 GLsizei size = image[face][level]->getWidth();
\r
1355 if(xoffset + width > size || yoffset + height > size || zoffset != 0)
\r
1357 return error(GL_INVALID_VALUE);
\r
1360 egl::Image *renderTarget = source->getRenderTarget(0);
\r
1364 ERR("Failed to retrieve the render target.");
\r
1365 return error(GL_OUT_OF_MEMORY);
\r
1368 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
1372 ERR("Failed to retrieve the source colorbuffer.");
\r
1376 sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
\r
1377 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
1379 copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]);
\r
1381 renderTarget->release();
\r
1384 void TextureCubeMap::generateMipmaps()
\r
1386 if(!isCubeComplete())
\r
1388 return error(GL_INVALID_OPERATION);
\r
1391 unsigned int q = log2(image[0][0]->getWidth());
\r
1393 for(unsigned int f = 0; f < 6; f++)
\r
1395 for(unsigned int i = 1; i <= q; i++)
\r
1399 image[f][i]->release();
\r
1402 image[f][i] = new egl::Image(this, std::max(image[0][0]->getWidth() >> i, 1), std::max(image[0][0]->getHeight() >> i, 1), image[0][0]->getFormat(), image[0][0]->getType());
\r
1406 return error(GL_OUT_OF_MEMORY);
\r
1409 getDevice()->stretchRect(image[f][i - 1], 0, image[f][i], 0, true);
\r
1414 Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target, GLint level, GLint layer)
\r
1416 if(!IsCubemapTextureTarget(target))
\r
1418 return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr);
\r
1421 int face = CubeFaceIndex(target);
\r
1423 if(!mFaceProxies[face])
\r
1425 mFaceProxies[face] = new Renderbuffer(name, new RenderbufferTextureCubeMap(this, target, level));
\r
1428 return mFaceProxies[face];
\r
1431 egl::Image *TextureCubeMap::getRenderTarget(GLenum target, unsigned int level)
\r
1433 ASSERT(IsCubemapTextureTarget(target));
\r
1434 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
1436 int face = CubeFaceIndex(target);
\r
1438 if(image[face][level])
\r
1440 image[face][level]->addRef();
\r
1443 return image[face][level];
\r
1446 bool TextureCubeMap::isShared(GLenum target, unsigned int level) const
\r
1448 ASSERT(IsCubemapTextureTarget(target));
\r
1449 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
1451 int face = CubeFaceIndex(target);
\r
1453 if(!image[face][level])
\r
1458 return image[face][level]->isShared();
\r
1461 Texture3D::Texture3D(GLuint name) : Texture(name)
\r
1463 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
1465 image[i] = nullptr;
\r
1468 mSurface = nullptr;
\r
1470 mColorbufferProxy = nullptr;
\r
1474 Texture3D::~Texture3D()
\r
1476 resource->lock(sw::DESTRUCT);
\r
1478 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
1482 image[i]->unbind(this);
\r
1483 image[i] = nullptr;
\r
1487 resource->unlock();
\r
1491 mSurface->setBoundTexture(nullptr);
\r
1492 mSurface = nullptr;
\r
1495 mColorbufferProxy = nullptr;
\r
1498 // We need to maintain a count of references to renderbuffers acting as
\r
1499 // proxies for this texture, so that we do not attempt to use a pointer
\r
1500 // to a renderbuffer proxy which has been deleted.
\r
1501 void Texture3D::addProxyRef(const Renderbuffer *proxy)
\r
1506 void Texture3D::releaseProxy(const Renderbuffer *proxy)
\r
1508 if(mProxyRefs > 0)
\r
1513 if(mProxyRefs == 0)
\r
1515 mColorbufferProxy = nullptr;
\r
1519 void Texture3D::sweep()
\r
1521 int imageCount = 0;
\r
1523 for(int i = 0; i < MIPMAP_LEVELS; i++)
\r
1525 if(image[i] && image[i]->isChildOf(this))
\r
1527 if(!image[i]->hasSingleReference())
\r
1536 if(imageCount == referenceCount)
\r
1542 GLenum Texture3D::getTarget() const
\r
1544 return GL_TEXTURE_3D_OES;
\r
1547 GLsizei Texture3D::getWidth(GLenum target, GLint level) const
\r
1549 ASSERT(target == getTarget());
\r
1550 return image[level] ? image[level]->getWidth() : 0;
\r
1553 GLsizei Texture3D::getHeight(GLenum target, GLint level) const
\r
1555 ASSERT(target == getTarget());
\r
1556 return image[level] ? image[level]->getHeight() : 0;
\r
1559 GLsizei Texture3D::getDepth(GLenum target, GLint level) const
\r
1561 ASSERT(target == getTarget());
\r
1562 return image[level] ? image[level]->getDepth() : 0;
\r
1565 GLenum Texture3D::getFormat(GLenum target, GLint level) const
\r
1567 ASSERT(target == getTarget());
\r
1568 return image[level] ? image[level]->getFormat() : GL_NONE;
\r
1571 GLenum Texture3D::getType(GLenum target, GLint level) const
\r
1573 ASSERT(target == getTarget());
\r
1574 return image[level] ? image[level]->getType() : GL_NONE;
\r
1577 sw::Format Texture3D::getInternalFormat(GLenum target, GLint level) const
\r
1579 ASSERT(target == getTarget());
\r
1580 return image[level] ? image[level]->getInternalFormat() : sw::FORMAT_NULL;
\r
1583 int Texture3D::getLevelCount() const
\r
1585 ASSERT(isSamplerComplete());
\r
1588 while(levels < MIPMAP_LEVELS && image[levels])
\r
1596 void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
1600 image[level]->release();
\r
1603 image[level] = new egl::Image(this, width, height, depth, format, type);
\r
1607 return error(GL_OUT_OF_MEMORY);
\r
1610 Texture::setImage(format, type, unpackInfo, pixels, image[level]);
\r
1613 void Texture3D::bindTexImage(egl::Surface *surface)
\r
1617 switch(surface->getInternalFormat())
\r
1619 case sw::FORMAT_A8R8G8B8:
\r
1622 case sw::FORMAT_X8R8G8B8:
\r
1630 for(int level = 0; level < MIPMAP_LEVELS; level++)
\r
1634 image[level]->release();
\r
1635 image[level] = nullptr;
\r
1639 image[0] = surface->getRenderTarget();
\r
1641 mSurface = surface;
\r
1642 mSurface->setBoundTexture(this);
\r
1645 void Texture3D::releaseTexImage()
\r
1647 for(int level = 0; level < MIPMAP_LEVELS; level++)
\r
1651 image[level]->release();
\r
1652 image[level] = nullptr;
\r
1657 void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
\r
1661 image[level]->release();
\r
1664 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
1665 image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
1669 return error(GL_OUT_OF_MEMORY);
\r
1672 Texture::setCompressedImage(imageSize, pixels, image[level]);
\r
1675 void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
\r
1677 Texture::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpackInfo, pixels, image[level]);
\r
1680 void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
\r
1682 Texture::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, image[level]);
\r
1685 void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, GLsizei depth, Framebuffer *source)
\r
1687 egl::Image *renderTarget = source->getRenderTarget(0);
\r
1691 ERR("Failed to retrieve the render target.");
\r
1692 return error(GL_OUT_OF_MEMORY);
\r
1697 image[level]->release();
\r
1700 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
\r
1701 image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
\r
1705 return error(GL_OUT_OF_MEMORY);
\r
1708 if(width != 0 && height != 0 && depth != 0)
\r
1710 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
1714 ERR("Failed to retrieve the source colorbuffer.");
\r
1718 sw::SliceRect sourceRect(x, y, x + width, y + height, z);
\r
1719 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
1720 for(GLint sliceZ = 0; sliceZ < depth; ++sliceZ, ++sourceRect.slice)
\r
1722 copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, sliceZ, image[level]);
\r
1726 renderTarget->release();
\r
1729 void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
\r
1733 return error(GL_INVALID_OPERATION);
\r
1736 if(xoffset + width > image[level]->getWidth() || yoffset + height > image[level]->getHeight() || zoffset >= image[level]->getDepth())
\r
1738 return error(GL_INVALID_VALUE);
\r
1741 egl::Image *renderTarget = source->getRenderTarget(0);
\r
1745 ERR("Failed to retrieve the render target.");
\r
1746 return error(GL_OUT_OF_MEMORY);
\r
1749 Renderbuffer* renderbuffer = source->getReadColorbuffer();
\r
1753 ERR("Failed to retrieve the source colorbuffer.");
\r
1757 sw::SliceRect sourceRect = {x, y, x + width, y + height, 0};
\r
1758 sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
\r
1760 copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
\r
1762 renderTarget->release();
\r
1765 void Texture3D::setImage(egl::Image *sharedImage)
\r
1767 sharedImage->addRef();
\r
1771 image[0]->release();
\r
1774 image[0] = sharedImage;
\r
1777 // Tests for 3D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
\r
1778 bool Texture3D::isSamplerComplete() const
\r
1785 GLsizei width = image[0]->getWidth();
\r
1786 GLsizei height = image[0]->getHeight();
\r
1787 GLsizei depth = image[0]->getDepth();
\r
1789 if(width <= 0 || height <= 0 || depth <= 0)
\r
1794 if(isMipmapFiltered())
\r
1796 if(!isMipmapComplete())
\r
1805 // Tests for 3D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
\r
1806 bool Texture3D::isMipmapComplete() const
\r
1808 GLsizei width = image[mBaseLevel]->getWidth();
\r
1809 GLsizei height = image[mBaseLevel]->getHeight();
\r
1810 GLsizei depth = image[mBaseLevel]->getDepth();
\r
1811 bool isTexture2DArray = getTarget() == GL_TEXTURE_2D_ARRAY;
\r
1813 int q = isTexture2DArray ? std::min(log2(std::max(width, height)), mMaxLevel) :
\r
1814 std::min(log2(std::max(std::max(width, height), depth)), mMaxLevel);
\r
1816 for(int level = mBaseLevel + 1; level <= q; level++)
\r
1823 if(image[level]->getFormat() != image[0]->getFormat())
\r
1828 if(image[level]->getType() != image[0]->getType())
\r
1833 if(image[level]->getWidth() != std::max(1, width >> level))
\r
1838 if(image[level]->getHeight() != std::max(1, height >> level))
\r
1843 int levelDepth = isTexture2DArray ? depth : std::max(1, depth >> level);
\r
1844 if(image[level]->getDepth() != levelDepth)
\r
1853 bool Texture3D::isCompressed(GLenum target, GLint level) const
\r
1855 return IsCompressed(getFormat(target, level), egl::getClientVersion());
\r
1858 bool Texture3D::isDepth(GLenum target, GLint level) const
\r
1860 return IsDepthTexture(getFormat(target, level));
\r
1863 void Texture3D::generateMipmaps()
\r
1867 return; // FIXME: error?
\r
1870 unsigned int q = log2(std::max(std::max(image[0]->getWidth(), image[0]->getHeight()), image[0]->getDepth()));
\r
1872 for(unsigned int i = 1; i <= q; i++)
\r
1876 image[i]->release();
\r
1879 image[i] = new egl::Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), image[0]->getFormat(), image[0]->getType());
\r
1883 return error(GL_OUT_OF_MEMORY);
\r
1886 getDevice()->stretchCube(image[i - 1], image[i]);
\r
1890 egl::Image *Texture3D::getImage(unsigned int level)
\r
1892 return image[level];
\r
1895 Renderbuffer *Texture3D::getRenderbuffer(GLenum target, GLint level, GLint layer)
\r
1897 if(target != getTarget())
\r
1899 return error(GL_INVALID_OPERATION, (Renderbuffer*)nullptr);
\r
1902 if(!mColorbufferProxy)
\r
1904 mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture3D(this, level, layer));
\r
1907 return mColorbufferProxy;
\r
1910 egl::Image *Texture3D::getRenderTarget(GLenum target, unsigned int level)
\r
1912 ASSERT(target == getTarget());
\r
1913 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
1917 image[level]->addRef();
\r
1920 return image[level];
\r
1923 bool Texture3D::isShared(GLenum target, unsigned int level) const
\r
1925 ASSERT(target == getTarget());
\r
1926 ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
\r
1928 if(mSurface) // Bound to an EGLSurface
\r
1938 return image[level]->isShared();
\r
1941 Texture2DArray::Texture2DArray(GLuint name) : Texture3D(name)
\r
1945 Texture2DArray::~Texture2DArray()
\r
1949 GLenum Texture2DArray::getTarget() const
\r
1951 return GL_TEXTURE_2D_ARRAY;
\r
1954 void Texture2DArray::generateMipmaps()
\r
1956 int depth = image[0] ? image[0]->getDepth() : 0;
\r
1959 return; // FIXME: error?
\r
1962 unsigned int q = log2(std::max(image[0]->getWidth(), image[0]->getHeight()));
\r
1964 for(unsigned int i = 1; i <= q; i++)
\r
1968 image[i]->release();
\r
1971 GLsizei w = std::max(image[0]->getWidth() >> i, 1);
\r
1972 GLsizei h = std::max(image[0]->getHeight() >> i, 1);
\r
1973 image[i] = new egl::Image(this, w, h, depth, image[0]->getFormat(), image[0]->getType());
\r
1977 return error(GL_OUT_OF_MEMORY);
\r
1980 GLsizei srcw = image[i - 1]->getWidth();
\r
1981 GLsizei srch = image[i - 1]->getHeight();
\r
1982 for(int z = 0; z < depth; ++z)
\r
1984 sw::SliceRect srcRect(0, 0, srcw, srch, z);
\r
1985 sw::SliceRect dstRect(0, 0, w, h, z);
\r
1986 getDevice()->stretchRect(image[i - 1], &srcRect, image[i], &dstRect, true);
\r
1991 TextureExternal::TextureExternal(GLuint name) : Texture2D(name)
\r
1993 mMinFilter = GL_LINEAR;
\r
1994 mMagFilter = GL_LINEAR;
\r
1995 mWrapS = GL_CLAMP_TO_EDGE;
\r
1996 mWrapT = GL_CLAMP_TO_EDGE;
\r
1997 mWrapR = GL_CLAMP_TO_EDGE;
\r
2000 TextureExternal::~TextureExternal()
\r
2004 GLenum TextureExternal::getTarget() const
\r
2006 return GL_TEXTURE_EXTERNAL_OES;
\r
2011 egl::Image *createBackBuffer(int width, int height, const egl::Config *config)
\r
2015 return new egl::Image(width, height, config->mRenderTargetFormat, config->mSamples, false);
\r
2021 egl::Image *createDepthStencil(unsigned int width, unsigned int height, sw::Format format, int multiSampleDepth, bool discard)
\r
2023 if(width == 0 || height == 0 || height > OUTLINE_RESOLUTION)
\r
2025 ERR("Invalid parameters: %dx%d", width, height);
\r
2029 bool lockable = true;
\r
2033 // case sw::FORMAT_D15S1:
\r
2034 case sw::FORMAT_D24S8:
\r
2035 case sw::FORMAT_D24X8:
\r
2036 // case sw::FORMAT_D24X4S4:
\r
2037 case sw::FORMAT_D24FS8:
\r
2038 case sw::FORMAT_D32:
\r
2039 case sw::FORMAT_D16:
\r
2042 // case sw::FORMAT_S8_LOCKABLE:
\r
2043 // case sw::FORMAT_D16_LOCKABLE:
\r
2044 case sw::FORMAT_D32F_LOCKABLE:
\r
2045 // case sw::FORMAT_D32_LOCKABLE:
\r
2046 case sw::FORMAT_DF24S8:
\r
2047 case sw::FORMAT_DF16S8:
\r
2051 UNREACHABLE(format);
\r
2054 egl::Image *surface = new egl::Image(width, height, format, multiSampleDepth, lockable);
\r
2058 ERR("Out of memory");
\r