WebGLContextTextures.cpp (7443B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "CanvasUtils.h" 7 #include "GLContext.h" 8 #include "WebGLBuffer.h" 9 #include "WebGLContext.h" 10 #include "WebGLContextUtils.h" 11 #include "WebGLExtensions.h" 12 #include "WebGLFramebuffer.h" 13 #include "WebGLProgram.h" 14 #include "WebGLRenderbuffer.h" 15 #include "WebGLShader.h" 16 #include "WebGLTexelConversions.h" 17 #include "WebGLTexture.h" 18 #include "WebGLValidateStrings.h" 19 #include "WebGLVertexArray.h" 20 #include "gfxContext.h" 21 #include "gfxPlatform.h" 22 #include "gfxUtils.h" 23 #include "jsfriendapi.h" 24 #include "mozilla/dom/BindingUtils.h" 25 #include "mozilla/dom/ImageData.h" 26 #include "nsContentUtils.h" 27 #include "nsDebug.h" 28 #include "nsError.h" 29 #include "nsLayoutUtils.h" 30 #include "nsReadableUtils.h" 31 #include "nsString.h" 32 33 namespace mozilla { 34 35 /*virtual*/ 36 bool WebGLContext::IsTexParamValid(GLenum pname) const { 37 switch (pname) { 38 case LOCAL_GL_TEXTURE_MIN_FILTER: 39 case LOCAL_GL_TEXTURE_MAG_FILTER: 40 case LOCAL_GL_TEXTURE_WRAP_S: 41 case LOCAL_GL_TEXTURE_WRAP_T: 42 return true; 43 44 case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: 45 return IsExtensionEnabled( 46 WebGLExtensionID::EXT_texture_filter_anisotropic); 47 48 default: 49 return false; 50 } 51 } 52 53 ////////////////////////////////////////////////////////////////////////////////////////// 54 // GL calls 55 56 void WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) { 57 FuncScope funcScope(*this, "bindTexture"); 58 if (IsContextLost()) return; 59 funcScope.mBindFailureGuard = true; 60 61 if (newTex && !ValidateObject("tex", *newTex)) return; 62 63 // Need to check rawTarget first before comparing against newTex->Target() as 64 // newTex->Target() returns a TexTarget, which will assert on invalid value. 65 RefPtr<WebGLTexture>* currentTexPtr = nullptr; 66 switch (rawTarget) { 67 case LOCAL_GL_TEXTURE_2D: 68 currentTexPtr = &mBound2DTextures[mActiveTexture]; 69 break; 70 71 case LOCAL_GL_TEXTURE_CUBE_MAP: 72 currentTexPtr = &mBoundCubeMapTextures[mActiveTexture]; 73 break; 74 75 case LOCAL_GL_TEXTURE_3D: 76 if (IsWebGL2()) currentTexPtr = &mBound3DTextures[mActiveTexture]; 77 break; 78 79 case LOCAL_GL_TEXTURE_2D_ARRAY: 80 if (IsWebGL2()) currentTexPtr = &mBound2DArrayTextures[mActiveTexture]; 81 break; 82 } 83 84 if (!currentTexPtr) { 85 ErrorInvalidEnumInfo("target", rawTarget); 86 return; 87 } 88 89 const auto texTarget = TexTarget(rawTarget); 90 if (newTex) { 91 if (!newTex->BindTexture(texTarget)) return; 92 } else { 93 gl->fBindTexture(texTarget.get(), 0); 94 } 95 96 *currentTexPtr = newTex; 97 98 funcScope.mBindFailureGuard = false; 99 } 100 101 void WebGLContext::GenerateMipmap(GLenum texTarget) { 102 const FuncScope funcScope(*this, "generateMipmap"); 103 104 const auto& tex = GetActiveTex(texTarget); 105 if (!tex) return; 106 tex->GenerateMipmap(); 107 } 108 109 Maybe<double> WebGLContext::GetTexParameter(const WebGLTexture& tex, 110 GLenum pname) const { 111 const FuncScope funcScope(*this, "getTexParameter"); 112 113 if (!IsTexParamValid(pname)) { 114 ErrorInvalidEnumInfo("pname", pname); 115 return Nothing(); 116 } 117 118 return tex.GetTexParameter(pname); 119 } 120 121 void WebGLContext::TexParameter_base(GLenum texTarget, GLenum pname, 122 const FloatOrInt& param) { 123 const FuncScope funcScope(*this, "texParameter"); 124 125 const auto& tex = GetActiveTex(texTarget); 126 if (!tex) return; 127 tex->TexParameter(texTarget, pname, param); 128 } 129 130 ////////////////////////////////////////////////////////////////////////////////////////// 131 // Uploads 132 133 WebGLTexture* WebGLContext::GetActiveTex(const GLenum texTarget) const { 134 const auto* list = &mBound2DTextures; 135 switch (texTarget) { 136 case LOCAL_GL_TEXTURE_2D: 137 break; 138 case LOCAL_GL_TEXTURE_CUBE_MAP: 139 list = &mBoundCubeMapTextures; 140 break; 141 case LOCAL_GL_TEXTURE_3D: 142 list = IsWebGL2() ? &mBound3DTextures : nullptr; 143 break; 144 case LOCAL_GL_TEXTURE_2D_ARRAY: 145 list = IsWebGL2() ? &mBound2DArrayTextures : nullptr; 146 break; 147 default: 148 list = nullptr; 149 } 150 if (!list) { 151 ErrorInvalidEnumArg("target", texTarget); 152 return nullptr; 153 } 154 const auto& tex = (*list)[mActiveTexture]; 155 if (!tex) { 156 GenerateError(LOCAL_GL_INVALID_OPERATION, "No texture bound to %s[%u].", 157 EnumString(texTarget).c_str(), mActiveTexture); 158 return nullptr; 159 } 160 return tex; 161 } 162 163 void WebGLContext::TexStorage(GLenum texTarget, uint32_t levels, 164 GLenum internalFormat, uvec3 size) const { 165 const FuncScope funcScope(*this, "texStorage(Multisample)?"); 166 if (!IsTexTarget3D(texTarget)) { 167 size.z = 1; 168 } 169 const auto tex = GetActiveTex(texTarget); 170 if (!tex) return; 171 tex->TexStorage(texTarget, levels, internalFormat, size); 172 } 173 174 void WebGLContext::TexImage(uint32_t level, GLenum respecFormat, uvec3 offset, 175 const webgl::PackingInfo& pi, 176 const webgl::TexUnpackBlobDesc& src) const { 177 const WebGLContext::FuncScope funcScope( 178 *this, bool(respecFormat) ? "texImage" : "texSubImage"); 179 180 const bool isUploadFromPbo = bool(src.pboOffset); 181 const bool isPboBound = bool(mBoundPixelUnpackBuffer); 182 if (isUploadFromPbo != isPboBound) { 183 GenerateError(LOCAL_GL_INVALID_OPERATION, 184 "Tex upload from %s but PIXEL_UNPACK_BUFFER %s bound.", 185 isUploadFromPbo ? "PBO" : "non-PBO", 186 isPboBound ? "was" : "was not"); 187 return; 188 } 189 190 if (respecFormat) { 191 offset = {0, 0, 0}; 192 } 193 const auto texTarget = ImageToTexTarget(src.imageTarget); 194 const auto tex = GetActiveTex(texTarget); 195 if (!tex) return; 196 tex->TexImage(level, respecFormat, offset, pi, src); 197 } 198 199 void WebGLContext::CompressedTexImage(bool sub, GLenum imageTarget, 200 uint32_t level, GLenum format, 201 uvec3 offset, uvec3 size, 202 const Range<const uint8_t>& src, 203 const uint32_t pboImageSize, 204 const Maybe<uint64_t>& pboOffset) const { 205 const WebGLContext::FuncScope funcScope( 206 *this, !sub ? "compressedTexImage" : "compressedTexSubImage"); 207 208 if (!sub) { 209 offset = {0, 0, 0}; 210 } 211 const auto texTarget = ImageToTexTarget(imageTarget); 212 if (!IsTexTarget3D(texTarget)) { 213 size.z = 1; 214 } 215 const auto tex = GetActiveTex(texTarget); 216 if (!tex) return; 217 tex->CompressedTexImage(sub, imageTarget, level, format, offset, size, src, 218 pboImageSize, pboOffset); 219 } 220 221 void WebGLContext::CopyTexImage(GLenum imageTarget, uint32_t level, 222 GLenum respecFormat, uvec3 dstOffset, 223 const ivec2& srcOffset, 224 const uvec2& size) const { 225 const WebGLContext::FuncScope funcScope( 226 *this, bool(respecFormat) ? "copyTexImage" : "copyTexSubImage"); 227 228 if (respecFormat) { 229 dstOffset = {0, 0, 0}; 230 } 231 const auto tex = GetActiveTex(ImageToTexTarget(imageTarget)); 232 if (!tex) return; 233 tex->CopyTexImage(imageTarget, level, respecFormat, dstOffset, srcOffset, 234 size); 235 } 236 237 } // namespace mozilla