Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / canvas / WebGLContextTextures.cpp
blob24180c7e586495ac0c2c79ed52cf504cc4f717f3
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"
17 #include "nsString.h"
18 #include "nsDebug.h"
19 #include "nsReadableUtils.h"
21 #include "gfxContext.h"
22 #include "gfxPlatform.h"
23 #include "GLContext.h"
25 #include "nsContentUtils.h"
26 #include "nsError.h"
27 #include "nsLayoutUtils.h"
29 #include "CanvasUtils.h"
30 #include "gfxUtils.h"
32 #include "jsfriendapi.h"
34 #include "WebGLTexelConversions.h"
35 #include "WebGLValidateStrings.h"
36 #include <algorithm>
38 // needed to check if current OS is lower than 10.7
39 #if defined(MOZ_WIDGET_COCOA)
40 # include "nsCocoaFeatures.h"
41 #endif
43 #include "mozilla/DebugOnly.h"
44 #include "mozilla/dom/BindingUtils.h"
45 #include "mozilla/dom/ImageData.h"
46 #include "mozilla/EndianUtils.h"
48 namespace mozilla {
50 /*virtual*/
51 bool WebGLContext::IsTexParamValid(GLenum pname) const {
52 switch (pname) {
53 case LOCAL_GL_TEXTURE_MIN_FILTER:
54 case LOCAL_GL_TEXTURE_MAG_FILTER:
55 case LOCAL_GL_TEXTURE_WRAP_S:
56 case LOCAL_GL_TEXTURE_WRAP_T:
57 return true;
59 case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
60 return IsExtensionEnabled(
61 WebGLExtensionID::EXT_texture_filter_anisotropic);
63 default:
64 return false;
68 //////////////////////////////////////////////////////////////////////////////////////////
69 // GL calls
71 void WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) {
72 FuncScope funcScope(*this, "bindTexture");
73 if (IsContextLost()) return;
74 funcScope.mBindFailureGuard = true;
76 if (newTex && !ValidateObject("tex", *newTex)) return;
78 // Need to check rawTarget first before comparing against newTex->Target() as
79 // newTex->Target() returns a TexTarget, which will assert on invalid value.
80 RefPtr<WebGLTexture>* currentTexPtr = nullptr;
81 switch (rawTarget) {
82 case LOCAL_GL_TEXTURE_2D:
83 currentTexPtr = &mBound2DTextures[mActiveTexture];
84 break;
86 case LOCAL_GL_TEXTURE_CUBE_MAP:
87 currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
88 break;
90 case LOCAL_GL_TEXTURE_3D:
91 if (IsWebGL2()) currentTexPtr = &mBound3DTextures[mActiveTexture];
92 break;
94 case LOCAL_GL_TEXTURE_2D_ARRAY:
95 if (IsWebGL2()) currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
96 break;
99 if (!currentTexPtr) {
100 ErrorInvalidEnumInfo("target", rawTarget);
101 return;
104 const TexTarget texTarget(rawTarget);
105 if (newTex) {
106 if (!newTex->BindTexture(texTarget)) return;
107 } else {
108 gl->fBindTexture(texTarget.get(), 0);
111 *currentTexPtr = newTex;
113 funcScope.mBindFailureGuard = false;
116 void WebGLContext::GenerateMipmap(GLenum texTarget) {
117 const FuncScope funcScope(*this, "generateMipmap");
119 const auto& tex = GetActiveTex(texTarget);
120 if (!tex) return;
121 tex->GenerateMipmap();
124 Maybe<double> WebGLContext::GetTexParameter(const WebGLTexture& tex,
125 GLenum pname) const {
126 const FuncScope funcScope(*this, "getTexParameter");
128 if (!IsTexParamValid(pname)) {
129 ErrorInvalidEnumInfo("pname", pname);
130 return Nothing();
133 return tex.GetTexParameter(pname);
136 void WebGLContext::TexParameter_base(GLenum texTarget, GLenum pname,
137 const FloatOrInt& param) {
138 const FuncScope funcScope(*this, "texParameter");
140 const auto& tex = GetActiveTex(texTarget);
141 if (!tex) return;
142 tex->TexParameter(texTarget, pname, param);
145 //////////////////////////////////////////////////////////////////////////////////////////
146 // Uploads
148 WebGLTexture* WebGLContext::GetActiveTex(const GLenum texTarget) const {
149 const auto* list = &mBound2DTextures;
150 switch (texTarget) {
151 case LOCAL_GL_TEXTURE_2D:
152 break;
153 case LOCAL_GL_TEXTURE_CUBE_MAP:
154 list = &mBoundCubeMapTextures;
155 break;
156 case LOCAL_GL_TEXTURE_3D:
157 list = IsWebGL2() ? &mBound3DTextures : nullptr;
158 break;
159 case LOCAL_GL_TEXTURE_2D_ARRAY:
160 list = IsWebGL2() ? &mBound2DArrayTextures : nullptr;
161 break;
162 default:
163 list = nullptr;
165 if (!list) {
166 ErrorInvalidEnumArg("target", texTarget);
167 return nullptr;
169 const auto& tex = (*list)[mActiveTexture];
170 if (!tex) {
171 GenerateError(LOCAL_GL_INVALID_OPERATION, "No texture bound to %s[%u].",
172 EnumString(texTarget).c_str(), mActiveTexture);
173 return nullptr;
175 return tex;
178 void WebGLContext::TexStorage(GLenum texTarget, uint32_t levels,
179 GLenum internalFormat, uvec3 size) const {
180 const FuncScope funcScope(*this, "texStorage(Multisample)?");
181 if (!IsTexTarget3D(texTarget)) {
182 size.z = 1;
184 const auto tex = GetActiveTex(texTarget);
185 if (!tex) return;
186 tex->TexStorage(texTarget, levels, internalFormat, size);
189 void WebGLContext::TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
190 const webgl::PackingInfo& pi,
191 const webgl::TexUnpackBlobDesc& src) const {
192 const WebGLContext::FuncScope funcScope(
193 *this, bool(respecFormat) ? "texImage" : "texSubImage");
195 const bool isUploadFromPbo = bool(src.pboOffset);
196 const bool isPboBound = bool(mBoundPixelUnpackBuffer);
197 if (isUploadFromPbo != isPboBound) {
198 GenerateError(LOCAL_GL_INVALID_OPERATION,
199 "Tex upload from %s but PIXEL_UNPACK_BUFFER %s bound.",
200 isUploadFromPbo ? "PBO" : "non-PBO",
201 isPboBound ? "was" : "was not");
202 return;
205 if (respecFormat) {
206 offset = {0, 0, 0};
208 const auto texTarget = ImageToTexTarget(src.imageTarget);
209 const auto tex = GetActiveTex(texTarget);
210 if (!tex) return;
211 tex->TexImage(level, respecFormat, offset, pi, src);
214 void WebGLContext::CompressedTexImage(bool sub, GLenum imageTarget,
215 uint32_t level, GLenum format,
216 uvec3 offset, uvec3 size,
217 const Range<const uint8_t>& src,
218 const uint32_t pboImageSize,
219 const Maybe<uint64_t>& pboOffset) const {
220 const WebGLContext::FuncScope funcScope(
221 *this, !sub ? "compressedTexImage" : "compressedTexSubImage");
223 if (!sub) {
224 offset = {0, 0, 0};
226 const auto texTarget = ImageToTexTarget(imageTarget);
227 if (!IsTexTarget3D(texTarget)) {
228 size.z = 1;
230 const auto tex = GetActiveTex(texTarget);
231 if (!tex) return;
232 tex->CompressedTexImage(sub, imageTarget, level, format, offset, size, src,
233 pboImageSize, pboOffset);
236 void WebGLContext::CopyTexImage(GLenum imageTarget, uint32_t level,
237 GLenum respecFormat, uvec3 dstOffset,
238 const ivec2& srcOffset,
239 const uvec2& size) const {
240 const WebGLContext::FuncScope funcScope(
241 *this, bool(respecFormat) ? "copyTexImage" : "copyTexSubImage");
243 if (respecFormat) {
244 dstOffset = {0, 0, 0};
246 const auto tex = GetActiveTex(ImageToTexTarget(imageTarget));
247 if (!tex) return;
248 tex->CopyTexImage(imageTarget, level, respecFormat, dstOffset, srcOffset,
249 size);
252 } // namespace mozilla