Bug 1188540 - Forward texture-related functions to WebGLTexture. - r=kamidphish

This commit is contained in:
Jeff Gilbert 2015-08-03 14:34:46 -07:00
Родитель 0f1cdda9e1
Коммит f0e28e9429
13 изменённых файлов: 2529 добавлений и 1980 удалений

Просмотреть файл

@ -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, &param);
}
void TexParameteri(GLenum target, GLenum pname, GLint param) {
TexParameter_base(target, pname, &param, 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, &param);
}
void TexParameteri(GLenum texTarget, GLenum pname, GLint param) {
TexParameter_base(texTarget, pname, &param, 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',