/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef WEBGL_TEXTURE_H_#define WEBGL_TEXTURE_H_#include<algorithm>#include<map>#include<set>#include<vector>#include"mozilla/Assertions.h"#include"mozilla/CheckedInt.h"#include"mozilla/dom/TypedArray.h"#include"mozilla/LinkedList.h"#include"nsWrapperCache.h"#include"CacheInvalidator.h"#include"WebGLObjectModel.h"#include"WebGLStrongTypes.h"#include"WebGLTypes.h"namespacemozilla{classErrorResult;classWebGLContext;classWebGLFramebuffer;classWebGLSampler;structFloatOrInt;structTexImageSource;namespacedom{classElement;classHTMLVideoElement;classImageData;classArrayBufferViewOrSharedArrayBufferView;}// namespace domnamespacelayers{classImage;}// namespace layersnamespacewebgl{structDriverUnpackInfo;structFormatUsageInfo;structPackingInfo;classTexUnpackBlob;}// namespace webglboolDoesTargetMatchDimensions(WebGLContext*webgl,TexImageTargettarget,uint8_tdims);namespacewebgl{structSamplingStatefinal{// Only store that which changes validation.TexMinFilterminFilter=LOCAL_GL_NEAREST_MIPMAP_LINEAR;TexMagFiltermagFilter=LOCAL_GL_LINEAR;TexWrapwrapS=LOCAL_GL_REPEAT;TexWrapwrapT=LOCAL_GL_REPEAT;//TexWrap wrapR = LOCAL_GL_REPEAT;//GLfloat minLod = -1000;//GLfloat maxLod = 1000;TexCompareModecompareMode=LOCAL_GL_NONE;//TexCompareFunc compareFunc = LOCAL_GL_LEQUAL;};structImageInfofinal{staticconstImageInfokUndefined;constwebgl::FormatUsageInfo*mFormat=nullptr;uint32_tmWidth=0;uint32_tmHeight=0;uint32_tmDepth=0;mutableboolmHasData=false;uint8_tmSamples=0;// -size_tMemoryUsage()const;boolIsDefined()const{if(!mFormat){MOZ_ASSERT(!mWidth&&!mHeight&&!mDepth);returnfalse;}returntrue;}Maybe<ImageInfo>NextMip(GLenumtarget)const;};}// namespace webgl// NOTE: When this class is switched to new DOM bindings, update the (then-slow)// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.classWebGLTexturefinal:publicnsWrapperCache,publicWebGLRefCountedObject<WebGLTexture>,publicLinkedListElement<WebGLTexture>,publicCacheInvalidator{// FriendsfriendclassWebGLContext;friendclassWebGLFramebuffer;////////////////////////////////////// Memberspublic:constGLuintmGLName;protected:TexTargetmTarget;staticconstuint8_tkMaxFaceCount=6;uint8_tmFaceCount;// 6 for cube maps, 1 otherwise.boolmImmutable;// Set by texStorage*uint8_tmImmutableLevelCount;uint32_tmBaseMipmapLevel;// Set by texParameter (defaults to 0)uint32_tmMaxMipmapLevel;// Set by texParameter (defaults to 1000)// You almost certainly don't want to query mMaxMipmapLevel.// You almost certainly want MaxEffectiveMipmapLevel().webgl::SamplingStatemSamplingState;mutableconstGLint*mCurSwizzle=nullptr;// nullptr means 'default swizzle'.// -structCompletenessInfofinal{uint8_tlevels=0;boolpowerOfTwo=false;boolmipmapComplete=false;constwebgl::FormatUsageInfo*usage=nullptr;constchar*incompleteReason=nullptr;};mutableCacheWeakMap<constWebGLSampler*,webgl::SampleableInfo>mSamplingCache;public:Maybe<constCompletenessInfo>CalcCompletenessInfo()const;Maybe<constwebgl::SampleableInfo>CalcSampleableInfo(constWebGLSampler*)const;constwebgl::SampleableInfo*GetSampleableInfo(constWebGLSampler*)const;// -constauto&Immutable()const{returnmImmutable;}constauto&BaseMipmapLevel()const{returnmBaseMipmapLevel;}// We can just max this out to 31, which is the number of unsigned bits in GLsizei.staticconstuint8_tkMaxLevelCount=31;// We store information about the various images that are part of this// texture. (cubemap faces, mipmap levels)webgl::ImageInfomImageInfoArr[kMaxLevelCount*kMaxFaceCount];////////////////////////////////////NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)WebGLTexture(WebGLContext*webgl,GLuinttex);voidDelete();boolHasEverBeenBound()const{returnmTarget!=LOCAL_GL_NONE;}TexTargetTarget()const{returnmTarget;}WebGLContext*GetParentObject()const{returnmContext;}virtualJSObject*WrapObject(JSContext*cx,JS::Handle<JSObject*>givenProto)override;protected:~WebGLTexture(){DeleteOnce();}public:////////////////////////////////////// GL callsboolBindTexture(TexTargettexTarget);voidGenerateMipmap();JS::ValueGetTexParameter(TexTargettexTarget,GLenumpname);boolIsTexture()const;voidTexParameter(TexTargettexTarget,GLenumpname,constFloatOrInt&param);////////////////////////////////////// WebGLTextureUpload.cppprotected:voidTexOrSubImageBlob(boolisSubImage,TexImageTargettarget,GLintlevel,GLenuminternalFormat,GLintxOffset,GLintyOffset,GLintzOffset,constwebgl::PackingInfo&pi,constwebgl::TexUnpackBlob*blob);boolValidateTexImageSpecification(TexImageTargettarget,GLintlevel,uint32_twidth,uint32_theight,uint32_tdepth,webgl::ImageInfo**constout_imageInfo);boolValidateTexImageSelection(TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,uint32_twidth,uint32_theight,uint32_tdepth,webgl::ImageInfo**constout_imageInfo);boolValidateCopyTexImageForFeedback(uint32_tlevel,GLintlayer=0)const;boolValidateUnpack(constwebgl::TexUnpackBlob*blob,boolisFunc3D,constwebgl::PackingInfo&srcPI)const;public:voidTexStorage(TexTargettarget,GLsizeilevels,GLenumsizedFormat,GLsizeiwidth,GLsizeiheight,GLsizeidepth);voidTexImage(TexImageTargettarget,GLintlevel,GLenuminternalFormat,GLsizeiwidth,GLsizeiheight,GLsizeidepth,GLintborder,constwebgl::PackingInfo&pi,constTexImageSource&src);voidTexSubImage(TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,GLsizeiwidth,GLsizeiheight,GLsizeidepth,constwebgl::PackingInfo&pi,constTexImageSource&src);protected:voidTexImage(TexImageTargettarget,GLintlevel,GLenuminternalFormat,constwebgl::PackingInfo&pi,constwebgl::TexUnpackBlob*blob);voidTexSubImage(TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,constwebgl::PackingInfo&pi,constwebgl::TexUnpackBlob*blob);public:voidCompressedTexImage(TexImageTargettarget,GLintlevel,GLenuminternalFormat,GLsizeiwidth,GLsizeiheight,GLsizeidepth,GLintborder,constTexImageSource&src,constMaybe<GLsizei>&expectedImageSize);voidCompressedTexSubImage(TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,GLsizeiwidth,GLsizeiheight,GLsizeidepth,GLenumsizedUnpackFormat,constTexImageSource&src,constMaybe<GLsizei>&expectedImageSize);voidCopyTexImage2D(TexImageTargettarget,GLintlevel,GLenuminternalFormat,GLintx,GLinty,GLsizeiwidth,GLsizeiheight,GLintborder);voidCopyTexSubImage(TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,GLintx,GLinty,GLsizeiwidth,GLsizeiheight);////////////////////////////////////protected:voidClampLevelBaseAndMax();voidRefreshSwizzle()const;public:uint32_tEffectiveMaxLevel()const;// GLES 3.0.5 p158: `q`protected:staticuint8_tFaceForTarget(TexImageTargettexImageTarget){GLenumrawTexImageTarget=texImageTarget.get();switch(rawTexImageTarget){caseLOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:caseLOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:caseLOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:caseLOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:caseLOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:caseLOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:returnrawTexImageTarget-LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;default:return0;}}auto&ImageInfoAtFace(uint8_tface,uint32_tlevel){MOZ_ASSERT(face<mFaceCount);MOZ_ASSERT(level<kMaxLevelCount);size_tpos=(level*mFaceCount)+face;returnmImageInfoArr[pos];}constauto&ImageInfoAtFace(uint8_tface,uint32_tlevel)const{returnconst_cast<WebGLTexture*>(this)->ImageInfoAtFace(face,level);}public:auto&ImageInfoAt(TexImageTargettexImageTarget,GLintlevel){constauto&face=FaceForTarget(texImageTarget);returnImageInfoAtFace(face,level);}constauto&ImageInfoAt(TexImageTargettexImageTarget,GLintlevel)const{returnconst_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget,level);}constauto&BaseImageInfo()const{if(mBaseMipmapLevel>=kMaxLevelCount)returnwebgl::ImageInfo::kUndefined;returnImageInfoAtFace(0,mBaseMipmapLevel);}size_tMemoryUsage()const;boolEnsureImageDataInitialized(TexImageTargettarget,uint32_tlevel);voidPopulateMipChain(uint32_tmaxLevel);boolIsMipAndCubeComplete(uint32_tmaxLevel,bool*out_initFailed)const;boolIsCubeMap()const{return(mTarget==LOCAL_GL_TEXTURE_CUBE_MAP);}};inlineTexImageTargetTexImageTargetForTargetAndFace(TexTargettarget,uint8_tface){switch(target.get()){caseLOCAL_GL_TEXTURE_2D:caseLOCAL_GL_TEXTURE_3D:MOZ_ASSERT(face==0);returntarget.get();caseLOCAL_GL_TEXTURE_CUBE_MAP:MOZ_ASSERT(face<6);returnLOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X+face;default:MOZ_CRASH("GFX: TexImageTargetForTargetAndFace");}}already_AddRefed<mozilla::layers::Image>ImageFromVideo(dom::HTMLVideoElement*elem);boolIsTarget3D(TexImageTargettarget);GLenumDoTexImage(gl::GLContext*gl,TexImageTargettarget,GLintlevel,constwebgl::DriverUnpackInfo*dui,GLsizeiwidth,GLsizeiheight,GLsizeidepth,constvoid*data);GLenumDoTexSubImage(gl::GLContext*gl,TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,GLsizeiwidth,GLsizeiheight,GLsizeidepth,constwebgl::PackingInfo&pi,constvoid*data);GLenumDoCompressedTexSubImage(gl::GLContext*gl,TexImageTargettarget,GLintlevel,GLintxOffset,GLintyOffset,GLintzOffset,GLsizeiwidth,GLsizeiheight,GLsizeidepth,GLenumsizedUnpackFormat,GLsizeidataSize,constvoid*data);}// namespace mozilla#endif // WEBGL_TEXTURE_H_