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/. */
6 #include "WebGLContext.h"
7 #include "WebGLContextUtils.h"
8 #include "WebGLBuffer.h"
9 #include "WebGLShader.h"
10 #include "WebGLProgram.h"
11 #include "WebGLFramebuffer.h"
12 #include "WebGLRenderbuffer.h"
13 #include "WebGLTexture.h"
14 #include "WebGLExtensions.h"
15 #include "WebGLVertexArray.h"
19 #include "nsReadableUtils.h"
21 #include "gfxContext.h"
22 #include "gfxPlatform.h"
23 #include "GLContext.h"
25 #include "nsContentUtils.h"
27 #include "nsLayoutUtils.h"
29 #include "CanvasUtils.h"
32 #include "jsfriendapi.h"
34 #include "WebGLTexelConversions.h"
35 #include "WebGLValidateStrings.h"
38 #include "mozilla/DebugOnly.h"
39 #include "mozilla/dom/BindingUtils.h"
40 #include "mozilla/dom/ImageData.h"
41 #include "mozilla/EndianUtils.h"
46 bool WebGLContext::IsTexParamValid(GLenum pname
) const {
48 case LOCAL_GL_TEXTURE_MIN_FILTER
:
49 case LOCAL_GL_TEXTURE_MAG_FILTER
:
50 case LOCAL_GL_TEXTURE_WRAP_S
:
51 case LOCAL_GL_TEXTURE_WRAP_T
:
54 case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT
:
55 return IsExtensionEnabled(
56 WebGLExtensionID::EXT_texture_filter_anisotropic
);
63 //////////////////////////////////////////////////////////////////////////////////////////
66 void WebGLContext::BindTexture(GLenum rawTarget
, WebGLTexture
* newTex
) {
67 FuncScope
funcScope(*this, "bindTexture");
68 if (IsContextLost()) return;
69 funcScope
.mBindFailureGuard
= true;
71 if (newTex
&& !ValidateObject("tex", *newTex
)) return;
73 // Need to check rawTarget first before comparing against newTex->Target() as
74 // newTex->Target() returns a TexTarget, which will assert on invalid value.
75 RefPtr
<WebGLTexture
>* currentTexPtr
= nullptr;
77 case LOCAL_GL_TEXTURE_2D
:
78 currentTexPtr
= &mBound2DTextures
[mActiveTexture
];
81 case LOCAL_GL_TEXTURE_CUBE_MAP
:
82 currentTexPtr
= &mBoundCubeMapTextures
[mActiveTexture
];
85 case LOCAL_GL_TEXTURE_3D
:
86 if (IsWebGL2()) currentTexPtr
= &mBound3DTextures
[mActiveTexture
];
89 case LOCAL_GL_TEXTURE_2D_ARRAY
:
90 if (IsWebGL2()) currentTexPtr
= &mBound2DArrayTextures
[mActiveTexture
];
95 ErrorInvalidEnumInfo("target", rawTarget
);
99 const auto texTarget
= TexTarget(rawTarget
);
101 if (!newTex
->BindTexture(texTarget
)) return;
103 gl
->fBindTexture(texTarget
.get(), 0);
106 *currentTexPtr
= newTex
;
108 funcScope
.mBindFailureGuard
= false;
111 void WebGLContext::GenerateMipmap(GLenum texTarget
) {
112 const FuncScope
funcScope(*this, "generateMipmap");
114 const auto& tex
= GetActiveTex(texTarget
);
116 tex
->GenerateMipmap();
119 Maybe
<double> WebGLContext::GetTexParameter(const WebGLTexture
& tex
,
120 GLenum pname
) const {
121 const FuncScope
funcScope(*this, "getTexParameter");
123 if (!IsTexParamValid(pname
)) {
124 ErrorInvalidEnumInfo("pname", pname
);
128 return tex
.GetTexParameter(pname
);
131 void WebGLContext::TexParameter_base(GLenum texTarget
, GLenum pname
,
132 const FloatOrInt
& param
) {
133 const FuncScope
funcScope(*this, "texParameter");
135 const auto& tex
= GetActiveTex(texTarget
);
137 tex
->TexParameter(texTarget
, pname
, param
);
140 //////////////////////////////////////////////////////////////////////////////////////////
143 WebGLTexture
* WebGLContext::GetActiveTex(const GLenum texTarget
) const {
144 const auto* list
= &mBound2DTextures
;
146 case LOCAL_GL_TEXTURE_2D
:
148 case LOCAL_GL_TEXTURE_CUBE_MAP
:
149 list
= &mBoundCubeMapTextures
;
151 case LOCAL_GL_TEXTURE_3D
:
152 list
= IsWebGL2() ? &mBound3DTextures
: nullptr;
154 case LOCAL_GL_TEXTURE_2D_ARRAY
:
155 list
= IsWebGL2() ? &mBound2DArrayTextures
: nullptr;
161 ErrorInvalidEnumArg("target", texTarget
);
164 const auto& tex
= (*list
)[mActiveTexture
];
166 GenerateError(LOCAL_GL_INVALID_OPERATION
, "No texture bound to %s[%u].",
167 EnumString(texTarget
).c_str(), mActiveTexture
);
173 void WebGLContext::TexStorage(GLenum texTarget
, uint32_t levels
,
174 GLenum internalFormat
, uvec3 size
) const {
175 const FuncScope
funcScope(*this, "texStorage(Multisample)?");
176 if (!IsTexTarget3D(texTarget
)) {
179 const auto tex
= GetActiveTex(texTarget
);
181 tex
->TexStorage(texTarget
, levels
, internalFormat
, size
);
184 void WebGLContext::TexImage(uint32_t level
, GLenum respecFormat
, uvec3 offset
,
185 const webgl::PackingInfo
& pi
,
186 const webgl::TexUnpackBlobDesc
& src
) const {
187 const WebGLContext::FuncScope
funcScope(
188 *this, bool(respecFormat
) ? "texImage" : "texSubImage");
190 const bool isUploadFromPbo
= bool(src
.pboOffset
);
191 const bool isPboBound
= bool(mBoundPixelUnpackBuffer
);
192 if (isUploadFromPbo
!= isPboBound
) {
193 GenerateError(LOCAL_GL_INVALID_OPERATION
,
194 "Tex upload from %s but PIXEL_UNPACK_BUFFER %s bound.",
195 isUploadFromPbo
? "PBO" : "non-PBO",
196 isPboBound
? "was" : "was not");
203 const auto texTarget
= ImageToTexTarget(src
.imageTarget
);
204 const auto tex
= GetActiveTex(texTarget
);
206 tex
->TexImage(level
, respecFormat
, offset
, pi
, src
);
209 void WebGLContext::CompressedTexImage(bool sub
, GLenum imageTarget
,
210 uint32_t level
, GLenum format
,
211 uvec3 offset
, uvec3 size
,
212 const Range
<const uint8_t>& src
,
213 const uint32_t pboImageSize
,
214 const Maybe
<uint64_t>& pboOffset
) const {
215 const WebGLContext::FuncScope
funcScope(
216 *this, !sub
? "compressedTexImage" : "compressedTexSubImage");
221 const auto texTarget
= ImageToTexTarget(imageTarget
);
222 if (!IsTexTarget3D(texTarget
)) {
225 const auto tex
= GetActiveTex(texTarget
);
227 tex
->CompressedTexImage(sub
, imageTarget
, level
, format
, offset
, size
, src
,
228 pboImageSize
, pboOffset
);
231 void WebGLContext::CopyTexImage(GLenum imageTarget
, uint32_t level
,
232 GLenum respecFormat
, uvec3 dstOffset
,
233 const ivec2
& srcOffset
,
234 const uvec2
& size
) const {
235 const WebGLContext::FuncScope
funcScope(
236 *this, bool(respecFormat
) ? "copyTexImage" : "copyTexSubImage");
239 dstOffset
= {0, 0, 0};
241 const auto tex
= GetActiveTex(ImageToTexTarget(imageTarget
));
243 tex
->CopyTexImage(imageTarget
, level
, respecFormat
, dstOffset
, srcOffset
,
247 } // namespace mozilla