зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1188540 - Forward texture-related functions to WebGLTexture. - r=kamidphish
This commit is contained in:
Родитель
0f1cdda9e1
Коммит
f0e28e9429
|
@ -357,15 +357,10 @@ public:
|
|||
private:
|
||||
WebGL2Context();
|
||||
|
||||
JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) override;
|
||||
virtual bool IsTexParamValid(GLenum pname) const override;
|
||||
|
||||
void UpdateBoundQuery(GLenum target, WebGLQuery* query);
|
||||
|
||||
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
|
||||
bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* info);
|
||||
|
||||
// CreateVertexArrayImpl is assumed to be infallible.
|
||||
virtual WebGLVertexArray* CreateVertexArrayImpl() override;
|
||||
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;
|
||||
|
|
|
@ -10,485 +10,126 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
bool
|
||||
WebGL2Context::ValidateSizedInternalFormat(GLenum internalformat, const char* info)
|
||||
{
|
||||
switch (internalformat) {
|
||||
// Sized Internal Formats
|
||||
// https://www.khronos.org/opengles/sdk/docs/man3/html/glTexStorage2D.xhtml
|
||||
case LOCAL_GL_R8:
|
||||
case LOCAL_GL_R8_SNORM:
|
||||
case LOCAL_GL_R16F:
|
||||
case LOCAL_GL_R32F:
|
||||
case LOCAL_GL_R8UI:
|
||||
case LOCAL_GL_R8I:
|
||||
case LOCAL_GL_R16UI:
|
||||
case LOCAL_GL_R16I:
|
||||
case LOCAL_GL_R32UI:
|
||||
case LOCAL_GL_R32I:
|
||||
case LOCAL_GL_RG8:
|
||||
case LOCAL_GL_RG8_SNORM:
|
||||
case LOCAL_GL_RG16F:
|
||||
case LOCAL_GL_RG32F:
|
||||
case LOCAL_GL_RG8UI:
|
||||
case LOCAL_GL_RG8I:
|
||||
case LOCAL_GL_RG16UI:
|
||||
case LOCAL_GL_RG16I:
|
||||
case LOCAL_GL_RG32UI:
|
||||
case LOCAL_GL_RG32I:
|
||||
case LOCAL_GL_RGB8:
|
||||
case LOCAL_GL_SRGB8:
|
||||
case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_RGB8_SNORM:
|
||||
case LOCAL_GL_R11F_G11F_B10F:
|
||||
case LOCAL_GL_RGB9_E5:
|
||||
case LOCAL_GL_RGB16F:
|
||||
case LOCAL_GL_RGB32F:
|
||||
case LOCAL_GL_RGB8UI:
|
||||
case LOCAL_GL_RGB8I:
|
||||
case LOCAL_GL_RGB16UI:
|
||||
case LOCAL_GL_RGB16I:
|
||||
case LOCAL_GL_RGB32UI:
|
||||
case LOCAL_GL_RGB32I:
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_SRGB8_ALPHA8:
|
||||
case LOCAL_GL_RGBA8_SNORM:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB10_A2:
|
||||
case LOCAL_GL_RGBA16F:
|
||||
case LOCAL_GL_RGBA32F:
|
||||
case LOCAL_GL_RGBA8UI:
|
||||
case LOCAL_GL_RGBA8I:
|
||||
case LOCAL_GL_RGB10_A2UI:
|
||||
case LOCAL_GL_RGBA16UI:
|
||||
case LOCAL_GL_RGBA16I:
|
||||
case LOCAL_GL_RGBA32I:
|
||||
case LOCAL_GL_RGBA32UI:
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
case LOCAL_GL_DEPTH_COMPONENT24:
|
||||
case LOCAL_GL_DEPTH_COMPONENT32F:
|
||||
case LOCAL_GL_DEPTH24_STENCIL8:
|
||||
case LOCAL_GL_DEPTH32F_STENCIL8:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsCompressedTextureFormat(internalformat))
|
||||
return true;
|
||||
|
||||
nsCString name;
|
||||
EnumName(internalformat, &name);
|
||||
ErrorInvalidEnum("%s: invalid internal format %s", info, name.get());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Validates parameters to texStorage{2D,3D} */
|
||||
bool
|
||||
WebGL2Context::ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* info)
|
||||
{
|
||||
// GL_INVALID_OPERATION is generated if the default texture object is curently bound to target.
|
||||
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
|
||||
if (!tex) {
|
||||
ErrorInvalidOperation("%s: no texture is bound to target %s", info, EnumName(target));
|
||||
return false;
|
||||
}
|
||||
|
||||
// GL_INVALID_OPERATION is generated if the texture object currently bound to target already has
|
||||
// GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.
|
||||
if (tex->IsImmutable()) {
|
||||
ErrorInvalidOperation("%s: texture bound to target %s is already immutable", info, EnumName(target));
|
||||
return false;
|
||||
}
|
||||
|
||||
// GL_INVALID_ENUM is generated if internalformat is not a valid sized internal format.
|
||||
if (!ValidateSizedInternalFormat(internalformat, info))
|
||||
return false;
|
||||
|
||||
// GL_INVALID_VALUE is generated if width, height or levels are less than 1.
|
||||
if (width < 1) { ErrorInvalidValue("%s: width is < 1", info); return false; }
|
||||
if (height < 1) { ErrorInvalidValue("%s: height is < 1", info); return false; }
|
||||
if (depth < 1) { ErrorInvalidValue("%s: depth is < 1", info); return false; }
|
||||
if (levels < 1) { ErrorInvalidValue("%s: levels is < 1", info); return false; }
|
||||
|
||||
// GL_INVALID_OPERATION is generated if levels is greater than floor(log2(max(width, height, depth)))+1.
|
||||
if (FloorLog2(std::max(std::max(width, height), depth)) + 1 < levels) {
|
||||
ErrorInvalidOperation("%s: too many levels for given texture dimensions", info);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Texture objects
|
||||
|
||||
void
|
||||
WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
|
||||
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
|
||||
{
|
||||
if (IsContextLost())
|
||||
const char funcName[] = "TexStorage2D";
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
|
||||
return;
|
||||
|
||||
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
|
||||
if (target != LOCAL_GL_TEXTURE_2D && target != LOCAL_GL_TEXTURE_CUBE_MAP)
|
||||
return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP");
|
||||
|
||||
if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
|
||||
return;
|
||||
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
gl->fTexStorage2D(target, levels, internalformat, width, height);
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
if (error) {
|
||||
return GenerateWarning("texStorage2D generated error %s", ErrorName(error));
|
||||
}
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
|
||||
tex->SetImmutable();
|
||||
|
||||
const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
|
||||
GLsizei w = width;
|
||||
GLsizei h = height;
|
||||
for (size_t l = 0; l < size_t(levels); l++) {
|
||||
for (size_t f = 0; f < facesCount; f++) {
|
||||
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, f),
|
||||
l, w, h, 1,
|
||||
internalformat,
|
||||
WebGLImageDataStatus::UninitializedImageData);
|
||||
}
|
||||
w = std::max(1, w / 2);
|
||||
h = std::max(1, h / 2);
|
||||
}
|
||||
tex->TexStorage2D(texTarget, levels, internalFormat, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
|
||||
WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth)
|
||||
{
|
||||
if (IsContextLost())
|
||||
const char funcName[] = "texStorage3D";
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
|
||||
return;
|
||||
|
||||
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
|
||||
if (target != LOCAL_GL_TEXTURE_3D)
|
||||
return ErrorInvalidEnum("texStorage3D: target is not TEXTURE_3D");
|
||||
|
||||
if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
|
||||
return;
|
||||
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
if (error) {
|
||||
return GenerateWarning("texStorage3D generated error %s", ErrorName(error));
|
||||
}
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
|
||||
tex->SetImmutable();
|
||||
|
||||
GLsizei w = width;
|
||||
GLsizei h = height;
|
||||
GLsizei d = depth;
|
||||
for (size_t l = 0; l < size_t(levels); l++) {
|
||||
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, 0),
|
||||
l, w, h, d,
|
||||
internalformat,
|
||||
WebGLImageDataStatus::UninitializedImageData);
|
||||
w = std::max(1, w >> 1);
|
||||
h = std::max(1, h >> 1);
|
||||
d = std::max(1, d >> 1);
|
||||
}
|
||||
tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLenum format, GLenum type,
|
||||
const dom::Nullable<dom::ArrayBufferView> &pixels,
|
||||
ErrorResult& rv)
|
||||
GLint border, GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
void* data;
|
||||
size_t dataLength;
|
||||
js::Scalar::Type jsArrayType;
|
||||
if (pixels.IsNull()) {
|
||||
data = nullptr;
|
||||
dataLength = 0;
|
||||
jsArrayType = js::Scalar::MaxTypedArrayViewType;
|
||||
} else {
|
||||
const dom::ArrayBufferView& view = pixels.Value();
|
||||
view.ComputeLengthAndData();
|
||||
|
||||
data = view.Data();
|
||||
dataLength = view.Length();
|
||||
jsArrayType = view.Type();
|
||||
}
|
||||
|
||||
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
|
||||
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
|
||||
|
||||
if (!ValidateTexImageTarget(target, func, dims))
|
||||
return;
|
||||
|
||||
TexImageTarget texImageTarget = target;
|
||||
|
||||
if (!ValidateTexImage(texImageTarget, level, internalformat,
|
||||
0, 0, 0,
|
||||
width, height, depth,
|
||||
border, format, type, func, dims))
|
||||
const char funcName[] = "texImage3D";
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ValidateTexInputData(type, jsArrayType, func, dims))
|
||||
return;
|
||||
|
||||
TexInternalFormat effectiveInternalFormat =
|
||||
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
|
||||
|
||||
if (effectiveInternalFormat == LOCAL_GL_NONE) {
|
||||
return ErrorInvalidOperation("texImage3D: bad combination of internalformat and type");
|
||||
}
|
||||
|
||||
// we need to find the exact sized format of the source data. Slightly abusing
|
||||
// EffectiveInternalFormatFromInternalFormatAndType for that purpose. Really, an unsized source format
|
||||
// is the same thing as an unsized internalformat.
|
||||
TexInternalFormat effectiveSourceFormat =
|
||||
EffectiveInternalFormatFromInternalFormatAndType(format, type);
|
||||
MOZ_ASSERT(effectiveSourceFormat != LOCAL_GL_NONE); // should have validated format/type combo earlier
|
||||
const size_t srcbitsPerTexel = GetBitsPerTexel(effectiveSourceFormat);
|
||||
MOZ_ASSERT((srcbitsPerTexel % 8) == 0); // should not have compressed formats here.
|
||||
size_t srcTexelSize = srcbitsPerTexel / 8;
|
||||
|
||||
CheckedUint32 checked_neededByteLength =
|
||||
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
uint32_t bytesNeeded = checked_neededByteLength.value();
|
||||
|
||||
if (dataLength && dataLength < bytesNeeded)
|
||||
return ErrorInvalidOperation("texImage3D: not enough data for operation (need %d, have %d)",
|
||||
bytesNeeded, dataLength);
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
|
||||
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("texImage3D: no texture is bound to this target");
|
||||
|
||||
if (tex->IsImmutable()) {
|
||||
return ErrorInvalidOperation(
|
||||
"texImage3D: disallowed because the texture "
|
||||
"bound to this target has already been made immutable by texStorage3D");
|
||||
}
|
||||
|
||||
GLenum driverType = LOCAL_GL_NONE;
|
||||
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||
GLenum driverFormat = LOCAL_GL_NONE;
|
||||
DriverFormatsFromEffectiveInternalFormat(gl,
|
||||
effectiveInternalFormat,
|
||||
&driverInternalFormat,
|
||||
&driverFormat,
|
||||
&driverType);
|
||||
|
||||
MakeContextCurrent();
|
||||
GetAndFlushUnderlyingGLErrors();
|
||||
gl->fTexImage3D(texImageTarget.get(), level,
|
||||
driverInternalFormat,
|
||||
width, height, depth,
|
||||
0, driverFormat, driverType,
|
||||
data);
|
||||
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||
if (error) {
|
||||
return GenerateWarning("texImage3D generated error %s", ErrorName(error));
|
||||
}
|
||||
|
||||
tex->SetImageInfo(texImageTarget, level,
|
||||
width, height, depth,
|
||||
effectiveInternalFormat,
|
||||
data ? WebGLImageDataStatus::InitializedImageData
|
||||
: WebGLImageDataStatus::UninitializedImageData);
|
||||
tex->TexImage3D(texImageTarget, level, internalFormat, width, height, depth, border,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type,
|
||||
const dom::Nullable<dom::ArrayBufferView>& pixels,
|
||||
ErrorResult& rv)
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (pixels.IsNull())
|
||||
return ErrorInvalidValue("texSubImage3D: pixels must not be null!");
|
||||
|
||||
const dom::ArrayBufferView& view = pixels.Value();
|
||||
view.ComputeLengthAndData();
|
||||
|
||||
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
|
||||
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
|
||||
|
||||
if (!ValidateTexImageTarget(rawTarget, func, dims))
|
||||
return;
|
||||
|
||||
TexImageTarget texImageTarget(rawTarget);
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
|
||||
if (!tex) {
|
||||
return ErrorInvalidOperation("texSubImage3D: no texture bound on active texture unit");
|
||||
}
|
||||
|
||||
if (!tex->HasImageInfoAt(texImageTarget, level)) {
|
||||
return ErrorInvalidOperation("texSubImage3D: no previously defined texture image");
|
||||
}
|
||||
|
||||
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
|
||||
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
|
||||
TexInternalFormat existingUnsizedInternalFormat = LOCAL_GL_NONE;
|
||||
TexType existingType = LOCAL_GL_NONE;
|
||||
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(existingEffectiveInternalFormat,
|
||||
&existingUnsizedInternalFormat,
|
||||
&existingType);
|
||||
|
||||
if (!ValidateTexImage(texImageTarget, level, existingEffectiveInternalFormat.get(),
|
||||
xoffset, yoffset, zoffset,
|
||||
width, height, depth,
|
||||
0, format, type, func, dims))
|
||||
const char funcName[] = "texSubImage3D";
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != existingType) {
|
||||
return ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
|
||||
}
|
||||
|
||||
js::Scalar::Type jsArrayType = view.Type();
|
||||
void* data = view.Data();
|
||||
size_t dataLength = view.Length();
|
||||
|
||||
if (!ValidateTexInputData(type, jsArrayType, func, dims))
|
||||
return;
|
||||
|
||||
const size_t bitsPerTexel = GetBitsPerTexel(existingEffectiveInternalFormat);
|
||||
MOZ_ASSERT((bitsPerTexel % 8) == 0); // should not have compressed formats here.
|
||||
size_t srcTexelSize = bitsPerTexel / 8;
|
||||
|
||||
if (width == 0 || height == 0 || depth == 0)
|
||||
return; // no effect, we better return right now
|
||||
|
||||
CheckedUint32 checked_neededByteLength =
|
||||
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
|
||||
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
|
||||
|
||||
uint32_t bytesNeeded = checked_neededByteLength.value();
|
||||
|
||||
if (dataLength < bytesNeeded)
|
||||
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
bool coversWholeImage = xoffset == 0 &&
|
||||
yoffset == 0 &&
|
||||
zoffset == 0 &&
|
||||
width == imageInfo.Width() &&
|
||||
height == imageInfo.Height() &&
|
||||
depth == imageInfo.Depth();
|
||||
if (coversWholeImage) {
|
||||
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
|
||||
} else {
|
||||
if (!tex->EnsureInitializedImageData(texImageTarget, level))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum driverType = LOCAL_GL_NONE;
|
||||
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||
GLenum driverFormat = LOCAL_GL_NONE;
|
||||
DriverFormatsFromEffectiveInternalFormat(gl,
|
||||
existingEffectiveInternalFormat,
|
||||
&driverInternalFormat,
|
||||
&driverFormat,
|
||||
&driverType);
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fTexSubImage3D(texImageTarget.get(), level,
|
||||
xoffset, yoffset, zoffset,
|
||||
width, height, depth,
|
||||
driverFormat, driverType, data);
|
||||
tex->TexSubImage3D(texImageTarget, level, xOffset, yOffset, zOffset, width, height,
|
||||
depth, unpackFormat, unpackType, maybeView, &out_rv);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLenum format, GLenum type, dom::ImageData* data,
|
||||
ErrorResult& rv)
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
GenerateWarning("texSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
GenerateWarning("copyTexSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLint border, GLsizei imageSize, const dom::ArrayBufferView& data)
|
||||
GLint border, GLsizei imageSize, const dom::ArrayBufferView& view)
|
||||
{
|
||||
GenerateWarning("compressedTexImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
WebGL2Context::CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei imageSize, const dom::ArrayBufferView& data)
|
||||
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferView& view)
|
||||
{
|
||||
GenerateWarning("compressedTexSubImage3D: Not implemented.");
|
||||
}
|
||||
|
||||
JS::Value
|
||||
WebGL2Context::GetTexParameterInternal(const TexTarget& target, GLenum pname)
|
||||
bool
|
||||
WebGL2Context::IsTexParamValid(GLenum pname) const
|
||||
{
|
||||
switch (pname) {
|
||||
case LOCAL_GL_TEXTURE_BASE_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||
case LOCAL_GL_TEXTURE_MAX_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_A:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_B:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_G:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_R:
|
||||
case LOCAL_GL_TEXTURE_WRAP_R:
|
||||
{
|
||||
GLint i = 0;
|
||||
gl->fGetTexParameteriv(target.get(), pname, &i);
|
||||
return JS::NumberValue(uint32_t(i));
|
||||
}
|
||||
case LOCAL_GL_TEXTURE_BASE_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||
case LOCAL_GL_TEXTURE_MAX_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_A:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_B:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_G:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_R:
|
||||
case LOCAL_GL_TEXTURE_WRAP_R:
|
||||
case LOCAL_GL_TEXTURE_MAX_LOD:
|
||||
case LOCAL_GL_TEXTURE_MIN_LOD:
|
||||
return true;
|
||||
|
||||
case LOCAL_GL_TEXTURE_MAX_LOD:
|
||||
case LOCAL_GL_TEXTURE_MIN_LOD:
|
||||
{
|
||||
GLfloat f = 0.0f;
|
||||
gl->fGetTexParameterfv(target.get(), pname, &f);
|
||||
return JS::NumberValue(float(f));
|
||||
}
|
||||
default:
|
||||
return WebGLContext::IsTexParamValid(pname);
|
||||
}
|
||||
|
||||
return WebGLContext::GetTexParameterInternal(target, pname);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -1821,158 +1821,6 @@ WebGLContext::DidRefresh()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
|
||||
GLint level, GLenum internalFormat,
|
||||
GLenum format, GLenum type,
|
||||
mozilla::dom::Element& elt)
|
||||
{
|
||||
if (type == LOCAL_GL_HALF_FLOAT_OES &&
|
||||
!gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float))
|
||||
{
|
||||
type = LOCAL_GL_HALF_FLOAT;
|
||||
}
|
||||
|
||||
if (!ValidateTexImageFormatAndType(format, type,
|
||||
WebGLTexImageFunc::TexImage,
|
||||
WebGLTexDimensions::Tex2D))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
|
||||
if (!video)
|
||||
return false;
|
||||
|
||||
uint16_t readyState;
|
||||
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
|
||||
readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)
|
||||
{
|
||||
//No frame inside, just return
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it doesn't have a principal, just bail
|
||||
nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
|
||||
if (!principal)
|
||||
return false;
|
||||
|
||||
mozilla::layers::ImageContainer* container = video->GetImageContainer();
|
||||
if (!container)
|
||||
return false;
|
||||
|
||||
if (video->GetCORSMode() == CORS_NONE) {
|
||||
bool subsumes;
|
||||
nsresult rv = mCanvasElement->NodePrincipal()->Subsumes(principal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
GenerateWarning("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
|
||||
"See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AutoLockImage lockedImage(container);
|
||||
Image* srcImage = lockedImage.GetImage();
|
||||
if (!srcImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gl->MakeCurrent();
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
|
||||
|
||||
const WebGLTexture::ImageInfo& info = tex->ImageInfoAt(texImageTarget, 0);
|
||||
bool dimensionsMatch = info.Width() == srcImage->GetSize().width &&
|
||||
info.Height() == srcImage->GetSize().height;
|
||||
if (!dimensionsMatch) {
|
||||
// we need to allocation
|
||||
gl->fTexImage2D(texImageTarget.get(), level, internalFormat,
|
||||
srcImage->GetSize().width, srcImage->GetSize().height,
|
||||
0, format, type, nullptr);
|
||||
}
|
||||
|
||||
const gl::OriginPos destOrigin = mPixelStoreFlipY ? gl::OriginPos::BottomLeft
|
||||
: gl::OriginPos::TopLeft;
|
||||
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage,
|
||||
srcImage->GetSize(),
|
||||
tex->mGLName,
|
||||
texImageTarget.get(),
|
||||
destOrigin);
|
||||
if (ok) {
|
||||
TexInternalFormat effectiveInternalFormat =
|
||||
EffectiveInternalFormatFromInternalFormatAndType(internalFormat,
|
||||
type);
|
||||
MOZ_ASSERT(effectiveInternalFormat != LOCAL_GL_NONE);
|
||||
tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width,
|
||||
srcImage->GetSize().height, 1,
|
||||
effectiveInternalFormat,
|
||||
WebGLImageDataStatus::InitializedImageData);
|
||||
tex->Bind(TexImageTargetToTexTarget(texImageTarget));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLenum format, GLenum type,
|
||||
dom::Element* elt, ErrorResult* const out_rv)
|
||||
{
|
||||
// TODO: Consolidate all the parameter validation
|
||||
// checks. Instead of spreading out the cheks in multple
|
||||
// places, consolidate into one spot.
|
||||
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateTexImageTarget(rawTexImageTarget,
|
||||
WebGLTexImageFunc::TexSubImage,
|
||||
WebGLTexDimensions::Tex2D))
|
||||
{
|
||||
ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
const TexImageTarget texImageTarget(rawTexImageTarget);
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texSubImage2D: level is negative");
|
||||
|
||||
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
|
||||
if (level > maxLevel) {
|
||||
ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d",
|
||||
level, maxLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
|
||||
|
||||
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
|
||||
const TexInternalFormat internalFormat = imageInfo.EffectiveInternalFormat();
|
||||
|
||||
// Trying to handle the video by GPU directly first
|
||||
if (TexImageFromVideoElement(texImageTarget, level,
|
||||
internalFormat.get(), format, type, *elt))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> data;
|
||||
WebGLTexelFormat srcFormat;
|
||||
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(*elt);
|
||||
*out_rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
|
||||
if (out_rv->Failed() || !data)
|
||||
return;
|
||||
|
||||
gfx::IntSize size = data->GetSize();
|
||||
uint32_t byteLength = data->Stride() * size.height;
|
||||
TexSubImage2D_base(texImageTarget.get(), level, xoffset, yoffset, size.width,
|
||||
size.height, data->Stride(), format, type, data->GetData(),
|
||||
byteLength, js::Scalar::MaxTypedArrayViewType, srcFormat,
|
||||
res.mIsPremultiplied);
|
||||
}
|
||||
|
||||
size_t
|
||||
RoundUpToMultipleOf(size_t value, size_t multiple)
|
||||
{
|
||||
|
@ -1980,6 +1828,12 @@ RoundUpToMultipleOf(size_t value, size_t multiple)
|
|||
return overshoot - (overshoot % multiple);
|
||||
}
|
||||
|
||||
CheckedUint32
|
||||
RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y)
|
||||
{
|
||||
return ((x + y - 1) / y) * y;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WebGLContext::ScopedMaskWorkaround::ScopedMaskWorkaround(WebGLContext& webgl)
|
||||
|
|
|
@ -282,9 +282,6 @@ public:
|
|||
// Returns hex formatted version of glenum if glenum is unknown.
|
||||
static void EnumName(GLenum glenum, nsACString* out_name);
|
||||
|
||||
bool IsCompressedTextureFormat(GLenum format);
|
||||
bool IsTextureFormatCompressed(TexInternalFormat format);
|
||||
|
||||
void DummyFramebufferOperation(const char* funcName);
|
||||
|
||||
WebGLTexture* ActiveBoundTextureForTarget(const TexTarget texTarget) const {
|
||||
|
@ -374,13 +371,11 @@ public:
|
|||
dom::Nullable< nsTArray<nsString> >& retval);
|
||||
void GetExtension(JSContext* cx, const nsAString& name,
|
||||
JS::MutableHandle<JSObject*> retval, ErrorResult& rv);
|
||||
void ActiveTexture(GLenum texture);
|
||||
void AttachShader(WebGLProgram* prog, WebGLShader* shader);
|
||||
void BindAttribLocation(WebGLProgram* prog, GLuint location,
|
||||
const nsAString& name);
|
||||
void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
|
||||
void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
|
||||
void BindTexture(GLenum target, WebGLTexture* tex);
|
||||
void BindVertexArray(WebGLVertexArray* vao);
|
||||
void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
|
||||
void BlendEquation(GLenum mode);
|
||||
|
@ -397,24 +392,9 @@ public:
|
|||
void CompileShader(WebGLShader* shader);
|
||||
void CompileShaderANGLE(WebGLShader* shader);
|
||||
void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource);
|
||||
void CompressedTexImage2D(GLenum target, GLint level,
|
||||
GLenum internalformat, GLsizei width,
|
||||
GLsizei height, GLint border,
|
||||
const dom::ArrayBufferView& view);
|
||||
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLsizei width,
|
||||
GLsizei height, GLenum format,
|
||||
const dom::ArrayBufferView& view);
|
||||
void CopyTexImage2D(GLenum texImageTarget, GLint level,
|
||||
GLenum internalformat, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height, GLint border);
|
||||
void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
already_AddRefed<WebGLFramebuffer> CreateFramebuffer();
|
||||
already_AddRefed<WebGLProgram> CreateProgram();
|
||||
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
|
||||
already_AddRefed<WebGLTexture> CreateTexture();
|
||||
already_AddRefed<WebGLShader> CreateShader(GLenum type);
|
||||
already_AddRefed<WebGLVertexArray> CreateVertexArray();
|
||||
void CullFace(GLenum face);
|
||||
|
@ -423,7 +403,6 @@ public:
|
|||
void DeleteRenderbuffer(WebGLRenderbuffer* rb);
|
||||
void DeleteShader(WebGLShader* shader);
|
||||
void DeleteVertexArray(WebGLVertexArray* vao);
|
||||
void DeleteTexture(WebGLTexture* tex);
|
||||
void DepthFunc(GLenum func);
|
||||
void DepthMask(WebGLboolean b);
|
||||
void DepthRange(GLclampf zNear, GLclampf zFar);
|
||||
|
@ -442,7 +421,6 @@ public:
|
|||
GLenum attachment, const char* funcName);
|
||||
|
||||
void FrontFace(GLenum mode);
|
||||
void GenerateMipmap(GLenum target);
|
||||
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
|
||||
GLuint index);
|
||||
already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram* prog,
|
||||
|
@ -508,13 +486,6 @@ public:
|
|||
void GetShaderInfoLog(WebGLShader* shader, nsAString& retval);
|
||||
void GetShaderSource(WebGLShader* shader, nsAString& retval);
|
||||
void GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval);
|
||||
JS::Value GetTexParameter(GLenum target, GLenum pname);
|
||||
|
||||
void GetTexParameter(JSContext*, GLenum target, GLenum pname,
|
||||
JS::MutableHandle<JS::Value> retval)
|
||||
{
|
||||
retval.set(GetTexParameter(target, pname));
|
||||
}
|
||||
|
||||
JS::Value GetUniform(JSContext* cx, WebGLProgram* prog,
|
||||
WebGLUniformLocation* loc);
|
||||
|
@ -534,7 +505,6 @@ public:
|
|||
bool IsProgram(WebGLProgram* prog);
|
||||
bool IsRenderbuffer(WebGLRenderbuffer* rb);
|
||||
bool IsShader(WebGLShader* shader);
|
||||
bool IsTexture(WebGLTexture* tex);
|
||||
bool IsVertexArray(WebGLVertexArray* vao);
|
||||
void LineWidth(GLfloat width);
|
||||
void LinkProgram(WebGLProgram* prog);
|
||||
|
@ -561,105 +531,6 @@ public:
|
|||
void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
|
||||
GLenum dppass);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum format,
|
||||
GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
|
||||
ErrorResult& rv);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum format, GLenum type, dom::ImageData* pixels,
|
||||
ErrorResult& rv);
|
||||
// Allow whatever element types the bindings are willing to pass
|
||||
// us in TexImage2D
|
||||
bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLenum format,
|
||||
GLenum type, mozilla::dom::Element& image);
|
||||
|
||||
template<class ElementType>
|
||||
void TexImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLenum internalFormat, GLenum format, GLenum type,
|
||||
ElementType& elt, ErrorResult& rv)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateTexImageTarget(rawTexImageTarget,
|
||||
WebGLTexImageFunc::TexImage,
|
||||
WebGLTexDimensions::Tex2D))
|
||||
{
|
||||
ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
const TexImageTarget texImageTarget(rawTexImageTarget);
|
||||
|
||||
if (level < 0)
|
||||
return ErrorInvalidValue("texImage2D: level is negative");
|
||||
|
||||
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
|
||||
if (level > maxLevel) {
|
||||
ErrorInvalidValue("texImage2D: level %d is too large, max is %d",
|
||||
level, maxLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
|
||||
|
||||
if (!tex)
|
||||
return ErrorInvalidOperation("no texture is bound to this target");
|
||||
|
||||
// Trying to handle the video by GPU directly first
|
||||
if (TexImageFromVideoElement(texImageTarget, level, internalFormat,
|
||||
format, type, elt))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> data;
|
||||
WebGLTexelFormat srcFormat;
|
||||
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
|
||||
rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
|
||||
if (rv.Failed() || !data)
|
||||
return;
|
||||
|
||||
gfx::IntSize size = data->GetSize();
|
||||
uint32_t byteLength = data->Stride() * size.height;
|
||||
return TexImage2D_base(texImageTarget, level, internalFormat,
|
||||
size.width, size.height, data->Stride(), 0,
|
||||
format, type, data->GetData(), byteLength,
|
||||
js::Scalar::MaxTypedArrayViewType, srcFormat,
|
||||
res.mIsPremultiplied);
|
||||
}
|
||||
|
||||
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
||||
TexParameter_base(target, pname, nullptr, ¶m);
|
||||
}
|
||||
void TexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
TexParameter_base(target, pname, ¶m, nullptr);
|
||||
}
|
||||
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const dom::Nullable<dom::ArrayBufferView>& pixels,
|
||||
ErrorResult& rv);
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLenum format, GLenum type,
|
||||
dom::ImageData* pixels, ErrorResult& rv);
|
||||
|
||||
void TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLenum format, GLenum type,
|
||||
dom::Element* elt, ErrorResult* const out_rv);
|
||||
|
||||
// Allow whatever element types the bindings are willing to pass
|
||||
// us in TexSubImage2D
|
||||
template<class ElementType>
|
||||
void TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
|
||||
GLint yoffset, GLenum format, GLenum type,
|
||||
ElementType& elt, ErrorResult& out_rv)
|
||||
{
|
||||
TexSubImage2D(rawTexImageTarget, level, xoffset, yoffset, format, type, &elt,
|
||||
&out_rv);
|
||||
}
|
||||
|
||||
void Uniform1i(WebGLUniformLocation* loc, GLint x);
|
||||
void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
|
||||
|
@ -940,6 +811,97 @@ private:
|
|||
bool ValidateCapabilityEnum(GLenum cap, const char* info);
|
||||
realGLboolean* GetStateTrackingSlot(GLenum cap);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Texture funcions (WebGLContextTextures.cpp)
|
||||
public:
|
||||
void ActiveTexture(GLenum texUnit);
|
||||
void BindTexture(GLenum texTarget, WebGLTexture* tex);
|
||||
already_AddRefed<WebGLTexture> CreateTexture();
|
||||
void DeleteTexture(WebGLTexture* tex);
|
||||
void GenerateMipmap(GLenum texTarget);
|
||||
|
||||
void GetTexParameter(JSContext*, GLenum texTarget, GLenum pname,
|
||||
JS::MutableHandle<JS::Value> retval)
|
||||
{
|
||||
retval.set(GetTexParameter(texTarget, pname));
|
||||
}
|
||||
|
||||
bool IsTexture(WebGLTexture* tex);
|
||||
|
||||
void TexParameterf(GLenum texTarget, GLenum pname, GLfloat param) {
|
||||
TexParameter_base(texTarget, pname, nullptr, ¶m);
|
||||
}
|
||||
|
||||
void TexParameteri(GLenum texTarget, GLenum pname, GLint param) {
|
||||
TexParameter_base(texTarget, pname, ¶m, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
JS::Value GetTexParameter(GLenum texTarget, GLenum pname);
|
||||
void TexParameter_base(GLenum texTarget, GLenum pname, GLint* maybeIntParam,
|
||||
GLfloat* maybeFloatParam);
|
||||
|
||||
virtual bool IsTexParamValid(GLenum pname) const;
|
||||
|
||||
// Upload funcs
|
||||
public:
|
||||
void CompressedTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border,
|
||||
const dom::ArrayBufferView& view);
|
||||
void CompressedTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height,
|
||||
GLenum unpackFormat, const dom::ArrayBufferView& view);
|
||||
|
||||
void CopyTexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv);
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLsizei width, GLsizei height, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv);
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv);
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
// Allow whatever element unpackTypes the bindings are willing to pass
|
||||
// us in Tex(Sub)Image2D
|
||||
template<typename ElementT>
|
||||
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, &elem,
|
||||
&out_rv);
|
||||
}
|
||||
template<typename ElementT>
|
||||
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, ElementT& elem,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
&elem, &out_rv);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vertices Feature (WebGLContextVertices.cpp)
|
||||
public:
|
||||
|
@ -1057,14 +1019,6 @@ protected:
|
|||
GLsizei depth, uint32_t pixelSize,
|
||||
uint32_t alignment);
|
||||
|
||||
virtual JS::Value GetTexParameterInternal(const TexTarget& target,
|
||||
GLenum pname);
|
||||
|
||||
// Returns x rounded to the next highest multiple of y.
|
||||
static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
|
||||
return ((x + y - 1) / y) * y;
|
||||
}
|
||||
|
||||
inline void InvalidateBufferFetching()
|
||||
{
|
||||
mBufferFetchingIsVerified = false;
|
||||
|
@ -1227,8 +1181,6 @@ protected:
|
|||
GLint width, GLint height, GLint depth,
|
||||
GLint border, GLenum format, GLenum type,
|
||||
WebGLTexImageFunc func, WebGLTexDimensions dims);
|
||||
bool ValidateTexImageTarget(GLenum texImageTarget, WebGLTexImageFunc func,
|
||||
WebGLTexDimensions dims);
|
||||
bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
|
||||
WebGLTexDimensions dims);
|
||||
bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
|
||||
|
@ -1272,24 +1224,6 @@ protected:
|
|||
|
||||
// helpers
|
||||
|
||||
// If jsArrayType is MaxTypedArrayViewType, it means no array.
|
||||
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width,
|
||||
GLsizei height, GLsizei srcStrideOrZero, GLint border,
|
||||
GLenum format, GLenum type, void* data,
|
||||
uint32_t byteLength, js::Scalar::Type jsArrayType,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied);
|
||||
void TexSubImage2D_base(GLenum texImageTarget, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLsizei width,
|
||||
GLsizei height, GLsizei srcStrideOrZero,
|
||||
GLenum format, GLenum type, void* pixels,
|
||||
uint32_t byteLength, js::Scalar::Type jsArrayType,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied);
|
||||
|
||||
void TexParameter_base(GLenum target, GLenum pname,
|
||||
GLint* const out_intParam,
|
||||
GLfloat* const out_floatParam);
|
||||
|
||||
bool ConvertImage(size_t width, size_t height, size_t srcStride,
|
||||
size_t dstStride, const uint8_t* src, uint8_t* dst,
|
||||
WebGLTexelFormat srcFormat, bool srcPremultiplied,
|
||||
|
@ -1321,11 +1255,6 @@ protected:
|
|||
RefPtr<gfx::DataSourceSurface>& imageOut,
|
||||
WebGLTexelFormat* format);
|
||||
|
||||
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
GLint level, TexInternalFormat internalFormat,
|
||||
GLint xoffset, GLint yoffset, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height, bool isSub);
|
||||
|
||||
// Returns false if `object` is null or not valid.
|
||||
template<class ObjectType>
|
||||
bool ValidateObject(const char* info, ObjectType* object);
|
||||
|
@ -1382,14 +1311,6 @@ protected:
|
|||
GLenum CheckedBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
|
||||
GLenum usage);
|
||||
|
||||
/** Like glTexImage2D, but if the call may change the texture size, checks
|
||||
* any GL error generated by this glTexImage2D call and returns it.
|
||||
*/
|
||||
GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
TexInternalFormat internalFormat, GLsizei width,
|
||||
GLsizei height, GLint border, TexFormat format,
|
||||
TexType type, const GLvoid* data);
|
||||
|
||||
void ForceLoseContext(bool simulateLoss = false);
|
||||
void ForceRestoreContext();
|
||||
|
||||
|
@ -1691,6 +1612,17 @@ private:
|
|||
|
||||
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
|
||||
|
||||
bool
|
||||
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
|
||||
TexTarget* const out_texTarget, WebGLTexture** const out_tex);
|
||||
bool
|
||||
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
|
||||
const char* funcName, TexImageTarget* const out_texImageTarget,
|
||||
WebGLTexture** const out_tex);
|
||||
|
||||
// Returns x rounded to the next highest multiple of y.
|
||||
CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,469 @@
|
|||
/* -*- 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/Endian.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static bool
|
||||
IsValidTexTarget(WebGLContext* webgl, GLenum rawTexTarget, TexTarget* const out)
|
||||
{
|
||||
switch (rawTexTarget) {
|
||||
case LOCAL_GL_TEXTURE_2D:
|
||||
case LOCAL_GL_TEXTURE_CUBE_MAP:
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (!webgl->IsWebGL2())
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = rawTexTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsValidTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
|
||||
TexImageTarget* const out)
|
||||
{
|
||||
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:
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_3D:
|
||||
if (!webgl->IsWebGL2())
|
||||
return false;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = rawTexImageTarget;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
|
||||
TexTarget* const out_texTarget, WebGLTexture** const out_tex)
|
||||
{
|
||||
if (webgl->IsContextLost())
|
||||
return false;
|
||||
|
||||
TexTarget texTarget;
|
||||
if (!IsValidTexTarget(webgl, 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, GLenum rawTexImageTarget,
|
||||
const char* funcName, TexImageTarget* const out_texImageTarget,
|
||||
WebGLTexture** const out_tex)
|
||||
{
|
||||
if (webgl->IsContextLost())
|
||||
return false;
|
||||
|
||||
TexImageTarget texImageTarget;
|
||||
if (!IsValidTexImageTarget(webgl, 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GL calls
|
||||
|
||||
void
|
||||
WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("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())
|
||||
return ErrorInvalidEnum("bindTexture: target TEXTURE_3D is only available in WebGL version 2.0 or newer");
|
||||
|
||||
currentTexPtr = &mBound3DTextures[mActiveTexture];
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
|
||||
}
|
||||
const TexTarget texTarget(rawTarget);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (newTex && !newTex->BindTexture(texTarget))
|
||||
return;
|
||||
|
||||
if (!newTex) {
|
||||
gl->fBindTexture(texTarget.get(), 0);
|
||||
}
|
||||
|
||||
*currentTexPtr = newTex;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::GenerateMipmap(GLenum rawTexTarget)
|
||||
{
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
|
||||
return;
|
||||
|
||||
tex->GenerateMipmap(texTarget);
|
||||
}
|
||||
|
||||
JS::Value
|
||||
WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
|
||||
{
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &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 (IsContextLost())
|
||||
return false;
|
||||
|
||||
if (!ValidateObjectAllowDeleted("isTexture", tex))
|
||||
return false;
|
||||
|
||||
return tex->IsTexture();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeIntParam,
|
||||
GLfloat* maybeFloatParam)
|
||||
{
|
||||
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
|
||||
|
||||
TexTarget texTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
|
||||
return;
|
||||
|
||||
tex->TexParameter(texTarget, pname, maybeIntParam, maybeFloatParam);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Uploads
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexImage
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType, elem,
|
||||
out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, width, height, border,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData, ErrorResult& out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
|
||||
imageData, &out_rv);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TexSubImage
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
elem, out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
|
||||
unpackFormat, unpackType, maybeView, &out_rv);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult& out_rv)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
|
||||
&tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
|
||||
imageData, &out_rv);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CopyTex(Sub)Image
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint border)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CopyTexImage2D(texImageTarget, level, internalFormat, x, y, width, height,
|
||||
border);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexSubImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CopyTexSubImage2D(texImageTarget, level, xOffset, yOffset, x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CompressedTex(Sub)Image
|
||||
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLint border, const dom::ArrayBufferView& view)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexImage2D(texImageTarget, level, internalFormat, width, height,
|
||||
border, view);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLsizei width,
|
||||
GLsizei height, GLenum unpackFormat,
|
||||
const dom::ArrayBufferView& view)
|
||||
{
|
||||
TexImageTarget texImageTarget;
|
||||
WebGLTexture* tex;
|
||||
if (!ValidateTexImageTarget(this, rawTexImageTarget, "compressedTexSubImage2D",
|
||||
&texImageTarget, &tex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tex->CompressedTexSubImage2D(texImageTarget, level, xOffset, yOffset, width, height,
|
||||
unpackFormat, view);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -1001,7 +1001,7 @@ WebGLContext::EnumName(GLenum glenum, nsACString* out_name)
|
|||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsCompressedTextureFormat(GLenum format)
|
||||
IsCompressedTextureFormat(GLenum format)
|
||||
{
|
||||
switch (format) {
|
||||
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
|
@ -1034,7 +1034,7 @@ WebGLContext::IsCompressedTextureFormat(GLenum format)
|
|||
|
||||
|
||||
bool
|
||||
WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
|
||||
IsTextureFormatCompressed(TexInternalFormat format)
|
||||
{
|
||||
return IsCompressedTextureFormat(format.get());
|
||||
}
|
||||
|
|
|
@ -61,6 +61,9 @@ TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
|
|||
// Helper function to create a JS::Value from a C string
|
||||
JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv);
|
||||
|
||||
bool IsCompressedTextureFormat(GLenum format);
|
||||
bool IsTextureFormatCompressed(TexInternalFormat format);
|
||||
|
||||
struct GLComponents
|
||||
{
|
||||
unsigned char mComponents;
|
||||
|
|
|
@ -607,40 +607,6 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func,
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given texture target is valid for TexImage.
|
||||
*/
|
||||
bool
|
||||
WebGLContext::ValidateTexImageTarget(GLenum target, WebGLTexImageFunc func,
|
||||
WebGLTexDimensions dims)
|
||||
{
|
||||
switch (dims) {
|
||||
case WebGLTexDimensions::Tex2D:
|
||||
if (target == LOCAL_GL_TEXTURE_2D ||
|
||||
IsTexImageCubemapTarget(target))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
|
||||
return false;
|
||||
|
||||
case WebGLTexDimensions::Tex3D:
|
||||
if (target == LOCAL_GL_TEXTURE_3D)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
|
||||
return false;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "ValidateTexImageTarget: Invalid dims");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if type is a valid texture image type for source,
|
||||
* taking into account enabled WebGL extensions.
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
#include <algorithm>
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLTexelConversions.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -730,6 +730,289 @@ WebGLTexture::SetFakeBlackStatus(WebGLTextureFakeBlackStatus x)
|
|||
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GL calls
|
||||
|
||||
bool
|
||||
WebGLTexture::BindTexture(TexTarget texTarget)
|
||||
{
|
||||
// silently ignore a deleted texture
|
||||
if (IsDeleted())
|
||||
return false;
|
||||
|
||||
if (HasEverBeenBound() && mTarget != texTarget) {
|
||||
mContext->ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target");
|
||||
return false;
|
||||
}
|
||||
|
||||
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
|
||||
Bind(texTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::GenerateMipmap(TexTarget texTarget)
|
||||
{
|
||||
const TexImageTarget imageTarget = (texTarget == LOCAL_GL_TEXTURE_2D)
|
||||
? LOCAL_GL_TEXTURE_2D
|
||||
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
if (!IsMipmapRangeValid())
|
||||
{
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: Texture does not have a valid mipmap range.");
|
||||
}
|
||||
if (!HasImageInfoAt(imageTarget, EffectiveBaseMipmapLevel()))
|
||||
{
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
|
||||
}
|
||||
|
||||
if (!mContext->IsWebGL2() && !IsFirstImagePowerOfTwo())
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
|
||||
|
||||
TexInternalFormat internalformat = ImageInfoAt(imageTarget, 0).EffectiveInternalFormat();
|
||||
if (IsTextureFormatCompressed(internalformat))
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
|
||||
|
||||
if (mContext->IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
|
||||
(IsGLDepthFormat(internalformat) || IsGLDepthStencilFormat(internalformat)))
|
||||
{
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: "
|
||||
"A texture that has a base internal format of "
|
||||
"DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
|
||||
}
|
||||
|
||||
if (!AreAllLevel0ImageInfosEqual())
|
||||
return mContext->ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type.");
|
||||
|
||||
SetGeneratedMipmap();
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
|
||||
if (gl->WorkAroundDriverBugs()) {
|
||||
// bug 696495 - to work around failures in the texture-mips.html test on various drivers, we
|
||||
// set the minification filter before calling glGenerateMipmap. This should not carry a significant performance
|
||||
// overhead so we do it unconditionally.
|
||||
//
|
||||
// note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See Chromium bug 101105.
|
||||
gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST_MIPMAP_NEAREST);
|
||||
gl->fGenerateMipmap(texTarget.get());
|
||||
gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER, MinFilter().get());
|
||||
} else {
|
||||
gl->fGenerateMipmap(texTarget.get());
|
||||
}
|
||||
}
|
||||
|
||||
JS::Value
|
||||
WebGLTexture::GetTexParameter(TexTarget texTarget, GLenum pname)
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
GLint i = 0;
|
||||
GLfloat f = 0.0f;
|
||||
|
||||
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:
|
||||
case LOCAL_GL_TEXTURE_BASE_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
|
||||
case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
|
||||
case LOCAL_GL_TEXTURE_MAX_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_A:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_B:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_G:
|
||||
case LOCAL_GL_TEXTURE_SWIZZLE_R:
|
||||
case LOCAL_GL_TEXTURE_WRAP_R:
|
||||
mContext->gl->fGetTexParameteriv(texTarget.get(), pname, &i);
|
||||
return JS::NumberValue(uint32_t(i));
|
||||
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
case LOCAL_GL_TEXTURE_MAX_LOD:
|
||||
case LOCAL_GL_TEXTURE_MIN_LOD:
|
||||
mContext->gl->fGetTexParameterfv(texTarget.get(), pname, &f);
|
||||
return JS::NumberValue(float(f));
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unhandled pname.");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLTexture::IsTexture() const
|
||||
{
|
||||
return HasEverBeenBound() && !IsDeleted();
|
||||
}
|
||||
|
||||
// Here we have to support all pnames with both int and float params.
|
||||
// See this discussion:
|
||||
// https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
|
||||
void
|
||||
WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam,
|
||||
GLfloat* maybeFloatParam)
|
||||
{
|
||||
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
|
||||
|
||||
GLint intParam = maybeIntParam ? *maybeIntParam : GLint(*maybeFloatParam);
|
||||
GLfloat floatParam = maybeFloatParam ? *maybeFloatParam : GLfloat(*maybeIntParam);
|
||||
|
||||
bool paramBadEnum = false;
|
||||
bool paramBadValue = false;
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_TEXTURE_BASE_LEVEL:
|
||||
case LOCAL_GL_TEXTURE_MAX_LEVEL:
|
||||
if (!mContext->IsWebGL2())
|
||||
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
|
||||
if (intParam < 0) {
|
||||
paramBadValue = true;
|
||||
break;
|
||||
}
|
||||
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
if (pname == LOCAL_GL_TEXTURE_BASE_LEVEL)
|
||||
mBaseMipmapLevel = intParam;
|
||||
else
|
||||
mMaxMipmapLevel = intParam;
|
||||
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||
if (!mContext->IsWebGL2())
|
||||
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
|
||||
paramBadValue = (intParam != LOCAL_GL_NONE &&
|
||||
intParam != LOCAL_GL_COMPARE_REF_TO_TEXTURE);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
|
||||
if (!mContext->IsWebGL2())
|
||||
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
|
||||
switch (intParam) {
|
||||
case LOCAL_GL_LEQUAL:
|
||||
case LOCAL_GL_GEQUAL:
|
||||
case LOCAL_GL_LESS:
|
||||
case LOCAL_GL_GREATER:
|
||||
case LOCAL_GL_EQUAL:
|
||||
case LOCAL_GL_NOTEQUAL:
|
||||
case LOCAL_GL_ALWAYS:
|
||||
case LOCAL_GL_NEVER:
|
||||
break;
|
||||
|
||||
default:
|
||||
paramBadValue = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_MIN_FILTER:
|
||||
switch (intParam) {
|
||||
case LOCAL_GL_NEAREST:
|
||||
case LOCAL_GL_LINEAR:
|
||||
case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
|
||||
case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
|
||||
case LOCAL_GL_NEAREST_MIPMAP_LINEAR:
|
||||
case LOCAL_GL_LINEAR_MIPMAP_LINEAR:
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
mMinFilter = intParam;
|
||||
break;
|
||||
|
||||
default:
|
||||
paramBadEnum = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_MAG_FILTER:
|
||||
switch (intParam) {
|
||||
case LOCAL_GL_NEAREST:
|
||||
case LOCAL_GL_LINEAR:
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
mMagFilter = intParam;
|
||||
break;
|
||||
|
||||
default:
|
||||
paramBadEnum = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_WRAP_S:
|
||||
switch (intParam) {
|
||||
case LOCAL_GL_CLAMP_TO_EDGE:
|
||||
case LOCAL_GL_MIRRORED_REPEAT:
|
||||
case LOCAL_GL_REPEAT:
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
mWrapS = intParam;
|
||||
break;
|
||||
|
||||
default:
|
||||
paramBadEnum = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_WRAP_T:
|
||||
switch (intParam) {
|
||||
case LOCAL_GL_CLAMP_TO_EDGE:
|
||||
case LOCAL_GL_MIRRORED_REPEAT:
|
||||
case LOCAL_GL_REPEAT:
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
mWrapT = intParam;
|
||||
break;
|
||||
|
||||
default:
|
||||
paramBadEnum = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
if (!mContext->IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic))
|
||||
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
|
||||
if (maybeFloatParam && floatParam < 1.0f)
|
||||
paramBadValue = true;
|
||||
else if (maybeIntParam && intParam < 1)
|
||||
paramBadValue = true;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return mContext->ErrorInvalidEnumInfo("texParameter: pname", pname);
|
||||
}
|
||||
|
||||
if (paramBadEnum) {
|
||||
if (maybeIntParam) {
|
||||
mContext->ErrorInvalidEnum("texParameteri: pname 0x%04x: Invalid param"
|
||||
" 0x%04x.",
|
||||
pname, intParam);
|
||||
} else {
|
||||
mContext->ErrorInvalidEnum("texParameterf: pname 0x%04x: Invalid param %g.",
|
||||
pname, floatParam);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (paramBadValue) {
|
||||
if (maybeIntParam) {
|
||||
mContext->ErrorInvalidValue("texParameteri: pname 0x%04x: Invalid param %i"
|
||||
" (0x%x).",
|
||||
pname, intParam, intParam);
|
||||
} else {
|
||||
mContext->ErrorInvalidValue("texParameterf: pname 0x%04x: Invalid param %g.",
|
||||
pname, floatParam);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
if (maybeIntParam)
|
||||
mContext->gl->fTexParameteri(texTarget.get(), pname, intParam);
|
||||
else
|
||||
mContext->gl->fTexParameterf(texTarget.get(), pname, floatParam);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTexture, AddRef)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
|
@ -18,6 +19,12 @@
|
|||
#include "WebGLStrongTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
class Element;
|
||||
class ImageData;
|
||||
} // namespace dom
|
||||
|
||||
// Zero is not an integer power of two.
|
||||
inline bool
|
||||
|
@ -27,6 +34,10 @@ IsPOTAssumingNonnegative(GLsizei x)
|
|||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesTargetMatchDimensions(WebGLContext* webgl, TexImageTarget target, uint8_t dims,
|
||||
const char* funcName);
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
class WebGLTexture final
|
||||
|
@ -36,7 +47,35 @@ class WebGLTexture final
|
|||
, public WebGLContextBoundObject
|
||||
, public WebGLFramebufferAttachable
|
||||
{
|
||||
friend class WebGLContext;
|
||||
friend class WebGLFramebuffer;
|
||||
|
||||
public:
|
||||
class ImageInfo;
|
||||
|
||||
const GLuint mGLName;
|
||||
|
||||
protected:
|
||||
GLenum mTarget;
|
||||
TexMinFilter mMinFilter;
|
||||
TexMagFilter mMagFilter;
|
||||
TexWrap mWrapS, mWrapT;
|
||||
|
||||
size_t mFacesCount, mMaxLevelWithCustomImages;
|
||||
nsTArray<ImageInfo> mImageInfos;
|
||||
|
||||
bool mHaveGeneratedMipmap; // Set by generateMipmap
|
||||
bool mImmutable; // Set by texStorage*
|
||||
|
||||
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
|
||||
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
|
||||
|
||||
WebGLTextureFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
|
||||
|
||||
explicit WebGLTexture(WebGLContext* webgl, GLuint tex);
|
||||
|
||||
void Delete();
|
||||
|
@ -50,27 +89,156 @@ public:
|
|||
|
||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
|
||||
|
||||
protected:
|
||||
~WebGLTexture() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
friend class WebGLContext;
|
||||
friend class WebGLFramebuffer;
|
||||
|
||||
// We store information about the various images that are part of this
|
||||
// texture. (cubemap faces, mipmap levels)
|
||||
|
||||
public:
|
||||
const GLuint mGLName;
|
||||
////////////////////////////////////
|
||||
// GL calls
|
||||
bool BindTexture(TexTarget texTarget);
|
||||
void GenerateMipmap(TexTarget texTarget);
|
||||
JS::Value GetTexParameter(TexTarget texTarget, GLenum pname);
|
||||
bool IsTexture() const;
|
||||
void TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam,
|
||||
GLfloat* maybeFloatParam);
|
||||
|
||||
////////////////////////////////////
|
||||
// WebGLTextureUpload.cpp
|
||||
|
||||
void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLint border, const dom::ArrayBufferView& view);
|
||||
|
||||
void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border, GLsizei imageSize,
|
||||
const dom::ArrayBufferView& view);
|
||||
|
||||
|
||||
void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLsizei width,
|
||||
GLsizei height, GLenum unpackFormat,
|
||||
const dom::ArrayBufferView& view);
|
||||
|
||||
void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum unpackFormat, GLsizei imageSize,
|
||||
const dom::ArrayBufferView& view);
|
||||
|
||||
|
||||
void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
|
||||
|
||||
void CopyTexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
void CopyTexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult* const out_rv);
|
||||
void TexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
|
||||
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
void TexImage3D(TexImageTarget target, GLint level, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLint border,
|
||||
GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
|
||||
|
||||
void TexStorage2D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height);
|
||||
void TexStorage3D(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth);
|
||||
|
||||
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height, GLenum unpackFormat,
|
||||
GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::ImageData* imageData, ErrorResult* const out_rv);
|
||||
void TexSubImage2D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
|
||||
dom::Element* elem, ErrorResult* const out_rv);
|
||||
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
|
||||
const dom::Nullable<dom::ArrayBufferView>& maybeView,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::ImageData* imageData,
|
||||
ErrorResult* const out_rv);
|
||||
void TexSubImage3D(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLint zOffset, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::Element* elem, ErrorResult* const out_rv);
|
||||
|
||||
protected:
|
||||
GLenum mTarget;
|
||||
|
||||
/** Like glTexImage2D, but if the call may change the texture size, checks
|
||||
* any GL error generated by this glTexImage2D call and returns it.
|
||||
*/
|
||||
GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
|
||||
TexInternalFormat internalFormat, GLsizei width,
|
||||
GLsizei height, GLint border, TexFormat format,
|
||||
TexType type, const GLvoid* data);
|
||||
|
||||
bool ValidateTexStorage(TexImageTarget texImageTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* funcName);
|
||||
void SpecifyTexStorage(GLsizei levels, TexInternalFormat internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth);
|
||||
|
||||
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
GLint level, TexInternalFormat internalFormat,
|
||||
GLint xoffset, GLint yoffset, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height, bool isSub);
|
||||
|
||||
bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLenum unpackFormat,
|
||||
GLenum unpackType, dom::Element* elem);
|
||||
|
||||
// If jsArrayType is MaxTypedArrayViewType, it means no array.
|
||||
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width, GLsizei height,
|
||||
GLsizei srcStrideOrZero, GLint border, GLenum unpackFormat,
|
||||
GLenum unpackType, void* data, uint32_t byteLength,
|
||||
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
|
||||
bool srcPremultiplied);
|
||||
void TexSubImage2D_base(TexImageTarget texImageTarget, GLint level, GLint xOffset,
|
||||
GLint yOffset, GLsizei width, GLsizei height,
|
||||
GLsizei srcStrideOrZero, GLenum unpackFormat,
|
||||
GLenum unpackType, void* pixels, uint32_t byteLength,
|
||||
js::Scalar::Type jsArrayType, WebGLTexelFormat srcFormat,
|
||||
bool srcPremultiplied);
|
||||
|
||||
bool ValidateTexStorage(TexTarget texTarget, GLsizei levels, GLenum internalFormat,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
const char* info);
|
||||
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
|
||||
|
||||
|
||||
public:
|
||||
// We store information about the various images that are part of this
|
||||
// texture. (cubemap faces, mipmap levels)
|
||||
class ImageInfo
|
||||
: public WebGLRectangleObject
|
||||
{
|
||||
|
@ -216,20 +384,6 @@ public:
|
|||
bool EnsureInitializedImageData(TexImageTarget imageTarget, GLint level);
|
||||
|
||||
protected:
|
||||
TexMinFilter mMinFilter;
|
||||
TexMagFilter mMagFilter;
|
||||
TexWrap mWrapS, mWrapT;
|
||||
|
||||
size_t mFacesCount, mMaxLevelWithCustomImages;
|
||||
nsTArray<ImageInfo> mImageInfos;
|
||||
|
||||
bool mHaveGeneratedMipmap; // Set by generateMipmap
|
||||
bool mImmutable; // Set by texStorage*
|
||||
|
||||
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
|
||||
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
|
||||
|
||||
WebGLTextureFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) {
|
||||
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -78,6 +78,7 @@ UNIFIED_SOURCES += [
|
|||
'WebGLContextGL.cpp',
|
||||
'WebGLContextLossHandler.cpp',
|
||||
'WebGLContextState.cpp',
|
||||
'WebGLContextTextures.cpp',
|
||||
'WebGLContextUnchecked.cpp',
|
||||
'WebGLContextUtils.cpp',
|
||||
'WebGLContextValidate.cpp',
|
||||
|
@ -125,6 +126,7 @@ UNIFIED_SOURCES += [
|
|||
'WebGLSync.cpp',
|
||||
'WebGLTexelConversions.cpp',
|
||||
'WebGLTexture.cpp',
|
||||
'WebGLTextureUpload.cpp',
|
||||
'WebGLTimerQuery.cpp',
|
||||
'WebGLTransformFeedback.cpp',
|
||||
'WebGLUniformLocation.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче