summaryrefslogtreecommitdiffstats
path: root/dom/canvas/WebGLContextTextures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/WebGLContextTextures.cpp')
-rw-r--r--dom/canvas/WebGLContextTextures.cpp415
1 files changed, 415 insertions, 0 deletions
diff --git a/dom/canvas/WebGLContextTextures.cpp b/dom/canvas/WebGLContextTextures.cpp
new file mode 100644
index 000000000..30716438f
--- /dev/null
+++ b/dom/canvas/WebGLContextTextures.cpp
@@ -0,0 +1,415 @@
+/* -*- 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/. */
+
+#include "WebGLContext.h"
+#include "WebGLContextUtils.h"
+#include "WebGLBuffer.h"
+#include "WebGLVertexAttribData.h"
+#include "WebGLShader.h"
+#include "WebGLProgram.h"
+#include "WebGLUniformLocation.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLShaderPrecisionFormat.h"
+#include "WebGLTexture.h"
+#include "WebGLExtensions.h"
+#include "WebGLVertexArray.h"
+
+#include "nsString.h"
+#include "nsDebug.h"
+#include "nsReadableUtils.h"
+
+#include "gfxContext.h"
+#include "gfxPlatform.h"
+#include "GLContext.h"
+
+#include "nsContentUtils.h"
+#include "nsError.h"
+#include "nsLayoutUtils.h"
+
+#include "CanvasUtils.h"
+#include "gfxUtils.h"
+
+#include "jsfriendapi.h"
+
+#include "WebGLTexelConversions.h"
+#include "WebGLValidateStrings.h"
+#include <algorithm>
+
+// needed to check if current OS is lower than 10.7
+#if defined(MOZ_WIDGET_COCOA)
+#include "nsCocoaFeatures.h"
+#endif
+
+#include "mozilla/DebugOnly.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/ImageData.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/EndianUtils.h"
+
+namespace mozilla {
+
+static bool
+IsValidTexTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexTarget,
+ TexTarget* const out)
+{
+ uint8_t targetDims;
+
+ switch (rawTexTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ case LOCAL_GL_TEXTURE_CUBE_MAP:
+ targetDims = 2;
+ break;
+
+ case LOCAL_GL_TEXTURE_3D:
+ case LOCAL_GL_TEXTURE_2D_ARRAY:
+ if (!webgl->IsWebGL2())
+ return false;
+
+ targetDims = 3;
+ break;
+
+ default:
+ return false;
+ }
+
+ // Some funcs (like GenerateMipmap) doesn't know the dimension, so don't check it.
+ if (funcDims && targetDims != funcDims)
+ return false;
+
+ *out = rawTexTarget;
+ return true;
+}
+
+static bool
+IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageTarget,
+ TexImageTarget* const out)
+{
+ uint8_t targetDims;
+
+ switch (rawTexImageTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ targetDims = 2;
+ break;
+
+ case LOCAL_GL_TEXTURE_3D:
+ case LOCAL_GL_TEXTURE_2D_ARRAY:
+ if (!webgl->IsWebGL2())
+ return false;
+
+ targetDims = 3;
+ break;
+
+ default:
+ return false;
+ }
+
+ if (targetDims != funcDims)
+ return false;
+
+ *out = rawTexImageTarget;
+ return true;
+}
+
+bool
+ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
+ GLenum rawTexTarget, TexTarget* const out_texTarget,
+ WebGLTexture** const out_tex)
+{
+ if (webgl->IsContextLost())
+ return false;
+
+ TexTarget texTarget;
+ if (!IsValidTexTarget(webgl, funcDims, rawTexTarget, &texTarget)) {
+ webgl->ErrorInvalidEnum("%s: Invalid texTarget.", funcName);
+ return false;
+ }
+
+ WebGLTexture* tex = webgl->ActiveBoundTextureForTarget(texTarget);
+ if (!tex) {
+ webgl->ErrorInvalidOperation("%s: No texture is bound to this target.", funcName);
+ return false;
+ }
+
+ *out_texTarget = texTarget;
+ *out_tex = tex;
+ return true;
+}
+
+bool
+ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
+ GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
+ WebGLTexture** const out_tex)
+{
+ if (webgl->IsContextLost())
+ return false;
+
+ TexImageTarget texImageTarget;
+ if (!IsValidTexImageTarget(webgl, funcDims, rawTexImageTarget, &texImageTarget)) {
+ webgl->ErrorInvalidEnum("%s: Invalid texImageTarget.", funcName);
+ return false;
+ }
+
+ WebGLTexture* tex = webgl->ActiveBoundTextureForTexImageTarget(texImageTarget);
+ if (!tex) {
+ webgl->ErrorInvalidOperation("%s: No texture is bound to this target.", funcName);
+ return false;
+ }
+
+ *out_texImageTarget = texImageTarget;
+ *out_tex = tex;
+ return true;
+}
+
+/*virtual*/ bool
+WebGLContext::IsTexParamValid(GLenum pname) const
+{
+ switch (pname) {
+ case LOCAL_GL_TEXTURE_MIN_FILTER:
+ case LOCAL_GL_TEXTURE_MAG_FILTER:
+ case LOCAL_GL_TEXTURE_WRAP_S:
+ case LOCAL_GL_TEXTURE_WRAP_T:
+ return true;
+
+ case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ return IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic);
+
+ default:
+ return false;
+ }
+}
+
+void
+WebGLContext::InvalidateResolveCacheForTextureWithTexUnit(const GLuint texUnit)
+{
+ if (mBound2DTextures[texUnit])
+ mBound2DTextures[texUnit]->InvalidateResolveCache();
+ if (mBoundCubeMapTextures[texUnit])
+ mBoundCubeMapTextures[texUnit]->InvalidateResolveCache();
+ if (mBound3DTextures[texUnit])
+ mBound3DTextures[texUnit]->InvalidateResolveCache();
+ if (mBound2DArrayTextures[texUnit])
+ mBound2DArrayTextures[texUnit]->InvalidateResolveCache();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// GL calls
+
+void
+WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
+{
+ if (IsContextLost())
+ return;
+
+ if (newTex && !ValidateObject("bindTexture", *newTex))
+ return;
+
+ // Need to check rawTarget first before comparing against newTex->Target() as
+ // newTex->Target() returns a TexTarget, which will assert on invalid value.
+ WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
+ switch (rawTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ currentTexPtr = &mBound2DTextures[mActiveTexture];
+ break;
+
+ case LOCAL_GL_TEXTURE_CUBE_MAP:
+ currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
+ break;
+
+ case LOCAL_GL_TEXTURE_3D:
+ if (IsWebGL2())
+ currentTexPtr = &mBound3DTextures[mActiveTexture];
+ break;
+
+ case LOCAL_GL_TEXTURE_2D_ARRAY:
+ if (IsWebGL2())
+ currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
+ break;
+ }
+
+ if (!currentTexPtr) {
+ ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
+ return;
+ }
+
+ const TexTarget texTarget(rawTarget);
+
+ MakeContextCurrent();
+
+ if (newTex) {
+ if (!newTex->BindTexture(texTarget))
+ return;
+ } else {
+ gl->fBindTexture(texTarget.get(), 0);
+ }
+
+ *currentTexPtr = newTex;
+}
+
+void
+WebGLContext::GenerateMipmap(GLenum rawTexTarget)
+{
+ const char funcName[] = "generateMipmap";
+ const uint8_t funcDims = 0;
+
+ TexTarget texTarget;
+ WebGLTexture* tex;
+ if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
+ return;
+
+ tex->GenerateMipmap(texTarget);
+}
+
+JS::Value
+WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
+{
+ const char funcName[] = "getTexParameter";
+ const uint8_t funcDims = 0;
+
+ TexTarget texTarget;
+ WebGLTexture* tex;
+ if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
+ return JS::NullValue();
+
+ if (!IsTexParamValid(pname)) {
+ ErrorInvalidEnumInfo("getTexParameter: pname", pname);
+ return JS::NullValue();
+ }
+
+ return tex->GetTexParameter(texTarget, pname);
+}
+
+bool
+WebGLContext::IsTexture(WebGLTexture* tex)
+{
+ if (!ValidateIsObject("isTexture", tex))
+ return false;
+
+ return tex->IsTexture();
+}
+
+void
+WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname,
+ const FloatOrInt& param)
+{
+ const char funcName[] = "texParameter";
+ const uint8_t funcDims = 0;
+
+ TexTarget texTarget;
+ WebGLTexture* tex;
+ if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
+ return;
+
+ tex->TexParameter(texTarget, pname, param);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Uploads
+
+void
+WebGLContext::CompressedTexImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
+ GLint level, GLenum internalFormat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border,
+ const TexImageSource& src)
+{
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
+ border, src);
+}
+
+void
+WebGLContext::CompressedTexSubImage(const char* funcName, uint8_t funcDims,
+ GLenum rawTarget, GLint level, GLint xOffset,
+ GLint yOffset, GLint zOffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum unpackFormat,
+ const TexImageSource& src)
+{
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
+ height, depth, unpackFormat, src);
+}
+
+////
+
+void
+WebGLContext::CopyTexImage2D(GLenum rawTarget, GLint level, GLenum internalFormat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border)
+{
+ const char funcName[] = "copyTexImage2D";
+ const uint8_t funcDims = 2;
+
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ tex->CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
+}
+
+void
+WebGLContext::CopyTexSubImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
+ GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
+ GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
+ height);
+}
+
+////
+
+void
+WebGLContext::TexImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
+ GLint level, GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLint border, GLenum unpackFormat,
+ GLenum unpackType, const TexImageSource& src)
+{
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ const webgl::PackingInfo pi = {unpackFormat, unpackType};
+ tex->TexImage(funcName, target, level, internalFormat, width, height, depth, border,
+ pi, src);
+}
+
+void
+WebGLContext::TexSubImage(const char* funcName, uint8_t funcDims, GLenum rawTarget,
+ GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum unpackFormat, GLenum unpackType,
+ const TexImageSource& src)
+{
+ TexImageTarget target;
+ WebGLTexture* tex;
+ if (!ValidateTexImageTarget(this, funcName, funcDims, rawTarget, &target, &tex))
+ return;
+
+ const webgl::PackingInfo pi = {unpackFormat, unpackType};
+ tex->TexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width, height,
+ depth, pi, src);
+}
+
+} // namespace mozilla