Back out changeset 2f614bcd9405 (bug 1221822) for test_conformance__extensions__ext-sRGB.html and test_webgl2_alpha_luminance.html failures

This commit is contained in:
Phil Ringnalda 2015-11-23 21:55:59 -08:00
parent a4e1fa37a6
commit 71a6f5da62
101 changed files with 7655 additions and 8213 deletions

View File

@ -983,7 +983,7 @@ nsDOMWindowUtils::SendKeyEvent(const nsAString& aType,
{
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
return nsContentUtils::SendKeyEvent(widget, aType, aKeyCode, aCharCode,
aModifiers, aAdditionalFlags,
aDefaultActionTaken);
@ -1312,7 +1312,7 @@ nsDOMWindowUtils::NodesFromRect(float aX, float aY,
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_STATE(doc);
return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
aIgnoreRootScrollFrame, aFlushLayout, aReturn);
}
@ -1408,9 +1408,7 @@ CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
"be an element.");
nsLayoutUtils::SurfaceFromElementResult result =
nsLayoutUtils::SurfaceFromElement(node->AsElement());
MOZ_ASSERT(result.GetSourceSurface());
return result.GetSourceSurface()->GetDataSurface();
return result.mSourceSurface->GetDataSurface();
}
NS_IMETHODIMP
@ -1751,7 +1749,7 @@ nsDOMWindowUtils::GetFullZoom(float* aFullZoom)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::DispatchDOMEventViaPresShell(nsIDOMNode* aTarget,
nsIDOMEvent* aEvent,
@ -2454,7 +2452,7 @@ nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
return presShell->RenderDocument(aRect, aFlags, aBackgroundColor, aThebesContext);
}
NS_IMETHODIMP
NS_IMETHODIMP
nsDOMWindowUtils::GetCursorType(int16_t *aCursor)
{
NS_ENSURE_ARG_POINTER(aCursor);

View File

@ -1209,8 +1209,8 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->MakeCurrent();
gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext()->fDeleteTextures(1, &mVideoTexture);
}
mCurrentVideoSize.width = 0;
mCurrentVideoSize.height = 0;
mCurrentVideoSize.width = 0;
mCurrentVideoSize.height = 0;
}
#endif
@ -2113,14 +2113,15 @@ CanvasRenderingContext2D::CreatePattern(const CanvasImageSource& source,
nsLayoutUtils::SurfaceFromElement(htmlElement,
nsLayoutUtils::SFE_WANT_FIRST_FRAME, mTarget);
if (!res.GetSourceSurface()) {
if (!res.mSourceSurface) {
error.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
RefPtr<CanvasPattern> pat = new CanvasPattern(this, res.GetSourceSurface(), repeatMode,
res.mPrincipal, res.mIsWriteOnly,
res.mCORSUsed);
RefPtr<CanvasPattern> pat =
new CanvasPattern(this, res.mSourceSurface, repeatMode, res.mPrincipal,
res.mIsWriteOnly, res.mCORSUsed);
return pat.forget();
}
@ -5406,9 +5407,9 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w
uint8_t* srcLine = aArray->Data() + copyY * (w * 4) + copyX * 4;
#if 0
printf("PutImageData_explicit: dirty x=%d y=%d w=%d h=%d copy x=%d y=%d w=%d h=%d ext x=%d y=%d w=%d h=%d\n",
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
copyX, copyY, copyWidth, copyHeight,
x, y, w, h);
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
copyX, copyY, copyWidth, copyHeight,
x, y, w, h);
#endif
for (uint32_t j = 0; j < copyHeight; j++) {
uint8_t *src = srcLine;

View File

@ -355,13 +355,12 @@ GetSurfaceFromElement(nsIGlobalObject* aGlobal, HTMLElementType& aElement, Error
return nullptr;
}
RefPtr<SourceSurface> surface = res.GetSourceSurface();
if (NS_WARN_IF(!surface)) {
if (NS_WARN_IF(!res.mSourceSurface)) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
RefPtr<SourceSurface> surface(res.mSourceSurface);
return surface.forget();
}

View File

@ -1,773 +0,0 @@
/* -*- Mode: C++; tab-width: 20; 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 "TexUnpackBlob.h"
#include "GLBlitHelper.h"
#include "GLContext.h"
#include "GLDefs.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/RefPtr.h"
#include "nsLayoutUtils.h"
#include "WebGLContext.h"
#include "WebGLTexelConversions.h"
#include "WebGLTexture.h"
namespace mozilla {
namespace webgl {
static GLenum
DoTexOrSubImage(bool isSubImage, gl::GLContext* gl, TexImageTarget target, GLint level,
const DriverUnpackInfo* dui, GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth, const void* data)
{
if (isSubImage) {
return DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
depth, dui->ToPacking(), data);
} else {
return DoTexImage(gl, target, level, dui, width, height, depth, data);
}
}
/*static*/ void
TexUnpackBlob::OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
gl::OriginPos* const out_dst)
{
// Our surfaces are TopLeft.
*out_src = gl::OriginPos::TopLeft;
// WebGL specs the default as passing DOM elements top-left first.
// Thus y-flip would give us bottom-left.
*out_dst = webgl->mPixelStore_FlipY ? gl::OriginPos::BottomLeft
: gl::OriginPos::TopLeft;
}
//////////////////////////////////////////////////////////////////////////////////////////
// TexUnpackBytes
bool
TexUnpackBytes::ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
const webgl::PackingInfo& pi)
{
if (!mBytes)
return true;
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const auto bytesNeeded = webgl->GetUnpackSize(isFunc3D, mWidth, mHeight, mDepth,
bytesPerPixel);
if (!bytesNeeded.isValid()) {
webgl->ErrorInvalidOperation("%s: Overflow while computing the needed buffer"
" size.",
funcName);
return false;
}
if (mByteCount < bytesNeeded.value()) {
webgl->ErrorInvalidOperation("%s: Provided buffer is too small. (needs %u, has"
" %u)",
funcName, bytesNeeded.value(), mByteCount);
return false;
}
return true;
}
static bool
UnpackFormatHasAlpha(GLenum unpackFormat)
{
switch (unpackFormat) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_RGBA:
return true;
default:
return false;
}
}
static WebGLTexelFormat
FormatFromPacking(const webgl::PackingInfo& pi)
{
switch (pi.type) {
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
return WebGLTexelFormat::RGB565;
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
return WebGLTexelFormat::RGBA5551;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
return WebGLTexelFormat::RGBA4444;
case LOCAL_GL_UNSIGNED_BYTE:
switch (pi.format) {
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R8;
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A8;
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA8;
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB8;
case LOCAL_GL_SRGB: return WebGLTexelFormat::RGB8;
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA8;
case LOCAL_GL_SRGB_ALPHA: return WebGLTexelFormat::RGBA8;
}
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
switch (pi.format) {
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R16F;
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A16F;
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA16F;
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB16F;
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA16F;
}
case LOCAL_GL_FLOAT:
switch (pi.format) {
case LOCAL_GL_LUMINANCE: return WebGLTexelFormat::R32F;
case LOCAL_GL_ALPHA: return WebGLTexelFormat::A32F;
case LOCAL_GL_LUMINANCE_ALPHA: return WebGLTexelFormat::RA32F;
case LOCAL_GL_RGB: return WebGLTexelFormat::RGB32F;
case LOCAL_GL_RGBA: return WebGLTexelFormat::RGBA32F;
}
}
return WebGLTexelFormat::FormatNotSupportingAnyConversion;
}
void
TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum* const out_glError)
{
WebGLContext* webgl = tex->mContext;
gl::GLContext* gl = webgl->gl;
const void* uploadBytes = mBytes;
UniqueBuffer tempBuffer;
do {
if (!webgl->mPixelStore_FlipY && !webgl->mPixelStore_PremultiplyAlpha)
break;
if (!mBytes || !mWidth || !mHeight || !mDepth)
break;
if (webgl->IsWebGL2())
break;
MOZ_ASSERT(mDepth == 1);
// This is literally the worst.
webgl->GenerateWarning("%s: Uploading ArrayBuffers with FLIP_Y or"
" PREMULTIPLY_ALPHA is slow.",
funcName);
tempBuffer = malloc(mByteCount);
if (!tempBuffer) {
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
const webgl::PackingInfo pi = { dui->unpackFormat, dui->unpackType };
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const auto rowByteAlignment = webgl->mPixelStore_UnpackAlignment;
const size_t bytesPerRow = bytesPerPixel * mWidth;
const size_t rowStride = RoundUpToMultipleOf(bytesPerRow, rowByteAlignment);
const bool needsYFlip = webgl->mPixelStore_FlipY;
bool needsAlphaPremult = webgl->mPixelStore_PremultiplyAlpha;
if (!UnpackFormatHasAlpha(pi.format))
needsAlphaPremult = false;
if (!needsAlphaPremult) {
if (!webgl->mPixelStore_FlipY)
break;
const uint8_t* src = (const uint8_t*)mBytes;
const uint8_t* const srcEnd = src + rowStride * mHeight;
uint8_t* dst = (uint8_t*)tempBuffer.get() + rowStride * (mHeight - 1);
while (src != srcEnd) {
memcpy(dst, src, bytesPerRow);
src += rowStride;
dst -= rowStride;
}
uploadBytes = tempBuffer.get();
break;
}
const auto texelFormat = FormatFromPacking(pi);
if (texelFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
MOZ_ASSERT(false, "Bad texelFormat from pi.");
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
const auto srcOrigin = gl::OriginPos::BottomLeft;
const auto dstOrigin = (needsYFlip ? gl::OriginPos::TopLeft
: gl::OriginPos::BottomLeft);
const bool srcPremultiplied = false;
const bool dstPremultiplied = needsAlphaPremult; // Always true here.
// And go!:
if (!ConvertImage(mWidth, mHeight,
mBytes, rowStride, srcOrigin, texelFormat, srcPremultiplied,
tempBuffer.get(), rowStride, dstOrigin, texelFormat,
dstPremultiplied))
{
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
uploadBytes = tempBuffer.get();
} while (false);
GLenum error = DoTexOrSubImage(isSubImage, gl, target, level, dui, xOffset, yOffset,
zOffset, mWidth, mHeight, mDepth, uploadBytes);
*out_glError = error;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackImage
TexUnpackImage::TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult)
: TexUnpackBlob(image->GetSize().width, image->GetSize().height, 1, true)
, mImage(image)
, mIsAlphaPremult(isAlphaPremult)
{ }
TexUnpackImage::~TexUnpackImage()
{ }
void
TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum* const out_glError)
{
MOZ_ASSERT_IF(needsRespec, !isSubImage);
*out_glError = 0;
WebGLContext* webgl = tex->mContext;
gl::GLContext* gl = webgl->GL();
gl->MakeCurrent();
if (needsRespec) {
GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, dui, xOffset,
yOffset, zOffset, mWidth, mHeight, mDepth,
nullptr);
if (error) {
MOZ_ASSERT(!error);
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
}
do {
if (dui->unpackFormat != LOCAL_GL_RGB && dui->unpackFormat != LOCAL_GL_RGBA)
break;
if (dui->unpackType != LOCAL_GL_UNSIGNED_BYTE)
break;
gl::ScopedFramebuffer scopedFB(gl);
gl::ScopedBindFramebuffer bindFB(gl, scopedFB.FB());
{
gl::GLContext::LocalErrorScope errorScope(*gl);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
target.get(), tex->mGLName, level);
if (errorScope.GetError())
break;
}
const GLenum status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
break;
gl::OriginPos srcOrigin, dstOrigin;
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
const gfx::IntSize destSize(mWidth, mHeight);
if (!gl->BlitHelper()->BlitImageToFramebuffer(mImage, destSize, scopedFB.FB(),
dstOrigin))
{
break;
}
return; // Blitting was successful, so we're done!
} while (false);
TexUnpackSurface surfBlob(mImage->GetAsSourceSurface(), mIsAlphaPremult);
surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level, dui,
xOffset, yOffset, zOffset, out_glError);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TexUnpackSurface
static bool
GuessAlignment(const void* data, size_t bytesPerRow, size_t stride, size_t maxAlignment,
size_t* const out_alignment)
{
size_t alignmentGuess = maxAlignment;
while (alignmentGuess) {
size_t guessStride = RoundUpToMultipleOf(bytesPerRow, alignmentGuess);
if (guessStride == stride &&
uintptr_t(data) % alignmentGuess == 0)
{
*out_alignment = alignmentGuess;
return true;
}
alignmentGuess /= 2;
}
return false;
}
static bool
SupportsBGRA(gl::GLContext* gl)
{
if (gl->IsANGLE())
return true;
return false;
}
/*static*/ bool
TexUnpackSurface::UploadDataSurface(bool isSubImage, WebGLContext* webgl,
TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, gfx::DataSourceSurface* surf,
bool isSurfAlphaPremult, GLenum* const out_glError)
{
gl::GLContext* gl = webgl->GL();
MOZ_ASSERT(gl->IsCurrent());
*out_glError = 0;
if (isSurfAlphaPremult != webgl->mPixelStore_PremultiplyAlpha)
return false;
gl::OriginPos srcOrigin, dstOrigin;
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
if (srcOrigin != dstOrigin)
return false;
// This differs from the raw-data upload in that we choose how we do the unpack.
// (alignment, etc.)
// Uploading RGBX as RGBA and blitting to RGB is faster than repacking RGBX into
// RGB on the CPU. However, this is optimization is out-of-scope for now.
static const webgl::DriverUnpackInfo kInfoBGRA = {
LOCAL_GL_BGRA,
LOCAL_GL_BGRA,
LOCAL_GL_UNSIGNED_BYTE,
};
const webgl::DriverUnpackInfo* chosenDUI = nullptr;
switch (surf->GetFormat()) {
case gfx::SurfaceFormat::B8G8R8A8:
if (SupportsBGRA(gl) &&
dui->internalFormat == LOCAL_GL_RGBA &&
dui->unpackFormat == LOCAL_GL_RGBA &&
dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
{
chosenDUI = &kInfoBGRA;
}
break;
case gfx::SurfaceFormat::R8G8B8A8:
if (dui->unpackFormat == LOCAL_GL_RGBA &&
dui->unpackType == LOCAL_GL_UNSIGNED_BYTE)
{
chosenDUI = dui;
}
break;
case gfx::SurfaceFormat::R5G6B5_UINT16:
if (dui->unpackFormat == LOCAL_GL_RGB &&
dui->unpackType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
{
chosenDUI = dui;
}
break;
default:
break;
}
if (!chosenDUI)
return false;
gfx::DataSourceSurface::ScopedMap map(surf, gfx::DataSourceSurface::MapType::READ);
if (!map.IsMapped())
return false;
const webgl::PackingInfo pi = {chosenDUI->unpackFormat, chosenDUI->unpackType};
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const size_t bytesPerRow = width * bytesPerPixel;
const GLint kMaxUnpackAlignment = 8;
size_t unpackAlignment;
if (!GuessAlignment(map.GetData(), bytesPerRow, map.GetStride(), kMaxUnpackAlignment,
&unpackAlignment))
{
return false;
// TODO: Consider using UNPACK_ settings to set the stride based on the too-large
// alignment used for some SourceSurfaces. (D2D allegedy likes alignment=16)
}
MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, unpackAlignment);
const GLsizei depth = 1;
GLenum error = DoTexOrSubImage(isSubImage, gl, target.get(), level, chosenDUI,
xOffset, yOffset, zOffset, width, height, depth,
map.GetData());
if (error) {
*out_glError = error;
return false;
}
return true;
}
////////////////////
static bool
GetFormatForSurf(gfx::SourceSurface* surf, WebGLTexelFormat* const out_texelFormat)
{
gfx::SurfaceFormat surfFormat = surf->GetFormat();
switch (surfFormat) {
case gfx::SurfaceFormat::B8G8R8A8:
*out_texelFormat = WebGLTexelFormat::BGRA8;
return true;
case gfx::SurfaceFormat::B8G8R8X8:
*out_texelFormat = WebGLTexelFormat::BGRX8;
return true;
case gfx::SurfaceFormat::R8G8B8A8:
*out_texelFormat = WebGLTexelFormat::RGBA8;
return true;
case gfx::SurfaceFormat::R8G8B8X8:
*out_texelFormat = WebGLTexelFormat::RGBX8;
return true;
case gfx::SurfaceFormat::R5G6B5_UINT16:
*out_texelFormat = WebGLTexelFormat::RGB565;
return true;
case gfx::SurfaceFormat::A8:
*out_texelFormat = WebGLTexelFormat::A8;
return true;
case gfx::SurfaceFormat::YUV:
// Ugh...
NS_ERROR("We don't handle uploads from YUV sources yet.");
// When we want to, check out gfx/ycbcr/YCbCrUtils.h. (specifically
// GetYCbCrToRGBDestFormatAndSize and ConvertYCbCrToRGB)
return false;
default:
return false;
}
}
static bool
GetFormatForPackingTuple(GLenum packingFormat, GLenum packingType,
WebGLTexelFormat* const out_texelFormat)
{
switch (packingType) {
case LOCAL_GL_UNSIGNED_BYTE:
switch (packingFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_LUMINANCE:
*out_texelFormat = WebGLTexelFormat::R8;
return true;
case LOCAL_GL_ALPHA:
*out_texelFormat = WebGLTexelFormat::A8;
return true;
case LOCAL_GL_LUMINANCE_ALPHA:
*out_texelFormat = WebGLTexelFormat::RA8;
return true;
case LOCAL_GL_RGB:
*out_texelFormat = WebGLTexelFormat::RGB8;
return true;
case LOCAL_GL_RGBA:
*out_texelFormat = WebGLTexelFormat::RGBA8;
return true;
default:
break;
}
break;
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
switch (packingFormat) {
case LOCAL_GL_RGB:
*out_texelFormat = WebGLTexelFormat::RGB565;
return true;
default:
break;
}
break;
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
switch (packingFormat) {
case LOCAL_GL_RGBA:
*out_texelFormat = WebGLTexelFormat::RGBA5551;
return true;
default:
break;
}
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
switch (packingFormat) {
case LOCAL_GL_RGBA:
*out_texelFormat = WebGLTexelFormat::RGBA4444;
return true;
default:
break;
}
break;
case LOCAL_GL_HALF_FLOAT:
case LOCAL_GL_HALF_FLOAT_OES:
switch (packingFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_LUMINANCE:
*out_texelFormat = WebGLTexelFormat::R16F;
return true;
case LOCAL_GL_ALPHA:
*out_texelFormat = WebGLTexelFormat::A16F;
return true;
case LOCAL_GL_LUMINANCE_ALPHA:
*out_texelFormat = WebGLTexelFormat::RA16F;
return true;
case LOCAL_GL_RGB:
*out_texelFormat = WebGLTexelFormat::RGB16F;
return true;
case LOCAL_GL_RGBA:
*out_texelFormat = WebGLTexelFormat::RGBA16F;
return true;
default:
break;
}
break;
case LOCAL_GL_FLOAT:
switch (packingFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_LUMINANCE:
*out_texelFormat = WebGLTexelFormat::R32F;
return true;
case LOCAL_GL_ALPHA:
*out_texelFormat = WebGLTexelFormat::A32F;
return true;
case LOCAL_GL_LUMINANCE_ALPHA:
*out_texelFormat = WebGLTexelFormat::RA32F;
return true;
case LOCAL_GL_RGB:
*out_texelFormat = WebGLTexelFormat::RGB32F;
return true;
case LOCAL_GL_RGBA:
*out_texelFormat = WebGLTexelFormat::RGBA32F;
return true;
default:
break;
}
break;
default:
break;
}
NS_ERROR("Unsupported EffectiveFormat dest format for DOM element upload.");
return false;
}
/*static*/ bool
TexUnpackSurface::ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
UniqueBuffer* const out_convertedBuffer,
uint8_t* const out_convertedAlignment,
bool* const out_outOfMemory)
{
*out_outOfMemory = false;
const size_t width = surf->GetSize().width;
const size_t height = surf->GetSize().height;
// Source args:
// After we call this, on OSX, our GLContext will no longer be current.
gfx::DataSourceSurface::ScopedMap srcMap(surf, gfx::DataSourceSurface::MapType::READ);
if (!srcMap.IsMapped())
return false;
const void* const srcBegin = srcMap.GetData();
const size_t srcStride = srcMap.GetStride();
WebGLTexelFormat srcFormat;
if (!GetFormatForSurf(surf, &srcFormat))
return false;
const bool srcPremultiplied = isSurfAlphaPremult;
// Dest args:
WebGLTexelFormat dstFormat;
if (!GetFormatForPackingTuple(dui->unpackFormat, dui->unpackType, &dstFormat))
return false;
const auto bytesPerPixel = webgl::BytesPerPixel({dui->unpackFormat, dui->unpackType});
const size_t dstRowBytes = bytesPerPixel * width;
const size_t dstAlignment = 8; // Just use the max!
const size_t dstStride = RoundUpToMultipleOf(dstRowBytes, dstAlignment);
CheckedUint32 checkedDstSize = dstStride;
checkedDstSize *= height;
if (!checkedDstSize.isValid()) {
*out_outOfMemory = true;
return false;
}
const size_t dstSize = checkedDstSize.value();
UniqueBuffer dstBuffer = malloc(dstSize);
if (!dstBuffer) {
*out_outOfMemory = true;
return false;
}
void* const dstBegin = dstBuffer.get();
gl::OriginPos srcOrigin, dstOrigin;
OriginsForDOM(webgl, &srcOrigin, &dstOrigin);
const bool dstPremultiplied = webgl->mPixelStore_PremultiplyAlpha;
// And go!:
if (!ConvertImage(width, height,
srcBegin, srcStride, srcOrigin, srcFormat, srcPremultiplied,
dstBegin, dstStride, dstOrigin, dstFormat, dstPremultiplied))
{
MOZ_ASSERT(false, "ConvertImage failed unexpectedly.");
NS_ERROR("ConvertImage failed unexpectedly.");
*out_outOfMemory = true;
return false;
}
*out_convertedBuffer = Move(dstBuffer);
*out_convertedAlignment = dstAlignment;
return true;
}
////////////////////
TexUnpackSurface::TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf,
bool isAlphaPremult)
: TexUnpackBlob(surf->GetSize().width, surf->GetSize().height, 1, true)
, mSurf(surf)
, mIsAlphaPremult(isAlphaPremult)
{ }
TexUnpackSurface::~TexUnpackSurface()
{ }
void
TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum* const out_glError)
{
*out_glError = 0;
WebGLContext* webgl = tex->mContext;
// MakeCurrent is a big mess in here, because mapping (and presumably unmapping) on
// OSX can lose our MakeCurrent. Therefore it's easiest to MakeCurrent just before we
// call into GL, instead of trying to keep MakeCurrent-ed.
RefPtr<gfx::DataSourceSurface> dataSurf = mSurf->GetDataSurface();
MOZ_ASSERT(dataSurf);
GLenum error;
if (UploadDataSurface(isSubImage, webgl, target, level, dui, xOffset, yOffset,
zOffset, mWidth, mHeight, dataSurf, mIsAlphaPremult, &error))
{
return;
}
if (error == LOCAL_GL_OUT_OF_MEMORY) {
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
return;
}
// CPU conversion. (++numCopies)
UniqueBuffer convertedBuffer;
uint8_t convertedAlignment;
bool outOfMemory;
if (!ConvertSurface(webgl, dui, dataSurf, mIsAlphaPremult, &convertedBuffer,
&convertedAlignment, &outOfMemory))
{
if (outOfMemory) {
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
} else {
NS_ERROR("Failed to convert surface.");
*out_glError = LOCAL_GL_OUT_OF_MEMORY;
}
return;
}
MOZ_ALWAYS_TRUE( webgl->gl->MakeCurrent() );
ScopedUnpackReset scopedReset(webgl);
webgl->gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, convertedAlignment);
error = DoTexOrSubImage(isSubImage, webgl->gl, target.get(), level, dui, xOffset,
yOffset, zOffset, mWidth, mHeight, mDepth,
convertedBuffer.get());
*out_glError = error;
}
} // namespace webgl
} // namespace mozilla

View File

@ -1,162 +0,0 @@
/* -*- 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/. */
#ifndef TEX_UNPACK_BLOB_H_
#define TEX_UNPACK_BLOB_H_
#include "GLContextTypes.h"
#include "GLTypes.h"
#include "WebGLStrongTypes.h"
template <class T>
class RefPtr;
namespace mozilla {
class UniqueBuffer;
class WebGLContext;
class WebGLTexture;
namespace dom {
class Element;
class HTMLCanvasElement;
class HTMLVideoElement;
} // namespace dom
namespace gfx {
class DataSourceSurface;
} // namespace gfx
namespace gl {
class GLContext;
} // namespace gl
namespace layers {
class Image;
class ImageContainer;
} // namespace layers
namespace webgl {
struct PackingInfo;
struct DriverUnpackInfo;
class TexUnpackBlob
{
public:
const GLsizei mWidth;
const GLsizei mHeight;
const GLsizei mDepth;
const bool mHasData;
protected:
TexUnpackBlob(GLsizei width, GLsizei height, GLsizei depth, bool hasData)
: mWidth(width)
, mHeight(height)
, mDepth(depth)
, mHasData(hasData)
{ }
public:
virtual ~TexUnpackBlob() {}
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
const webgl::PackingInfo& pi) = 0;
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_glError) = 0;
static void OriginsForDOM(WebGLContext* webgl, gl::OriginPos* const out_src,
gl::OriginPos* const out_dst);
};
class TexUnpackBytes : public TexUnpackBlob
{
public:
const size_t mByteCount;
const void* const mBytes;
TexUnpackBytes(GLsizei width, GLsizei height, GLsizei depth, size_t byteCount,
const void* bytes)
: TexUnpackBlob(width, height, depth, bool(bytes))
, mByteCount(byteCount)
, mBytes(bytes)
{ }
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
const webgl::PackingInfo& pi) override;
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_glError) override;
};
class TexUnpackImage : public TexUnpackBlob
{
public:
const RefPtr<layers::Image> mImage;
const bool mIsAlphaPremult;
TexUnpackImage(const RefPtr<layers::Image>& image, bool isAlphaPremult);
virtual ~TexUnpackImage() override;
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
const webgl::PackingInfo& pi) override
{
return true;
}
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_glError) override;
};
class TexUnpackSurface : public TexUnpackBlob
{
public:
const RefPtr<gfx::SourceSurface> mSurf;
const bool mIsAlphaPremult;
TexUnpackSurface(const RefPtr<gfx::SourceSurface>& surf, bool isAlphaPremult);
virtual ~TexUnpackSurface() override;
virtual bool ValidateUnpack(WebGLContext* webgl, const char* funcName, bool isFunc3D,
const webgl::PackingInfo& pi) override
{
return true;
}
virtual void TexOrSubImage(bool isSubImage, bool needsRespec, const char* funcName,
WebGLTexture* tex, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset,
GLenum* const out_glError) override;
protected:
static bool ConvertSurface(WebGLContext* webgl, const webgl::DriverUnpackInfo* dui,
gfx::DataSourceSurface* surf, bool isSurfAlphaPremult,
UniqueBuffer* const out_convertedBuffer,
uint8_t* const out_convertedAlignment,
bool* const out_outOfMemory);
static bool UploadDataSurface(bool isSubImage, WebGLContext* webgl,
TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, gfx::DataSourceSurface* surf,
bool isSurfAlphaPremult, GLenum* const out_glError);
};
} // namespace webgl
} // namespace mozilla
#endif // TEX_UNPACK_BLOB_H_

View File

@ -27,9 +27,9 @@ WebGL1Context::~WebGL1Context()
}
UniquePtr<webgl::FormatUsageAuthority>
WebGL1Context::CreateFormatUsage(gl::GLContext* gl) const
WebGL1Context::CreateFormatUsage() const
{
return webgl::FormatUsageAuthority::CreateForWebGL1(gl);
return webgl::FormatUsageAuthority::CreateForWebGL1();
}
JSObject*

View File

@ -18,9 +18,7 @@ public:
private:
WebGL1Context();
virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const override;
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const override;
public:
virtual ~WebGL1Context();

View File

@ -29,9 +29,9 @@ WebGL2Context::~WebGL2Context()
}
UniquePtr<webgl::FormatUsageAuthority>
WebGL2Context::CreateFormatUsage(gl::GLContext* gl) const
WebGL2Context::CreateFormatUsage() const
{
return webgl::FormatUsageAuthority::CreateForWebGL2(gl);
return webgl::FormatUsageAuthority::CreateForWebGL2();
}
/*static*/ bool
@ -55,6 +55,20 @@ WebGL2Context::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
////////////////////////////////////////////////////////////////////////////////
// WebGL 2 initialisation
// These WebGL 1 extensions are natively supported by WebGL 2.
static const WebGLExtensionID kNativelySupportedExtensions[] = {
WebGLExtensionID::ANGLE_instanced_arrays,
WebGLExtensionID::EXT_blend_minmax,
WebGLExtensionID::EXT_sRGB,
WebGLExtensionID::OES_element_index_uint,
WebGLExtensionID::OES_standard_derivatives,
WebGLExtensionID::OES_texture_float_linear,
WebGLExtensionID::OES_texture_half_float_linear,
WebGLExtensionID::OES_vertex_array_object,
WebGLExtensionID::WEBGL_depth_texture,
WebGLExtensionID::WEBGL_draw_buffers
};
static const gl::GLFeature kRequiredFeatures[] = {
gl::GLFeature::blend_minmax,
gl::GLFeature::clear_buffers,
@ -137,25 +151,35 @@ WebGLContext::InitWebGL2()
return false;
}
// ok WebGL 2 is compatible, we can enable natively supported extensions.
for (size_t i = 0; i < ArrayLength(kNativelySupportedExtensions); i++) {
EnableExtension(kNativelySupportedExtensions[i]);
MOZ_ASSERT(IsExtensionEnabled(kNativelySupportedExtensions[i]));
}
// we initialise WebGL 2 related stuff.
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
&mGLMaxTransformFeedbackSeparateAttribs);
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
&mGLMaxUniformBufferBindings);
if (MinCapabilityMode()) {
mGLMax3DTextureSize = MINVALUE_GL_MAX_3D_TEXTURE_SIZE;
mGLMaxArrayTextureLayers = MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS;
} else {
gl->fGetIntegerv(LOCAL_GL_MAX_3D_TEXTURE_SIZE,
(GLint*) &mGLMax3DTextureSize);
gl->fGetIntegerv(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS,
(GLint*) &mGLMaxArrayTextureLayers);
}
mBoundTransformFeedbackBuffers.SetLength(mGLMaxTransformFeedbackSeparateAttribs);
mBoundUniformBuffers.SetLength(mGLMaxUniformBufferBindings);
mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
mBoundTransformFeedback = mDefaultTransformFeedback;
if (!gl->IsGLES()) {
// Desktop OpenGL requires the following to be enabled in order to
// support sRGB operations on framebuffers.
gl->MakeCurrent();
gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
}
return true;
}

View File

@ -8,6 +8,12 @@
#include "WebGLContext.h"
/*
* Minimum value constants define in 6.2 State Tables of OpenGL ES - 3.0.4
*/
#define MINVALUE_GL_MAX_3D_TEXTURE_SIZE 256
#define MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS 256
namespace mozilla {
class ErrorResult;
@ -90,47 +96,37 @@ public:
// -------------------------------------------------------------------------
// Texture objects - WebGL2ContextTextures.cpp
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
GLsizei height);
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth);
void TexImage3D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels);
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& out_rv);
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
dom::ImageData* data, ErrorResult& out_rv);
protected:
void TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_rv);
public:
template<class T>
inline void
TexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset,
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_rv)
{
TexSubImage3D(target, level, xOffset, yOffset, zOffset, unpackFormat, unpackType,
&elem, &out_rv);
}
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
GLsizei depth);
void TexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv);
void TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
ErrorResult& rv);
void TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, dom::ImageData* data,
ErrorResult& rv);
template<class ElementType>
void TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, ElementType& elt, ErrorResult& rv)
{}
void CopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLint x, GLint y, GLsizei width,
GLsizei height);
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height);
void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border,
const dom::ArrayBufferViewOrSharedArrayBufferView& data);
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum sizedUnpackFormat,
const dom::ArrayBufferViewOrSharedArrayBufferView& data);
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& data);
// -------------------------------------------------------------------------
@ -387,8 +383,7 @@ public:
private:
WebGL2Context();
virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const override;
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const override;
virtual bool IsTexParamValid(GLenum pname) const override;

View File

@ -13,12 +13,107 @@
namespace mozilla {
using gl::GLContext;
using gl::GLFormats;
using webgl::EffectiveFormat;
using webgl::FormatInfo;
using webgl::ComponentType;
// Returns one of FLOAT, INT, UNSIGNED_INT.
// Fixed-points (normalized ints) are considered FLOAT.
static GLenum
ValueTypeForFormat(GLenum internalFormat)
{
switch (internalFormat) {
// Fixed-point
case LOCAL_GL_R8:
case LOCAL_GL_RG8:
case LOCAL_GL_RGB565:
case LOCAL_GL_RGB8:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_RGBA8:
case LOCAL_GL_RGB10_A2:
case LOCAL_GL_ALPHA8:
case LOCAL_GL_LUMINANCE8:
case LOCAL_GL_LUMINANCE8_ALPHA8:
case LOCAL_GL_SRGB8:
case LOCAL_GL_SRGB8_ALPHA8:
case LOCAL_GL_R8_SNORM:
case LOCAL_GL_RG8_SNORM:
case LOCAL_GL_RGB8_SNORM:
case LOCAL_GL_RGBA8_SNORM:
// Floating-point
case LOCAL_GL_R16F:
case LOCAL_GL_RG16F:
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGBA16F:
case LOCAL_GL_ALPHA16F_EXT:
case LOCAL_GL_LUMINANCE16F_EXT:
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
case LOCAL_GL_R32F:
case LOCAL_GL_RG32F:
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGBA32F:
case LOCAL_GL_ALPHA32F_EXT:
case LOCAL_GL_LUMINANCE32F_EXT:
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
case LOCAL_GL_R11F_G11F_B10F:
case LOCAL_GL_RGB9_E5:
return LOCAL_GL_FLOAT;
// Int
case LOCAL_GL_R8I:
case LOCAL_GL_RG8I:
case LOCAL_GL_RGB8I:
case LOCAL_GL_RGBA8I:
case LOCAL_GL_R16I:
case LOCAL_GL_RG16I:
case LOCAL_GL_RGB16I:
case LOCAL_GL_RGBA16I:
case LOCAL_GL_R32I:
case LOCAL_GL_RG32I:
case LOCAL_GL_RGB32I:
case LOCAL_GL_RGBA32I:
return LOCAL_GL_INT;
// Unsigned int
case LOCAL_GL_R8UI:
case LOCAL_GL_RG8UI:
case LOCAL_GL_RGB8UI:
case LOCAL_GL_RGBA8UI:
case LOCAL_GL_R16UI:
case LOCAL_GL_RG16UI:
case LOCAL_GL_RGB16UI:
case LOCAL_GL_RGBA16UI:
case LOCAL_GL_R32UI:
case LOCAL_GL_RG32UI:
case LOCAL_GL_RGB32UI:
case LOCAL_GL_RGBA32UI:
case LOCAL_GL_RGB10_A2UI:
return LOCAL_GL_UNSIGNED_INT;
default:
MOZ_CRASH("Bad `internalFormat`.");
}
}
// -------------------------------------------------------------------------
// Framebuffer objects
static bool
GetFBInfoForBlit(const WebGLFramebuffer* fb, WebGLContext* webgl,
const char* const fbInfo, GLsizei* const out_samples,
const webgl::FormatInfo** const out_colorFormat,
const webgl::FormatInfo** const out_depthFormat,
const webgl::FormatInfo** const out_stencilFormat)
GLenum* const out_colorFormat, GLenum* const out_depthFormat,
GLenum* const out_stencilFormat)
{
auto status = fb->PrecheckFramebufferStatus();
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
@ -28,58 +123,36 @@ GetFBInfoForBlit(const WebGLFramebuffer* fb, WebGLContext* webgl,
}
*out_samples = 1; // TODO
*out_colorFormat = nullptr;
*out_depthFormat = nullptr;
*out_stencilFormat = nullptr;
if (fb->ColorAttachment(0).IsDefined()) {
const auto& attachment = fb->ColorAttachment(0);
*out_colorFormat = attachment.Format()->format;
const auto& attachement = fb->ColorAttachment(0);
*out_colorFormat = attachement.EffectiveInternalFormat().get();
} else {
*out_colorFormat = 0;
}
if (fb->DepthStencilAttachment().IsDefined()) {
const auto& attachment = fb->DepthStencilAttachment();
*out_depthFormat = attachment.Format()->format;
const auto& attachement = fb->DepthStencilAttachment();
*out_depthFormat = attachement.EffectiveInternalFormat().get();
*out_stencilFormat = *out_depthFormat;
} else {
if (fb->DepthAttachment().IsDefined()) {
const auto& attachment = fb->DepthAttachment();
*out_depthFormat = attachment.Format()->format;
const auto& attachement = fb->DepthAttachment();
*out_depthFormat = attachement.EffectiveInternalFormat().get();
} else {
*out_depthFormat = 0;
}
if (fb->StencilAttachment().IsDefined()) {
const auto& attachment = fb->StencilAttachment();
*out_stencilFormat = attachment.Format()->format;
const auto& attachement = fb->StencilAttachment();
*out_stencilFormat = attachement.EffectiveInternalFormat().get();
} else {
*out_stencilFormat = 0;
}
}
return true;
}
static void
GetBackbufferFormats(const WebGLContextOptions& options,
const webgl::FormatInfo** const out_color,
const webgl::FormatInfo** const out_depth,
const webgl::FormatInfo** const out_stencil)
{
const auto effFormat = options.alpha ? webgl::EffectiveFormat::RGBA8
: webgl::EffectiveFormat::RGB8;
*out_color = webgl::GetFormat(effFormat);
*out_depth = nullptr;
*out_stencil = nullptr;
if (options.depth && options.stencil) {
*out_depth = webgl::GetFormat(webgl::EffectiveFormat::DEPTH24_STENCIL8);
*out_stencil = *out_depth;
} else {
if (options.depth) {
*out_depth = webgl::GetFormat(webgl::EffectiveFormat::DEPTH_COMPONENT16);
}
if (options.stencil) {
*out_stencil = webgl::GetFormat(webgl::EffectiveFormat::STENCIL_INDEX8);
}
}
}
void
WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
@ -123,9 +196,9 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
}
GLsizei srcSamples;
const webgl::FormatInfo* srcColorFormat = nullptr;
const webgl::FormatInfo* srcDepthFormat = nullptr;
const webgl::FormatInfo* srcStencilFormat = nullptr;
GLenum srcColorFormat = 0;
GLenum srcDepthFormat = 0;
GLenum srcStencilFormat = 0;
if (mBoundReadFramebuffer) {
if (!GetFBInfoForBlit(mBoundReadFramebuffer, this, "READ_FRAMEBUFFER",
@ -137,14 +210,26 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
} else {
srcSamples = 1; // Always 1.
GetBackbufferFormats(mOptions, &srcColorFormat, &srcDepthFormat,
&srcStencilFormat);
// TODO: Don't hardcode these.
srcColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
if (mOptions.depth && mOptions.stencil) {
srcDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
srcStencilFormat = srcDepthFormat;
} else {
if (mOptions.depth) {
srcDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
}
if (mOptions.stencil) {
srcStencilFormat = LOCAL_GL_STENCIL_INDEX8;
}
}
}
GLsizei dstSamples;
const webgl::FormatInfo* dstColorFormat = nullptr;
const webgl::FormatInfo* dstDepthFormat = nullptr;
const webgl::FormatInfo* dstStencilFormat = nullptr;
GLenum dstColorFormat = 0;
GLenum dstDepthFormat = 0;
GLenum dstStencilFormat = 0;
if (mBoundDrawFramebuffer) {
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, this, "DRAW_FRAMEBUFFER",
@ -156,39 +241,36 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
} else {
dstSamples = gl->Screen()->Samples();
GetBackbufferFormats(mOptions, &dstColorFormat, &dstDepthFormat,
&dstStencilFormat);
// TODO: Don't hardcode these.
dstColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
if (mOptions.depth && mOptions.stencil) {
dstDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
dstStencilFormat = dstDepthFormat;
} else {
if (mOptions.depth) {
dstDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
}
if (mOptions.stencil) {
dstStencilFormat = LOCAL_GL_STENCIL_INDEX8;
}
}
}
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
const auto fnSignlessType = [](const webgl::FormatInfo* format)
-> webgl::ComponentType
{
if (!format)
return webgl::ComponentType::None;
switch (format->componentType) {
case webgl::ComponentType::UInt:
return webgl::ComponentType::Int;
case webgl::ComponentType::NormUInt:
return webgl::ComponentType::NormInt;
default:
return format->componentType;
}
};
const auto srcType = fnSignlessType(srcColorFormat);
const auto dstType = fnSignlessType(dstColorFormat);
if (srcType != dstType) {
ErrorInvalidOperation("blitFramebuffer: Color buffer format component type"
const GLenum srcColorType = srcColorFormat ? ValueTypeForFormat(srcColorFormat)
: 0;
const GLenum dstColorType = dstColorFormat ? ValueTypeForFormat(dstColorFormat)
: 0;
if (dstColorType != srcColorType) {
ErrorInvalidOperation("blitFramebuffer: Color buffer value type"
" mismatch.");
return;
}
const bool srcIsInt = (srcType == webgl::ComponentType::Int);
const bool srcIsInt = srcColorType == LOCAL_GL_INT ||
srcColorType == LOCAL_GL_UNSIGNED_INT;
if (srcIsInt && filter != LOCAL_GL_NEAREST) {
ErrorInvalidOperation("blitFramebuffer: Integer read buffers can only"
" be filtered with NEAREST.");
@ -296,16 +378,16 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
if (level < 0)
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
switch (texture->Target().get()) {
switch (texture->Target()) {
case LOCAL_GL_TEXTURE_3D:
if (uint32_t(layer) >= mImplMax3DTextureSize) {
if ((GLuint) layer >= mGLMax3DTextureSize) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_3D_TEXTURE_SIZE");
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
if (uint32_t(layer) >= mImplMaxArrayTextureLayers) {
if ((GLuint) layer >= mGLMaxArrayTextureLayers) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_ARRAY_TEXTURE_LAYERS");
}
@ -315,6 +397,9 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
"existing 3D texture, or a 2D texture array.");
}
} else {
return ErrorInvalidOperation("framebufferTextureLayer: texture must be an "
"existing 3D texture, or a 2D texture array.");
}
WebGLFramebuffer* fb;
@ -345,10 +430,96 @@ WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
GLenum target,
GLenum attachment,
GLenum pname,
ErrorResult& out_error)
ErrorResult& rv)
{
return WebGLContext::GetFramebufferAttachmentParameter(cx, target, attachment, pname,
out_error);
if (IsContextLost())
return JS::NullValue();
// OpenGL ES 3.0.4 (August 27, 2014) 6.1. QUERYING GL STATE 240
// "getFramebufferAttachmentParamter returns information about attachments of a bound
// framebuffer object. target must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or
// FRAMEBUFFER."
if (!ValidateFramebufferTarget(target, "getFramebufferAttachmentParameter"))
return JS::NullValue();
// FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER.
if (target == LOCAL_GL_FRAMEBUFFER)
target = LOCAL_GL_DRAW_FRAMEBUFFER;
WebGLFramebuffer* boundFB = nullptr;
switch (target) {
case LOCAL_GL_DRAW_FRAMEBUFFER: boundFB = mBoundDrawFramebuffer; break;
case LOCAL_GL_READ_FRAMEBUFFER: boundFB = mBoundReadFramebuffer; break;
}
if (boundFB) {
return boundFB->GetAttachmentParameter(cx, attachment, pname, rv);
}
// Handle default FB
const gl::GLFormats& formats = gl->GetGLFormats();
GLenum internalFormat = LOCAL_GL_NONE;
/* If the default framebuffer is bound to target, then attachment must be BACK,
identifying the color buffer; DEPTH, identifying the depth buffer; or STENCIL,
identifying the stencil buffer. */
switch (attachment) {
case LOCAL_GL_BACK:
internalFormat = formats.color_texInternalFormat;
break;
case LOCAL_GL_DEPTH:
internalFormat = formats.depth;
break;
case LOCAL_GL_STENCIL:
internalFormat = formats.stencil;
break;
default:
ErrorInvalidEnum("getFramebufferAttachmentParameter: Can only query "
"attachment BACK, DEPTH, or STENCIL from default "
"framebuffer");
return JS::NullValue();
}
const FormatInfo* info = webgl::GetInfoBySizedFormat(internalFormat);
MOZ_RELEASE_ASSERT(info);
EffectiveFormat effectiveFormat = info->effectiveFormat;
switch (pname) {
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
return JS::Int32Value(LOCAL_GL_FRAMEBUFFER_DEFAULT);
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
return JS::Int32Value(webgl::GetComponentSize(effectiveFormat, pname));
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT &&
pname == LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)
{
ErrorInvalidOperation("getFramebufferAttachmentParameter: Querying "
"FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE against "
"DEPTH_STENCIL_ATTACHMENT is an error.");
return JS::NullValue();
}
return JS::Int32Value(webgl::GetComponentType(effectiveFormat));
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
return JS::Int32Value(webgl::GetColorEncoding(effectiveFormat));
}
/* Any combinations of framebuffer type and pname not described above will generate an
INVALID_ENUM error. */
ErrorInvalidEnum("getFramebufferAttachmentParameter: Invalid combination of ");
return JS::NullValue();
}
// Map attachments intended for the default buffer, to attachments for a non-
@ -386,14 +557,12 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
const dom::Sequence<GLenum>& attachments,
ErrorResult& rv)
{
const char funcName[] = "invalidateSubFramebuffer";
if (IsContextLost())
return;
MakeContextCurrent();
if (!ValidateFramebufferTarget(target, funcName))
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
return;
const WebGLFramebuffer* fb;
@ -414,10 +583,9 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
MOZ_CRASH("Bad target.");
}
const bool badColorAttachmentIsInvalidOp = true;
for (size_t i = 0; i < attachments.Length(); i++) {
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
badColorAttachmentIsInvalidOp))
if (!ValidateFramebufferAttachment(fb, attachments[i],
"invalidateFramebuffer"))
{
return;
}
@ -426,7 +594,8 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
// InvalidateFramebuffer is a hint to the driver. Should be OK to
// skip calls if not supported, for example by OSX 10.9 GL
// drivers.
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
if (!invalidateFBSupported)
return;
if (!fb && !isDefaultFB) {
@ -436,8 +605,7 @@ WebGL2Context::InvalidateFramebuffer(GLenum target,
return;
}
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(),
tmpAttachments.Elements());
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements());
} else {
gl->fInvalidateFramebuffer(target, attachments.Length(), attachments.Elements());
}
@ -448,21 +616,14 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
GLint x, GLint y, GLsizei width, GLsizei height,
ErrorResult& rv)
{
const char funcName[] = "invalidateSubFramebuffer";
if (IsContextLost())
return;
MakeContextCurrent();
if (!ValidateFramebufferTarget(target, funcName))
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
return;
if (width < 0 || height < 0) {
ErrorInvalidValue("%s: width and height must be >= 0.", funcName);
return;
}
const WebGLFramebuffer* fb;
bool isDefaultFB;
switch (target) {
@ -481,10 +642,9 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
MOZ_CRASH("Bad target.");
}
const bool badColorAttachmentIsInvalidOp = true;
for (size_t i = 0; i < attachments.Length(); i++) {
if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
badColorAttachmentIsInvalidOp))
if (!ValidateFramebufferAttachment(fb, attachments[i],
"invalidateSubFramebuffer"))
{
return;
}
@ -493,7 +653,8 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
// InvalidateFramebuffer is a hint to the driver. Should be OK to
// skip calls if not supported, for example by OSX 10.9 GL
// drivers.
if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
if (!invalidateFBSupported)
return;
if (!fb && !isDefaultFB) {
@ -503,11 +664,11 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
return;
}
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(),
tmpAttachments.Elements(), x, y, width, height);
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements(),
x, y, width, height);
} else {
gl->fInvalidateSubFramebuffer(target, attachments.Length(),
attachments.Elements(), x, y, width, height);
gl->fInvalidateSubFramebuffer(target, attachments.Length(), attachments.Elements(),
x, y, width, height);
}
}
@ -518,7 +679,7 @@ WebGL2Context::ReadBuffer(GLenum mode)
return;
const bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 &&
mode <= LastColorAttachmentEnum());
mode <= LastColorAttachment());
if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK && !isColorAttachment) {
ErrorInvalidEnum("readBuffer: `mode` must be one of NONE, BACK, or "

View File

@ -59,6 +59,8 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
/* fall through */
/* GLint */
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
case LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS:
case LOCAL_GL_MAX_ELEMENTS_INDICES:
case LOCAL_GL_MAX_ELEMENTS_VERTICES:
@ -87,12 +89,6 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::Int32Value(val);
}
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
return JS::Int32Value(mImplMax3DTextureSize);
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
return JS::Int32Value(mImplMaxArrayTextureLayers);
case LOCAL_GL_MAX_VARYING_COMPONENTS: {
// On OS X Core Profile this is buggy. The spec says that the
// value is 4 * GL_MAX_VARYING_VECTORS
@ -155,7 +151,9 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return WebGLObjectAsJSValue(cx, mBoundSamplers[mActiveTexture].get(), rv);
case LOCAL_GL_TEXTURE_BINDING_2D_ARRAY:
return WebGLObjectAsJSValue(cx, mBound2DArrayTextures[mActiveTexture].get(), rv);
// TODO: Implement gl.TEXTURE_2D_ARRAY
// return WebGLObjectAsJSValue(cx, mBound2DTextureArrays[mActiveTexture].get(), rv);
return JS::NullValue();
case LOCAL_GL_TEXTURE_BINDING_3D:
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);

View File

@ -11,19 +11,15 @@
namespace mozilla {
void
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height)
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
{
const char funcName[] = "TexStorage2D";
const uint8_t funcDims = 2;
TexTarget target;
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
const GLsizei depth = 1;
tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
tex->TexStorage2D(texTarget, levels, internalFormat, width, height);
}
void
@ -31,178 +27,88 @@ WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internal
GLsizei width, GLsizei height, GLsizei depth)
{
const char funcName[] = "texStorage3D";
const uint8_t funcDims = 3;
TexTarget target;
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &target, &tex))
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
tex->TexStorage(funcName, target, levels, internalFormat, width, height, depth);
tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
}
void
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView)
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
const char funcName[] = "texImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, maybeView);
tex->TexImage3D(texImageTarget, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum unpackFormat, GLenum unpackType,
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult& /*out_rv*/)
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint border = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, maybeView);
tex->TexSubImage3D(texImageTarget, level, xOffset, yOffset, zOffset, width, height,
depth, unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::ImageData* imageData,
ErrorResult& /*out_rv*/)
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, imageData);
GenerateWarning("texSubImage3D: Not implemented.");
}
void
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, dom::Element* elem,
ErrorResult* const out_rv)
WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
const char funcName[] = "texSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, elem, out_rv);
GenerateWarning("copyTexSubImage3D: Not implemented.");
}
void
WebGL2Context::CompressedTexImage3D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border,
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
WebGL2Context::CompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const char funcName[] = "compressedTexImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
border, view);
GenerateWarning("compressedTexImage3D: Not implemented.");
}
void
WebGL2Context::CompressedTexSubImage3D(GLenum rawTexImageTarget, 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 sizedUnpackFormat,
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
GLenum unpackFormat, GLsizei imageSize, const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const char funcName[] = "compressedTexSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
height, depth, sizedUnpackFormat, view);
GenerateWarning("compressedTexSubImage3D: Not implemented.");
}
void
WebGL2Context::CopyTexSubImage3D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLint x, GLint y,
GLsizei width, GLsizei height)
{
const char funcName[] = "copyTexSubImage3D";
const uint8_t funcDims = 3;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
height);
}
/*virtual*/ bool
bool
WebGL2Context::IsTexParamValid(GLenum pname) const
{
switch (pname) {

View File

@ -55,7 +55,7 @@ public:
bool IsElementArrayUsedWithMultipleTypes() const;
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;

View File

@ -95,10 +95,6 @@ WebGLContextOptions::WebGLContextOptions()
alpha = false;
}
/*static*/ const uint32_t WebGLContext::kMinMaxColorAttachments = 4;
/*static*/ const uint32_t WebGLContext::kMinMaxDrawBuffers = 4;
WebGLContext::WebGLContext()
: WebGLContextUnchecked(nullptr)
, mBypassShaderValidation(false)
@ -115,6 +111,11 @@ WebGLContext::WebGLContext()
mOptionsFrozen = false;
mActiveTexture = 0;
mPixelStoreFlipY = false;
mPixelStorePremultiplyAlpha = false;
mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
mVertexAttrib0Vector[0] = 0;
mVertexAttrib0Vector[1] = 0;
@ -139,6 +140,31 @@ WebGLContext::WebGLContext()
mDepthTestEnabled = 0;
mStencilTestEnabled = 0;
// initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
// so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
mGLMaxVertexAttribs = 0;
mGLMaxTextureUnits = 0;
mGLMaxTextureSize = 0;
mGLMaxTextureSizeLog2 = 0;
mGLMaxCubeMapTextureSize = 0;
mGLMaxCubeMapTextureSizeLog2 = 0;
mGLMaxRenderbufferSize = 0;
mGLMaxTextureImageUnits = 0;
mGLMaxVertexTextureImageUnits = 0;
mGLMaxVaryingVectors = 0;
mGLMaxFragmentUniformVectors = 0;
mGLMaxVertexUniformVectors = 0;
mGLMaxColorAttachments = 1;
mGLMaxDrawBuffers = 1;
mGLMaxTransformFeedbackSeparateAttribs = 0;
mGLMaxUniformBufferBindings = 0;
mGLMax3DTextureSize = 0;
mGLMaxArrayTextureLayers = 0;
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
mPixelStorePackAlignment = 4;
mPixelStoreUnpackAlignment = 4;
if (NS_IsMainThread()) {
// XXX mtseng: bug 709490, not thread safe
WebGLMemoryTracker::AddWebGLContext(this);
@ -198,7 +224,6 @@ WebGLContext::DestroyResourcesAndContext()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBound2DArrayTextures.Clear();
mBoundSamplers.Clear();
mBoundArrayBuffer = nullptr;
mBoundCopyReadBuffer = nullptr;
@ -242,14 +267,10 @@ WebGLContext::DestroyResourcesAndContext()
while (!mTransformFeedbacks.isEmpty())
mTransformFeedbacks.getLast()->DeleteOnce();
mFakeBlack_2D_0000 = nullptr;
mFakeBlack_2D_0001 = nullptr;
mFakeBlack_CubeMap_0000 = nullptr;
mFakeBlack_CubeMap_0001 = nullptr;
mFakeBlack_3D_0000 = nullptr;
mFakeBlack_3D_0001 = nullptr;
mFakeBlack_2D_Array_0000 = nullptr;
mFakeBlack_2D_Array_0001 = nullptr;
mBlackOpaqueTexture2D = nullptr;
mBlackOpaqueTextureCubeMap = nullptr;
mBlackTransparentTexture2D = nullptr;
mBlackTransparentTextureCubeMap = nullptr;
if (mFakeVertexAttrib0BufferObject)
gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
@ -1277,37 +1298,37 @@ WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
void
WebGLContext::ClearScreen()
{
bool colorAttachmentsMask[WebGLContext::kMaxColorAttachments] = {false};
MakeContextCurrent();
ScopedBindFramebuffer autoFB(gl, 0);
const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK);
if (changeDrawBuffers) {
const GLenum back = LOCAL_GL_BACK;
gl->fDrawBuffers(1, &back);
}
GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT;
GLbitfield clearMask = LOCAL_GL_COLOR_BUFFER_BIT;
if (mOptions.depth)
bufferBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
clearMask |= LOCAL_GL_DEPTH_BUFFER_BIT;
if (mOptions.stencil)
bufferBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
clearMask |= LOCAL_GL_STENCIL_BUFFER_BIT;
ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha);
colorAttachmentsMask[0] = true;
if (changeDrawBuffers) {
gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0);
}
ForceClearFramebufferWithDefaultValues(mNeedsFakeNoAlpha, clearMask,
colorAttachmentsMask);
}
void
WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
bool fakeNoAlpha)
WebGLContext::ForceClearFramebufferWithDefaultValues(bool fakeNoAlpha, GLbitfield mask,
const bool colorAttachmentsMask[kMaxColorAttachments])
{
MakeContextCurrent();
const bool initializeColorBuffer = bool(clearBits & LOCAL_GL_COLOR_BUFFER_BIT);
const bool initializeDepthBuffer = bool(clearBits & LOCAL_GL_DEPTH_BUFFER_BIT);
const bool initializeStencilBuffer = bool(clearBits & LOCAL_GL_STENCIL_BUFFER_BIT);
bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
bool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
bool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
bool drawBuffersIsEnabled = IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
bool shouldOverrideDrawBuffers = false;
bool usingDefaultFrameBuffer = !mBoundDrawFramebuffer;
GLenum currentDrawBuffers[WebGLContext::kMaxColorAttachments];
// Fun GL fact: No need to worry about the viewport here, glViewport is just
// setting up a coordinates transformation, it doesn't affect glClear at all.
@ -1318,6 +1339,38 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
if (initializeColorBuffer) {
if (drawBuffersIsEnabled) {
GLenum drawBuffersCommand[WebGLContext::kMaxColorAttachments] = { LOCAL_GL_NONE };
for (int32_t i = 0; i < mGLMaxDrawBuffers; i++) {
GLint temp;
gl->fGetIntegerv(LOCAL_GL_DRAW_BUFFER0 + i, &temp);
currentDrawBuffers[i] = temp;
if (colorAttachmentsMask[i]) {
drawBuffersCommand[i] = LOCAL_GL_COLOR_ATTACHMENT0 + i;
}
if (currentDrawBuffers[i] != drawBuffersCommand[i])
shouldOverrideDrawBuffers = true;
}
// When clearing the default framebuffer, we must be clearing only
// GL_BACK, and nothing else, or else gl may return an error. We will
// only use the first element of currentDrawBuffers in this case.
if (usingDefaultFrameBuffer) {
gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK);
if (currentDrawBuffers[0] == LOCAL_GL_COLOR_ATTACHMENT0)
currentDrawBuffers[0] = LOCAL_GL_BACK;
shouldOverrideDrawBuffers = false;
}
// calling draw buffers can cause resolves on adreno drivers so
// we try to avoid calling it
if (shouldOverrideDrawBuffers)
gl->fDrawBuffers(mGLMaxDrawBuffers, drawBuffersCommand);
}
gl->fColorMask(1, 1, 1, 1);
if (fakeNoAlpha) {
@ -1345,7 +1398,7 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
}
// Do the clear!
gl->fClear(clearBits);
gl->fClear(mask);
// And reset!
if (mScissorTestEnabled)
@ -1357,6 +1410,15 @@ WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield clearBits,
// Restore GL state after clearing.
if (initializeColorBuffer) {
if (drawBuffersIsEnabled) {
if (usingDefaultFrameBuffer) {
gl->Screen()->SetDrawBuffer(currentDrawBuffers[0]);
} else if (shouldOverrideDrawBuffers) {
gl->fDrawBuffers(mGLMaxDrawBuffers, currentDrawBuffers);
}
}
gl->fColorMask(mColorWriteMask[0],
mColorWriteMask[1],
mColorWriteMask[2],
@ -1756,30 +1818,17 @@ WebGLContext::DidRefresh()
}
}
bool
WebGLContext::ValidateCurFBForRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height)
size_t
RoundUpToMultipleOf(size_t value, size_t multiple)
{
if (!mBoundReadFramebuffer) {
ClearBackbufferIfNeeded();
size_t overshoot = value + multiple - 1;
return overshoot - (overshoot % multiple);
}
// FIXME - here we're assuming that the default framebuffer is backed by
// UNSIGNED_BYTE that might not always be true, say if we had a 16bpp default
// framebuffer.
auto effFormat = mOptions.alpha ? webgl::EffectiveFormat::RGBA8
: webgl::EffectiveFormat::RGB8;
*out_format = mFormatUsage->GetUsage(effFormat);
MOZ_ASSERT(*out_format);
*out_width = mWidth;
*out_height = mHeight;
return true;
}
return mBoundReadFramebuffer->ValidateForRead(funcName, out_format, out_width,
out_height);
CheckedUint32
RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y)
{
return ((x + y - 1) / y) * y;
}
////////////////////////////////////////////////////////////////////////////////
@ -1820,215 +1869,6 @@ WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
}
}
////////////////////////////////////////
ScopedUnpackReset::ScopedUnpackReset(WebGLContext* webgl)
: ScopedGLWrapper<ScopedUnpackReset>(webgl->gl)
, mWebGL(webgl)
{
if (mWebGL->mPixelStore_UnpackAlignment != 4) mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
if (mWebGL->IsWebGL2()) {
if (mWebGL->mPixelStore_UnpackRowLength != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , 0);
if (mWebGL->mPixelStore_UnpackImageHeight != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0);
if (mWebGL->mPixelStore_UnpackSkipPixels != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , 0);
if (mWebGL->mPixelStore_UnpackSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , 0);
if (mWebGL->mPixelStore_UnpackSkipImages != 0) mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , 0);
if (mWebGL->mBoundPixelUnpackBuffer) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
}
}
void
ScopedUnpackReset::UnwrapImpl()
{
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mWebGL->mPixelStore_UnpackAlignment);
if (mWebGL->IsWebGL2()) {
mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH , mWebGL->mPixelStore_UnpackRowLength );
mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mWebGL->mPixelStore_UnpackImageHeight);
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS , mWebGL->mPixelStore_UnpackSkipPixels );
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS , mWebGL->mPixelStore_UnpackSkipRows );
mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES , mWebGL->mPixelStore_UnpackSkipImages );
GLuint pbo = 0;
if (mWebGL->mBoundPixelUnpackBuffer) {
pbo = mWebGL->mBoundPixelUnpackBuffer->mGLName;
}
mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, pbo);
}
}
////////////////////////////////////////
void
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
uint32_t* const out_intSize)
{
// Only >0 if dstStartInSrc is >0:
// 0 3 // src coords
// | [========] // dst box
// ^--^
*out_intStartInSrc = std::max<int32_t>(0, dstStartInSrc);
// Only >0 if dstStartInSrc is <0:
//-6 0 // src coords
// [=====|==] // dst box
// ^-----^
*out_intStartInDst = std::max<int32_t>(0, 0 - dstStartInSrc);
int32_t intEndInSrc = std::min<int32_t>(srcSize, dstStartInSrc + dstSize);
*out_intSize = std::max<int32_t>(0, intEndInSrc - *out_intStartInSrc);
}
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth)
{
// This has two usecases:
// 1. Lazy zeroing of uninitialized textures:
// a. Before draw, when FakeBlack isn't viable. (TexStorage + Draw*)
// b. Before partial upload. (TexStorage + TexSubImage)
// 2. Zero subrects from out-of-bounds blits. (CopyTex(Sub)Image)
// We have no sympathy for any of these cases.
// "Doctor, it hurts when I do this!" "Well don't do that!"
webgl->GenerateWarning("%s: This operation requires zeroing texture data. This is"
" slow.",
funcName);
gl::GLContext* gl = webgl->GL();
gl->MakeCurrent();
ScopedUnpackReset scopedReset(webgl);
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); // Don't bother with striding it well.
auto compression = usage->format->compression;
if (compression) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
MOZ_RELEASE_ASSERT(!respecifyTexture);
auto sizedFormat = usage->format->sizedFormat;
MOZ_RELEASE_ASSERT(sizedFormat);
const auto fnSizeInBlocks = [](CheckedUint32 pixels, uint8_t pixelsPerBlock) {
return RoundUpToMultipleOf(pixels, pixelsPerBlock) / pixelsPerBlock;
};
const auto widthBlocks = fnSizeInBlocks(width, compression->blockWidth);
const auto heightBlocks = fnSizeInBlocks(height, compression->blockHeight);
CheckedUint32 checkedByteCount = compression->bytesPerBlock;
checkedByteCount *= widthBlocks;
checkedByteCount *= heightBlocks;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
GLenum error = DoCompressedTexSubImage(gl, target.get(), level, xOffset, yOffset,
zOffset, width, height, depth, sizedFormat,
byteCount, zeros.get());
if (error)
return false;
return true;
}
const auto driverUnpackInfo = usage->idealUnpack;
MOZ_RELEASE_ASSERT(driverUnpackInfo);
const webgl::PackingInfo packing = driverUnpackInfo->ToPacking();
const auto bytesPerPixel = webgl::BytesPerPixel(packing);
CheckedUint32 checkedByteCount = bytesPerPixel;
checkedByteCount *= width;
checkedByteCount *= height;
checkedByteCount *= depth;
if (!checkedByteCount.isValid())
return false;
const size_t byteCount = checkedByteCount.value();
UniqueBuffer zeros = calloc(1, byteCount);
if (!zeros)
return false;
GLenum error;
if (respecifyTexture) {
MOZ_RELEASE_ASSERT(!xOffset && !yOffset && !zOffset);
error = DoTexImage(gl, target, level, driverUnpackInfo, width, height, depth,
zeros.get());
} else {
error = DoTexSubImage(gl, target, level, xOffset, yOffset, zOffset, width, height,
depth, packing, zeros.get());
}
if (error)
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
CheckedUint32
WebGLContext::GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
uint32_t depth, uint8_t bytesPerPixel)
{
if (!width || !height || !depth)
return 0;
////////////////
const auto& maybeRowLength = mPixelStore_UnpackRowLength;
const auto& maybeImageHeight = mPixelStore_UnpackImageHeight;
const auto usedPixelsPerRow = CheckedUint32(mPixelStore_UnpackSkipPixels) + width;
const auto stridePixelsPerRow = (maybeRowLength ? CheckedUint32(maybeRowLength)
: usedPixelsPerRow);
const auto usedRowsPerImage = CheckedUint32(mPixelStore_UnpackSkipRows) + height;
const auto strideRowsPerImage = (maybeImageHeight ? CheckedUint32(maybeImageHeight)
: usedRowsPerImage);
const uint32_t skipImages = (isFunc3D ? mPixelStore_UnpackSkipImages
: 0);
const CheckedUint32 usedImages = CheckedUint32(skipImages) + depth;
////////////////
CheckedUint32 strideBytesPerRow = bytesPerPixel * stridePixelsPerRow;
strideBytesPerRow = RoundUpToMultipleOf(strideBytesPerRow,
mPixelStore_UnpackAlignment);
const CheckedUint32 strideBytesPerImage = strideBytesPerRow * strideRowsPerImage;
////////////////
CheckedUint32 usedBytesPerRow = bytesPerPixel * usedPixelsPerRow;
// Don't round this to the alignment, since alignment here is really just used for
// establishing stride, particularly in WebGL 1, where you can't set ROW_LENGTH.
CheckedUint32 totalBytes = strideBytesPerImage * (usedImages - 1);
totalBytes += strideBytesPerRow * (usedRowsPerImage - 1);
totalBytes += usedBytesPerRow;
return totalBytes;
}
////////////////////////////////////////////////////////////////////////////////
// XPCOM goop
@ -2042,7 +1882,6 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mBound2DTextures,
mBoundCubeMapTextures,
mBound3DTextures,
mBound2DArrayTextures,
mBoundSamplers,
mBoundArrayBuffer,
mBoundCopyReadBuffer,

View File

@ -26,8 +26,6 @@
#include "nsTArray.h"
#include "nsWrapperCache.h"
#include "SurfaceTypes.h"
#include "ScopedGLHelpers.h"
#include "TexUnpackBlob.h"
#ifdef XP_MACOSX
#include "ForceDiscreteGPUHelperCGL.h"
@ -38,7 +36,6 @@
#include "WebGLFormats.h"
#include "WebGLObjectModel.h"
#include "WebGLStrongTypes.h"
#include "WebGLTexture.h"
// Generated
#include "nsIDOMEventListener.h"
@ -70,12 +67,6 @@ class nsIDocShell;
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
/*
* Minimum value constants define in 6.2 State Tables of OpenGL ES - 3.0.4
*/
#define MINVALUE_GL_MAX_3D_TEXTURE_SIZE 256
#define MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS 256
/*
* WebGL-only GLenums
*/
@ -87,9 +78,7 @@ class nsIDocShell;
#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
namespace mozilla {
class ScopedCopyTexImageSource;
class ScopedResolveTexturesForDraw;
class ScopedUnpackReset;
class WebGLActiveInfo;
class WebGLContextLossHandler;
class WebGLBuffer;
@ -122,7 +111,6 @@ class SourceSurface;
namespace webgl {
struct LinkedProgramInfo;
class ShaderValidator;
class TexUnpackBlob;
} // namespace webgl
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
@ -212,9 +200,6 @@ class WebGLContext
UNMASKED_RENDERER_WEBGL = 0x9246
};
static const uint32_t kMinMaxColorAttachments;
static const uint32_t kMinMaxDrawBuffers;
public:
WebGLContext();
@ -315,8 +300,6 @@ public:
return mBoundCubeMapTextures[mActiveTexture];
case LOCAL_GL_TEXTURE_3D:
return mBound3DTextures[mActiveTexture];
case LOCAL_GL_TEXTURE_2D_ARRAY:
return mBound2DArrayTextures[mActiveTexture];
default:
MOZ_CRASH("bad target");
}
@ -357,11 +340,18 @@ public:
// all context resources to be lost.
uint32_t Generation() { return mGeneration.value(); }
// Returns null if the current bound FB is not likely complete.
const WebGLRectangleObject* CurValidDrawFBRectObject() const;
const WebGLRectangleObject* CurValidReadFBRectObject() const;
static const size_t kMaxColorAttachments = 16;
// This is similar to GLContext::ClearSafely, but tries to minimize the
// amount of work it does.
// It only clears the buffers we specify, and can reset its state without
// first having to query anything, as WebGL knows its state at all times.
void ForceClearFramebufferWithDefaultValues(GLbitfield bufferBits, bool fakeNoAlpha);
void ForceClearFramebufferWithDefaultValues(bool fakeNoAlpha, GLbitfield mask,
const bool colorAttachmentsMask[kMaxColorAttachments]);
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
void ClearScreen();
@ -444,9 +434,8 @@ public:
GLint level);
// Framebuffer validation
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
const char* funcName,
bool badColorAttachmentIsInvalidOp = false);
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb,
GLenum attachment, const char* funcName);
void FrontFace(GLenum mode);
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
@ -538,11 +527,6 @@ public:
void LinkProgram(WebGLProgram* prog);
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
protected:
bool DoReadPixelsAndConvert(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum destFormat, GLenum destType, void* destBytes,
GLenum auxReadFormat, GLenum auxReadType);
public:
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& pixels,
@ -905,62 +889,46 @@ public:
GLsizei width, GLsizei height, GLint border, GLenum unpackFormat,
GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult&);
ErrorResult& out_rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult&);
ErrorResult& out_rv);
void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_error);
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::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult&);
ErrorResult& out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult&);
ErrorResult& out_rv);
void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_error);
ErrorResult* const out_rv);
// Allow whatever element unpackTypes the bindings are willing to pass
// us in Tex(Sub)Image2D
template<typename T>
inline void
TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_error)
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_error);
&out_rv);
}
template<typename T>
inline void
TexSubImage2D(GLenum texImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, T& elem, ErrorResult& out_error)
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_error);
&elem, &out_rv);
}
// WebGLTextureUpload.cpp
bool ValidateTexImageSpecification(const char* funcName, uint8_t funcDims,
GLenum texImageTarget, GLint level,
GLsizei width, GLsizei height, GLsizei depth,
GLint border,
TexImageTarget* const out_target,
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
bool ValidateTexImageSelection(const char* funcName, uint8_t funcDims,
GLenum texImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth,
TexImageTarget* const out_target,
WebGLTexture** const out_texture,
WebGLTexture::ImageInfo** const out_imageInfo);
// -----------------------------------------------------------------------------
// Vertices Feature (WebGLContextVertices.cpp)
public:
@ -1043,7 +1011,7 @@ private:
GLsizei primcount, const char* info,
GLuint* out_upperBound);
bool DrawInstanced_check(const char* info);
void Draw_cleanup(const char* funcName);
void Draw_cleanup();
void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
const GLfloat* ptr);
@ -1060,10 +1028,24 @@ private:
// -----------------------------------------------------------------------------
// PROTECTED
protected:
void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) {
mFakeBlackStatus = x;
}
// Returns the current fake-black-status, except if it was Unknown,
// in which case this function resolves it first, so it never returns Unknown.
WebGLContextFakeBlackStatus ResolvedFakeBlackStatus();
void BindFakeBlackTextures();
void UnbindFakeBlackTextures();
WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
bool DoFakeVertexAttrib0(GLuint vertexCount);
void UndoFakeVertexAttrib0();
static CheckedUint32 GetImageSize(GLsizei height, GLsizei width,
GLsizei depth, uint32_t pixelSize,
uint32_t alignment);
inline void InvalidateBufferFetching()
{
mBufferFetchingIsVerified = false;
@ -1094,7 +1076,6 @@ protected:
void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
GLuint mActiveTexture;
GLenum mDefaultFB_DrawBuffer0;
// glGetError sources:
bool mEmitContextLostErrorOnce;
@ -1109,36 +1090,23 @@ protected:
// some GL constants
int32_t mGLMaxVertexAttribs;
int32_t mGLMaxTextureUnits;
int32_t mGLMaxTextureSize;
int32_t mGLMaxTextureSizeLog2;
int32_t mGLMaxCubeMapTextureSize;
int32_t mGLMaxCubeMapTextureSizeLog2;
int32_t mGLMaxRenderbufferSize;
int32_t mGLMaxTextureImageUnits;
int32_t mGLMaxVertexTextureImageUnits;
int32_t mGLMaxVaryingVectors;
int32_t mGLMaxFragmentUniformVectors;
int32_t mGLMaxVertexUniformVectors;
int32_t mGLMaxColorAttachments;
int32_t mGLMaxDrawBuffers;
uint32_t mGLMaxTransformFeedbackSeparateAttribs;
GLuint mGLMaxUniformBufferBindings;
GLsizei mGLMaxSamples;
// What is supported:
uint32_t mGLMaxColorAttachments;
uint32_t mGLMaxDrawBuffers;
// What we're allowing:
uint32_t mImplMaxColorAttachments;
uint32_t mImplMaxDrawBuffers;
public:
GLenum LastColorAttachmentEnum() const {
return LOCAL_GL_COLOR_ATTACHMENT0 + mImplMaxColorAttachments - 1;
}
protected:
// Texture sizes are often not actually the GL values. Let's be explicit that these
// are implementation limits.
uint32_t mImplMaxTextureSize;
uint32_t mImplMaxCubeMapTextureSize;
uint32_t mImplMax3DTextureSize;
uint32_t mImplMaxArrayTextureLayers;
uint32_t mImplMaxRenderbufferSize;
GLuint mGLMax3DTextureSize;
GLuint mGLMaxArrayTextureLayers;
public:
GLuint MaxVertexAttribs() const {
@ -1149,7 +1117,8 @@ public:
return mGLMaxTextureUnits;
}
bool IsFormatValidForFB(TexInternalFormat format) const;
bool IsFormatValidForFB(GLenum sizedFormat) const;
protected:
// Represents current status of the context with respect to context loss.
@ -1186,11 +1155,9 @@ protected:
WebGLExtensionBase* EnableSupportedExtension(JSContext* js,
WebGLExtensionID ext);
public:
// returns true if the extension has been enabled by calling getExtension.
bool IsExtensionEnabled(WebGLExtensionID ext) const;
protected:
// returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes)
bool IsExtensionSupported(JSContext* cx, WebGLExtensionID ext) const;
bool IsExtensionSupported(WebGLExtensionID ext) const;
@ -1240,8 +1207,8 @@ protected:
WebGLintptr byteOffset, const char* info);
bool ValidateStencilParamsForDrawCall();
bool ValidateCopyTexImage(TexInternalFormat srcFormat, TexInternalFormat dstformat,
WebGLTexImageFunc func, WebGLTexDimensions dims);
bool ValidateCopyTexImage(GLenum internalFormat, WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateSamplerParameterName(GLenum pname, const char* info);
bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info);
@ -1288,10 +1255,6 @@ protected:
WebGLProgram* program,
const char* funcName);
bool ValidateCurFBForRead(const char* funcName,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height);
void Invalidate();
void DestroyResourcesAndContext();
@ -1305,23 +1268,31 @@ protected:
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize);
public:
template<class ElementType>
nsLayoutUtils::SurfaceFromElementResult
SurfaceFromElement(dom::Element* elem)
{
SurfaceFromElement(ElementType* element) {
MOZ_ASSERT(element);
uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE)
if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
if (!mPixelStore_PremultiplyAlpha)
if (!mPixelStorePremultiplyAlpha)
flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
gfx::DrawTarget* idealDrawTarget = nullptr; // Don't care for now.
return nsLayoutUtils::SurfaceFromElement(elem, flags, idealDrawTarget);
return nsLayoutUtils::SurfaceFromElement(element, flags);
}
protected:
template<class ElementType>
nsLayoutUtils::SurfaceFromElementResult
SurfaceFromElement(ElementType& element) {
return SurfaceFromElement(&element);
}
nsresult
SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
RefPtr<gfx::DataSourceSurface>& imageOut,
WebGLTexelFormat* format);
// Returns false if `object` is null or not valid.
template<class ObjectType>
bool ValidateObject(const char* info, ObjectType* object);
@ -1360,22 +1331,30 @@ private:
virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
protected:
int32_t MaxTextureSizeForTarget(TexTarget target) const {
return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize
: mGLMaxCubeMapTextureSize;
}
int32_t
MaxTextureLevelForTexImageTarget(TexImageTarget texImageTarget) const {
const TexTarget target = TexImageTargetToTexTarget(texImageTarget);
return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSizeLog2
: mGLMaxCubeMapTextureSizeLog2;
}
/** Like glBufferData, but if the call may change the buffer size, checks
* any GL error generated by this glBufferData call and returns it.
*/
GLenum CheckedBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
GLenum usage);
public:
void ForceLoseContext(bool simulateLoss = false);
protected:
void ForceRestoreContext();
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DArrayTextures;
nsTArray<WebGLRefPtr<WebGLSampler> > mBoundSamplers;
void ResolveTexturesForDraw() const;
@ -1383,6 +1362,10 @@ protected:
WebGLRefPtr<WebGLProgram> mCurrentProgram;
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
GLenum LastColorAttachment() const {
return LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments - 1;
}
bool ValidateFramebufferTarget(GLenum target, const char* const info);
WebGLRefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
@ -1408,50 +1391,34 @@ protected:
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
// PixelStore parameters
uint32_t mPixelStore_UnpackImageHeight;
uint32_t mPixelStore_UnpackSkipImages;
uint32_t mPixelStore_UnpackRowLength;
uint32_t mPixelStore_UnpackSkipRows;
uint32_t mPixelStore_UnpackSkipPixels;
uint32_t mPixelStore_UnpackAlignment;
uint32_t mPixelStore_PackRowLength;
uint32_t mPixelStore_PackSkipRows;
uint32_t mPixelStore_PackSkipPixels;
uint32_t mPixelStore_PackAlignment;
uint32_t mPixelStorePackAlignment;
uint32_t mPixelStoreUnpackAlignment;
uint32_t mPixelStoreColorspaceConversion;
bool mPixelStoreFlipY;
bool mPixelStorePremultiplyAlpha;
CheckedUint32 GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
uint32_t depth, uint8_t bytesPerPixel);
WebGLContextFakeBlackStatus mFakeBlackStatus;
CheckedUint32 GetPackSize(uint32_t width, uint32_t height, uint8_t bytesPerPixel,
CheckedUint32* const out_startOffset,
CheckedUint32* const out_rowStride);
GLenum mPixelStore_ColorspaceConversion;
bool mPixelStore_FlipY;
bool mPixelStore_PremultiplyAlpha;
////////////////////////////////////
class FakeBlackTexture {
public:
gl::GLContext* const mGL;
const GLuint mGLName;
GLuint mGLName;
FakeBlackTexture(gl::GLContext* gl, TexTarget target, FakeBlackType type);
public:
FakeBlackTexture(gl::GLContext* gl, TexTarget target, GLenum format);
~FakeBlackTexture();
GLuint GLName() const { return mGLName; }
};
UniquePtr<FakeBlackTexture> mFakeBlack_2D_0000;
UniquePtr<FakeBlackTexture> mFakeBlack_2D_0001;
UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0000;
UniquePtr<FakeBlackTexture> mFakeBlack_CubeMap_0001;
UniquePtr<FakeBlackTexture> mFakeBlack_3D_0000;
UniquePtr<FakeBlackTexture> mFakeBlack_3D_0001;
UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0000;
UniquePtr<FakeBlackTexture> mFakeBlack_2D_Array_0001;
UniquePtr<FakeBlackTexture> mBlackOpaqueTexture2D;
UniquePtr<FakeBlackTexture> mBlackOpaqueTextureCubeMap;
UniquePtr<FakeBlackTexture> mBlackTransparentTexture2D;
UniquePtr<FakeBlackTexture> mBlackTransparentTextureCubeMap;
void BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack);
////////////////////////////////////
void
BindFakeBlackTexturesHelper(GLenum target,
const nsTArray<WebGLRefPtr<WebGLTexture> >& boundTexturesArray,
UniquePtr<FakeBlackTexture>& opaqueTextureScopedPtr,
UniquePtr<FakeBlackTexture>& transparentTextureScopedPtr);
// Generic Vertex Attributes
UniquePtr<GLenum[]> mVertexAttribType;
@ -1567,19 +1534,10 @@ public:
public:
UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const = 0;
virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const = 0;
// Friend list
friend class ScopedCopyTexImageSource;
friend class ScopedResolveTexturesForDraw;
friend class ScopedUnpackReset;
friend class webgl::TexUnpackBlob;
friend class webgl::TexUnpackBytes;
friend class webgl::TexUnpackSurface;
friend class WebGLTexture;
friend class WebGLFBAttachPoint;
friend class WebGLFramebuffer;
friend class WebGLRenderbuffer;
friend class WebGLProgram;
@ -1673,99 +1631,24 @@ WebGLContext::ValidateObject(const char* info, ObjectType* object)
return ValidateObjectAssumeNonNull(info, object);
}
// Returns `value` rounded to the next highest multiple of `multiple`.
// AKA PadToAlignment, StrideForAlignment.
template<typename V, typename M>
V
RoundUpToMultipleOf(const V& value, const M& multiple)
{
return ((value + multiple - 1) / multiple) * multiple;
}
size_t RoundUpToMultipleOf(size_t value, size_t multiple);
bool
ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
GLenum rawTexTarget, TexTarget* const out_texTarget,
WebGLTexture** const out_tex);
ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
TexTarget* const out_texTarget, WebGLTexture** const out_tex);
bool
ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
const char* funcName, TexImageTarget* const out_texImageTarget,
WebGLTexture** const out_tex);
class UniqueBuffer
{
// Like UniquePtr<>, but for void* and malloc/calloc/free.
void* mBuffer;
public:
UniqueBuffer()
: mBuffer(nullptr)
{ }
MOZ_IMPLICIT UniqueBuffer(void* buffer)
: mBuffer(buffer)
{ }
~UniqueBuffer() {
free(mBuffer);
}
UniqueBuffer(UniqueBuffer&& other) {
this->mBuffer = other.mBuffer;
other.mBuffer = nullptr;
}
UniqueBuffer& operator =(UniqueBuffer&& other) {
free(this->mBuffer);
this->mBuffer = other.mBuffer;
other.mBuffer = nullptr;
return *this;
}
UniqueBuffer& operator =(void* newBuffer) {
free(this->mBuffer);
this->mBuffer = newBuffer;
return *this;
}
explicit operator bool() const { return bool(mBuffer); }
void* get() const { return mBuffer; }
UniqueBuffer(const UniqueBuffer& other) = delete; // construct using Move()!
void operator =(const UniqueBuffer& other) = delete; // assign using Move()!
};
class ScopedUnpackReset
: public gl::ScopedGLWrapper<ScopedUnpackReset>
{
friend struct gl::ScopedGLWrapper<ScopedUnpackReset>;
protected:
WebGLContext* const mWebGL;
public:
explicit ScopedUnpackReset(WebGLContext* webgl);
protected:
void UnwrapImpl();
};
// Returns x rounded to the next highest multiple of y.
CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y);
void
ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
void** const out_data, size_t* const out_length,
js::Scalar::Type* const out_type);
void
Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
uint32_t* const out_intSize);
bool
ZeroTextureData(WebGLContext* webgl, const char* funcName, bool respecifyTexture,
TexImageTarget target, uint32_t level,
const webgl::FormatUsageInfo* usage, uint32_t xOffset, uint32_t yOffset,
uint32_t zOffset, uint32_t width, uint32_t height, uint32_t depth);
} // namespace mozilla
#endif

View File

@ -23,134 +23,13 @@ namespace mozilla {
// For a Tegra workaround.
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
////////////////////////////////////////
class ScopedResolveTexturesForDraw
{
struct TexRebindRequest
{
uint32_t texUnit;
WebGLTexture* tex;
};
WebGLContext* const mWebGL;
std::vector<TexRebindRequest> mRebindRequests;
public:
ScopedResolveTexturesForDraw(WebGLContext* webgl, const char* funcName,
bool* const out_error);
~ScopedResolveTexturesForDraw();
};
ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
const char* funcName,
bool* const out_error)
: mWebGL(webgl)
{
//typedef nsTArray<WebGLRefPtr<WebGLTexture>> TexturesT;
typedef decltype(WebGLContext::mBound2DTextures) TexturesT;
const auto fnResolveAll = [this, funcName, out_error](const TexturesT& textures)
{
const auto len = textures.Length();
for (uint32_t texUnit = 0; texUnit < len; ++texUnit) {
WebGLTexture* tex = textures[texUnit];
if (!tex)
continue;
FakeBlackType fakeBlack;
*out_error |= !tex->ResolveForDraw(funcName, texUnit, &fakeBlack);
if (fakeBlack == FakeBlackType::None)
continue;
mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack);
mRebindRequests.push_back({texUnit, tex});
}
};
*out_error = false;
fnResolveAll(mWebGL->mBound2DTextures);
fnResolveAll(mWebGL->mBoundCubeMapTextures);
fnResolveAll(mWebGL->mBound3DTextures);
fnResolveAll(mWebGL->mBound2DArrayTextures);
if (*out_error) {
mWebGL->ErrorOutOfMemory("%s: Failed to resolve textures for draw.", funcName);
}
}
ScopedResolveTexturesForDraw::~ScopedResolveTexturesForDraw()
{
if (!mRebindRequests.size())
return;
gl::GLContext* gl = mWebGL->gl;
for (const auto& itr : mRebindRequests) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + itr.texUnit);
gl->fBindTexture(itr.tex->Target().get(), itr.tex->mGLName);
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mWebGL->mActiveTexture);
}
void
WebGLContext::BindFakeBlack(uint32_t texUnit, TexTarget target, FakeBlackType fakeBlack)
{
MOZ_ASSERT(fakeBlack == FakeBlackType::RGBA0000 ||
fakeBlack == FakeBlackType::RGBA0001);
const auto fnGetSlot = [this, target, fakeBlack]() -> UniquePtr<FakeBlackTexture>*
{
switch (fakeBlack) {
case FakeBlackType::RGBA0000:
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D : return &mFakeBlack_2D_0000;
case LOCAL_GL_TEXTURE_CUBE_MAP: return &mFakeBlack_CubeMap_0000;
case LOCAL_GL_TEXTURE_3D : return &mFakeBlack_3D_0000;
case LOCAL_GL_TEXTURE_2D_ARRAY: return &mFakeBlack_2D_Array_0000;
default: return nullptr;
}
case FakeBlackType::RGBA0001:
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D : return &mFakeBlack_2D_0001;
case LOCAL_GL_TEXTURE_CUBE_MAP: return &mFakeBlack_CubeMap_0001;
case LOCAL_GL_TEXTURE_3D : return &mFakeBlack_3D_0001;
case LOCAL_GL_TEXTURE_2D_ARRAY: return &mFakeBlack_2D_Array_0001;
default: return nullptr;
}
default:
return nullptr;
}
};
UniquePtr<FakeBlackTexture>* slot = fnGetSlot();
if (!slot) {
MOZ_CRASH("fnGetSlot failed.");
}
UniquePtr<FakeBlackTexture>& fakeBlackTex = *slot;
if (!fakeBlackTex) {
fakeBlackTex.reset(new FakeBlackTexture(gl, target, fakeBlack));
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + texUnit);
gl->fBindTexture(target.get(), fakeBlackTex->mGLName);
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
}
////////////////////////////////////////
bool
WebGLContext::DrawInstanced_check(const char* info)
{
MOZ_ASSERT(IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays));
if (!mBufferFetchingHasPerVertex) {
if ((IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays)) &&
!mBufferFetchingHasPerVertex)
{
/* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
* If all of the enabled vertex attribute arrays that are bound to active
* generic attributes in the program have a non-zero divisor, the draw
@ -232,25 +111,25 @@ WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
return false;
}
if (!DrawInstanced_check(info)) {
return false;
}
BindFakeBlackTextures();
return true;
}
void
WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
{
const char funcName[] = "drawArrays";
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, funcName))
if (!ValidateDrawModeEnum(mode, "drawArrays: mode"))
return;
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
if (!DrawArrays_check(first, count, 1, funcName))
if (!DrawArrays_check(first, count, 1, "drawArrays"))
return;
RunContextLossTimer();
@ -260,28 +139,19 @@ WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
gl->fDrawArrays(mode, first, count);
}
Draw_cleanup(funcName);
Draw_cleanup();
}
void
WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
{
const char funcName[] = "drawArraysInstanced";
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, funcName))
if (!ValidateDrawModeEnum(mode, "drawArraysInstanced: mode"))
return;
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
return;
if (!DrawArrays_check(first, count, primcount, funcName))
return;
if (!DrawInstanced_check(funcName))
if (!DrawArrays_check(first, count, primcount, "drawArraysInstanced"))
return;
RunContextLossTimer();
@ -291,7 +161,7 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
gl->fDrawArraysInstanced(mode, first, count, primcount);
}
Draw_cleanup(funcName);
Draw_cleanup();
}
bool
@ -314,40 +184,39 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
}
// If count is 0, there's nothing to do.
if (count == 0 || primcount == 0)
if (count == 0 || primcount == 0) {
return false;
}
uint8_t bytesPerElem = 0;
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
bytesPerElem = 1;
break;
CheckedUint32 checked_byteCount;
case LOCAL_GL_UNSIGNED_SHORT:
bytesPerElem = 2;
break;
GLsizei first = 0;
case LOCAL_GL_UNSIGNED_INT:
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) {
bytesPerElem = 4;
if (type == LOCAL_GL_UNSIGNED_SHORT) {
checked_byteCount = 2 * CheckedUint32(count);
if (byteOffset % 2 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_SHORT (must be a multiple of 2)", info);
return false;
}
break;
first = byteOffset / 2;
}
if (!bytesPerElem) {
ErrorInvalidEnum("%s: Invalid `type`: 0x%04x", info, type);
else if (type == LOCAL_GL_UNSIGNED_BYTE) {
checked_byteCount = count;
first = byteOffset;
}
else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) {
checked_byteCount = 4 * CheckedUint32(count);
if (byteOffset % 4 != 0) {
ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)", info);
return false;
}
first = byteOffset / 4;
}
else {
ErrorInvalidEnum("%s: type must be UNSIGNED_SHORT or UNSIGNED_BYTE", info);
return false;
}
if (byteOffset % bytesPerElem != 0) {
ErrorInvalidOperation("%s: `byteOffset` must be a multiple of the size of `type`",
info);
return false;
}
const GLsizei first = byteOffset / bytesPerElem;
const CheckedUint32 checked_byteCount = bytesPerElem * CheckedUint32(count);
if (!checked_byteCount.isValid()) {
ErrorInvalidValue("%s: overflow in byteCount", info);
return false;
@ -423,6 +292,12 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
return false;
}
if (!DrawInstanced_check(info)) {
return false;
}
BindFakeBlackTextures();
return true;
}
@ -430,21 +305,18 @@ void
WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset)
{
const char funcName[] = "drawElements";
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, funcName))
return;
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
return;
GLuint upperBound = 0;
if (!DrawElements_check(count, type, byteOffset, 1, funcName, &upperBound))
if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
&upperBound))
{
return;
}
RunContextLossTimer();
@ -460,31 +332,25 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
}
}
Draw_cleanup(funcName);
Draw_cleanup();
}
void
WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
WebGLintptr byteOffset, GLsizei primcount)
{
const char funcName[] = "drawElementsInstanced";
if (IsContextLost())
return;
if (!ValidateDrawModeEnum(mode, funcName))
return;
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
if (!ValidateDrawModeEnum(mode, "drawElementsInstanced: mode"))
return;
GLuint upperBound = 0;
if (!DrawElements_check(count, type, byteOffset, primcount, funcName, &upperBound))
return;
if (!DrawInstanced_check(funcName))
if (!DrawElements_check(count, type, byteOffset, primcount,
"drawElementsInstanced", &upperBound))
{
return;
}
RunContextLossTimer();
@ -495,12 +361,13 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
primcount);
}
Draw_cleanup(funcName);
Draw_cleanup();
}
void WebGLContext::Draw_cleanup(const char* funcName)
void WebGLContext::Draw_cleanup()
{
UndoFakeVertexAttrib0();
UnbindFakeBlackTextures();
if (!mBoundDrawFramebuffer) {
Invalidate();
@ -519,29 +386,17 @@ void WebGLContext::Draw_cleanup(const char* funcName)
}
}
// Let's check for a really common error: Viewport is larger than the actual
// destination framebuffer.
uint32_t destWidth = mViewportWidth;
uint32_t destHeight = mViewportHeight;
if (mBoundDrawFramebuffer) {
const auto& fba = mBoundDrawFramebuffer->ColorAttachment(0);
if (fba.IsDefined()) {
fba.Size(&destWidth, &destHeight);
}
} else {
destWidth = mWidth;
destHeight = mHeight;
}
if (mViewportWidth > int32_t(destWidth) ||
mViewportHeight > int32_t(destHeight))
{
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
GenerateWarning("%s: Drawing to a destination rect smaller than the viewport"
" rect. (This warning will only be given once)",
funcName);
mAlreadyWarnedAboutViewportLargerThanDest = true;
// Let's check the viewport
const WebGLRectangleObject* rect = CurValidDrawFBRectObject();
if (rect) {
if (mViewportWidth > rect->Width() ||
mViewportHeight > rect->Height())
{
if (!mAlreadyWarnedAboutViewportLargerThanDest) {
GenerateWarning("Drawing to a destination rect smaller than the viewport rect. "
"(This warning will only be given once)");
mAlreadyWarnedAboutViewportLargerThanDest = true;
}
}
}
}
@ -791,67 +646,145 @@ WebGLContext::UndoFakeVertexAttrib0()
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->mGLName : 0);
}
static GLuint
CreateGLTexture(gl::GLContext* gl)
WebGLContextFakeBlackStatus
WebGLContext::ResolvedFakeBlackStatus()
{
MOZ_ASSERT(gl->IsCurrent());
GLuint ret = 0;
gl->fGenTextures(1, &ret);
return ret;
// handle this case first, it's the generic case
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
return mFakeBlackStatus;
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
return mFakeBlackStatus;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
{
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
return mFakeBlackStatus;
}
}
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
// that means that we do NOT need it.
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
return mFakeBlackStatus;
}
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target,
FakeBlackType type)
: mGL(gl)
, mGLName(CreateGLTexture(gl))
void
WebGLContext::BindFakeBlackTexturesHelper(
GLenum target,
const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
UniquePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
UniquePtr<FakeBlackTexture> & transparentTextureScopedPtr)
{
GLenum texFormat;
switch (type) {
case FakeBlackType::RGBA0000:
texFormat = LOCAL_GL_RGBA;
break;
case FakeBlackType::RGBA0001:
texFormat = LOCAL_GL_RGB;
break;
default:
MOZ_CRASH("bad type");
}
gl::ScopedBindTexture scopedBind(mGL, mGLName, target.get());
mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
mGL->fTexParameteri(target.get(), LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
// We allocate our zeros on the heap, and we overallocate (16 bytes instead of 4) to
// minimize the risk of running into a driver bug in texImage2D, as it is a bit
// unusual maybe to create 1x1 textures, and the stack may not have the alignment that
// TexImage2D expects.
const webgl::DriverUnpackInfo dui = {texFormat, texFormat, LOCAL_GL_UNSIGNED_BYTE};
UniqueBuffer zeros = moz_xcalloc(1, 16); // Infallible allocation.
if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
for (int i = 0; i < 6; ++i) {
const TexImageTarget curTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
const GLenum error = DoTexImage(mGL, curTarget.get(), 0, &dui, 1, 1, 1,
zeros.get());
if (error)
MOZ_CRASH("Unexpected error during FakeBlack creation.");
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (!boundTexturesArray[i]) {
continue;
}
} else {
const GLenum error = DoTexImage(mGL, target.get(), 0, &dui, 1, 1, 1,
zeros.get());
if (error)
MOZ_CRASH("Unexpected error during FakeBlack creation.");
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
continue;
}
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().EffectiveInternalFormat());
UniquePtr<FakeBlackTexture>&
blackTexturePtr = alpha
? transparentTextureScopedPtr
: opaqueTextureScopedPtr;
if (!blackTexturePtr) {
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
blackTexturePtr = MakeUnique<FakeBlackTexture>(gl, target, format);
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(target,
blackTexturePtr->GLName());
}
}
void
WebGLContext::BindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
mBound2DTextures,
mBlackOpaqueTexture2D,
mBlackTransparentTexture2D);
BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
mBoundCubeMapTextures,
mBlackOpaqueTextureCubeMap,
mBlackTransparentTextureCubeMap);
}
void
WebGLContext::UnbindFakeBlackTextures()
{
// this is the generic case: try to return early
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
return;
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->mGLName);
}
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->mGLName);
}
}
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
}
WebGLContext::FakeBlackTexture::FakeBlackTexture(gl::GLContext* gl, TexTarget target, GLenum format)
: mGL(gl)
, mGLName(0)
{
MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
mGL->MakeCurrent();
GLuint formerBinding = 0;
gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
? LOCAL_GL_TEXTURE_BINDING_2D
: LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
&formerBinding);
gl->fGenTextures(1, &mGLName);
gl->fBindTexture(target.get(), mGLName);
// we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
// to minimize the risk of running into a driver bug in texImage2D, as it is
// a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
// that texImage2D expects.
UniquePtr<uint8_t> zeros((uint8_t*)moz_xcalloc(1, 16));
if (target == LOCAL_GL_TEXTURE_2D) {
gl->fTexImage2D(target.get(), 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros.get());
} else {
for (GLuint i = 0; i < 6; ++i) {
gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
0, format, LOCAL_GL_UNSIGNED_BYTE, zeros.get());
}
}
gl->fBindTexture(target.get(), formerBinding);
}
WebGLContext::FakeBlackTexture::~FakeBlackTexture()
{
mGL->MakeCurrent();
mGL->fDeleteTextures(1, &mGLName);
if (mGL) {
mGL->MakeCurrent();
mGL->fDeleteTextures(1, &mGLName);
}
}
} // namespace mozilla

View File

@ -106,20 +106,46 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
if (mDisableExtensions)
return false;
// Extensions for both WebGL 1 and 2.
switch (ext) {
// In alphabetical order
switch (ext) {
// ANGLE_
case WebGLExtensionID::ANGLE_instanced_arrays:
return WebGLExtensionInstancedArrays::IsSupported(this);
// EXT_
case WebGLExtensionID::EXT_blend_minmax:
return WebGLExtensionBlendMinMax::IsSupported(this);
case WebGLExtensionID::EXT_color_buffer_half_float:
return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
case WebGLExtensionID::EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
case WebGLExtensionID::EXT_shader_texture_lod:
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
case WebGLExtensionID::EXT_sRGB:
return WebGLExtensionSRGB::IsSupported(this);
case WebGLExtensionID::EXT_texture_filter_anisotropic:
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
// OES_
case WebGLExtensionID::OES_element_index_uint:
return gl->IsSupported(gl::GLFeature::element_index_uint);
case WebGLExtensionID::OES_standard_derivatives:
return gl->IsSupported(gl::GLFeature::standard_derivatives);
case WebGLExtensionID::OES_texture_float:
return gl->IsSupported(gl::GLFeature::texture_float);
case WebGLExtensionID::OES_texture_float_linear:
return gl->IsSupported(gl::GLFeature::texture_float_linear);
case WebGLExtensionID::OES_texture_half_float:
// If we have Feature::texture_half_float, we must not be on ES2
// and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
// right before making the relevant calls.
return gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float) ||
gl->IsSupported(gl::GLFeature::texture_half_float);
case WebGLExtensionID::OES_texture_half_float_linear:
return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
case WebGLExtensionID::OES_vertex_array_object:
return true;
// WEBGL_
case WebGLExtensionID::WEBGL_color_buffer_float:
@ -141,6 +167,15 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
case WebGLExtensionID::WEBGL_debug_renderer_info:
return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
return false;
return gl->IsSupported(gl::GLFeature::depth_texture) ||
gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
case WebGLExtensionID::WEBGL_draw_buffers:
return WebGLExtensionDrawBuffers::IsSupported(this);
case WebGLExtensionID::WEBGL_lose_context:
// We always support this extension.
return true;
@ -150,61 +185,14 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
break;
}
if (!IsWebGL2()) {
// WebGL1-only extensions
if (gfxPrefs::WebGLDraftExtensionsEnabled() || IsWebGL2()) {
switch (ext) {
// ANGLE_
case WebGLExtensionID::ANGLE_instanced_arrays:
return WebGLExtensionInstancedArrays::IsSupported(this);
// EXT_
case WebGLExtensionID::EXT_blend_minmax:
return WebGLExtensionBlendMinMax::IsSupported(this);
case WebGLExtensionID::EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
case WebGLExtensionID::EXT_shader_texture_lod:
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
case WebGLExtensionID::EXT_sRGB:
return WebGLExtensionSRGB::IsSupported(this);
// OES_
case WebGLExtensionID::OES_element_index_uint:
return gl->IsSupported(gl::GLFeature::element_index_uint);
case WebGLExtensionID::OES_standard_derivatives:
return gl->IsSupported(gl::GLFeature::standard_derivatives);
case WebGLExtensionID::OES_texture_float:
return WebGLExtensionTextureFloat::IsSupported(this);
case WebGLExtensionID::OES_texture_half_float:
return WebGLExtensionTextureHalfFloat::IsSupported(this);
case WebGLExtensionID::OES_vertex_array_object:
return true;
// WEBGL_
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
return false;
return gl->IsSupported(gl::GLFeature::depth_texture) ||
gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
case WebGLExtensionID::WEBGL_draw_buffers:
return WebGLExtensionDrawBuffers::IsSupported(this);
case WebGLExtensionID::EXT_disjoint_timer_query:
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
default:
// For warnings-as-errors.
break;
}
if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
switch (ext) {
case WebGLExtensionID::EXT_disjoint_timer_query:
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
default:
// For warnings-as-errors.
break;
}
}
}
return false;

View File

@ -137,80 +137,71 @@ WebGLContext::DepthMask(WebGLboolean b)
void
WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
{
const char funcName[] = "drawBuffers";
if (IsContextLost())
return;
const size_t buffersLength = buffers.Length();
if (!buffersLength) {
return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)");
}
if (!mBoundDrawFramebuffer) {
// GLES 3.0.4 p186:
// "If the GL is bound to the default framebuffer, then `n` must be 1 and the
// constant must be BACK or NONE. [...] If DrawBuffers is supplied with a
// constant other than BACK and NONE, or with a value of `n` other than 1, the
// error INVALID_OPERATION is generated."
if (buffers.Length() != 1) {
ErrorInvalidOperation("%s: For the default framebuffer, `buffers` must have a"
" length of 1.",
funcName);
return;
// OK: we are rendering in the default framebuffer
/* EXT_draw_buffers :
If the GL is bound to the default framebuffer, then <buffersLength> must be 1
and the constant must be BACK or NONE. When draw buffer zero is
BACK, color values are written into the sole buffer for single-
buffered contexts, or into the back buffer for double-buffered
contexts. If DrawBuffersEXT is supplied with a constant other than
BACK and NONE, the error INVALID_OPERATION is generated.
*/
if (buffersLength != 1) {
return ErrorInvalidValue("drawBuffers: invalid <buffers> (main framebuffer: buffers.length must be 1)");
}
switch (buffers[0]) {
case LOCAL_GL_NONE:
case LOCAL_GL_BACK:
break;
default:
ErrorInvalidOperation("%s: For the default framebuffer, `buffers[0]` must be"
" BACK or NONE.",
funcName);
if (buffers[0] == LOCAL_GL_NONE || buffers[0] == LOCAL_GL_BACK) {
gl->Screen()->SetDrawBuffer(buffers[0]);
return;
}
mDefaultFB_DrawBuffer0 = buffers[0];
gl->Screen()->SetDrawBuffer(buffers[0]);
return;
return ErrorInvalidOperation("drawBuffers: invalid operation (main framebuffer: buffers[0] must be GL_NONE or GL_BACK)");
}
// Framebuffer object (not default framebuffer)
// OK: we are rendering in a framebuffer object
if (buffers.Length() > mImplMaxDrawBuffers) {
// "An INVALID_VALUE error is generated if `n` is greater than MAX_DRAW_BUFFERS."
ErrorInvalidValue("%s: `buffers` must have a length <= MAX_DRAW_BUFFERS.",
funcName);
return;
if (buffersLength > size_t(mGLMaxDrawBuffers)) {
/* EXT_draw_buffers :
The maximum number of draw buffers is implementation-dependent. The
number of draw buffers supported can be queried by calling
GetIntegerv with the symbolic constant MAX_DRAW_BUFFERS_EXT. An
INVALID_VALUE error is generated if <buffersLength> is greater than
MAX_DRAW_BUFFERS_EXT.
*/
return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers.length > GL_MAX_DRAW_BUFFERS)");
}
for (size_t i = 0; i < buffers.Length(); i++) {
// "If the GL is bound to a draw framebuffer object, the `i`th buffer listed in
// bufs must be COLOR_ATTACHMENTi or NONE. Specifying a buffer out of order,
// BACK, or COLOR_ATTACHMENTm where `m` is greater than or equal to the value of
// MAX_COLOR_ATTACHMENTS, will generate the error INVALID_OPERATION.
// WEBGL_draw_buffers:
// "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
// equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
// This means that if buffers.Length() isn't larger than MaxDrawBuffers, it won't
// be larger than MaxColorAttachments.
for (uint32_t i = 0; i < buffersLength; i++)
{
/* EXT_draw_buffers :
If the GL is bound to a draw framebuffer object, the <i>th buffer listed
in <bufs> must be COLOR_ATTACHMENT<i>_EXT or NONE. Specifying a
buffer out of order, BACK, or COLOR_ATTACHMENT<m>_EXT where <m> is
greater than or equal to the value of MAX_COLOR_ATTACHMENTS_EXT,
will generate the error INVALID_OPERATION.
*/
/* WEBGL_draw_buffers :
The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter.
*/
if (buffers[i] != LOCAL_GL_NONE &&
buffers[i] != LOCAL_GL_COLOR_ATTACHMENT0 + i)
{
ErrorInvalidOperation("%s: `buffers[i]` must be NONE or COLOR_ATTACHMENTi.",
funcName);
return;
buffers[i] != GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + i)) {
return ErrorInvalidOperation("drawBuffers: invalid operation (buffers[i] must be GL_NONE or GL_COLOR_ATTACHMENTi)");
}
}
MakeContextCurrent();
const GLenum* ptr = nullptr;
if (buffers.Length()) {
ptr = buffers.Elements();
}
gl->fDrawBuffers(buffers.Length(), ptr);
const auto end = ptr + buffers.Length();
mBoundDrawFramebuffer->mDrawBuffers.assign(ptr, end);
gl->fDrawBuffers(buffersLength, buffers.Elements());
}
void

File diff suppressed because it is too large Load Diff

View File

@ -77,9 +77,7 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits)
{
*out_stencilBits = 0;
if (mBoundDrawFramebuffer) {
if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() &&
mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
{
if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
// Error, we don't know which stencil buffer's bits to use
ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
return false;
@ -144,15 +142,15 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
if (pname == LOCAL_GL_MAX_COLOR_ATTACHMENTS) {
return JS::Int32Value(mImplMaxColorAttachments);
return JS::Int32Value(mGLMaxColorAttachments);
} else if (pname == LOCAL_GL_MAX_DRAW_BUFFERS) {
return JS::Int32Value(mImplMaxDrawBuffers);
return JS::Int32Value(mGLMaxDrawBuffers);
} else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mImplMaxDrawBuffers))
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
{
GLint iv = 0;
gl->fGetIntegerv(pname, &iv);
@ -168,7 +166,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
WebGLVertexArray* vao =
(mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
@ -176,7 +174,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) {
if (pname == LOCAL_GL_TIMESTAMP_EXT) {
GLuint64 iv = 0;
gl->fGetInteger64v(pname, (GLint64*) &iv);
@ -237,7 +235,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
@ -382,13 +380,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::Int32Value(i);
}
case LOCAL_GL_MAX_TEXTURE_SIZE:
return JS::Int32Value(mImplMaxTextureSize);
return JS::Int32Value(mGLMaxTextureSize);
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
return JS::Int32Value(mImplMaxCubeMapTextureSize);
return JS::Int32Value(mGLMaxCubeMapTextureSize);
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
return JS::Int32Value(mImplMaxRenderbufferSize);
return JS::Int32Value(mGLMaxRenderbufferSize);
case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
return JS::Int32Value(mGLMaxVertexUniformVectors);
@ -451,13 +449,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
// bool, WebGL-specific
case UNPACK_FLIP_Y_WEBGL:
return JS::BooleanValue(mPixelStore_FlipY);
return JS::BooleanValue(mPixelStoreFlipY);
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
return JS::BooleanValue(mPixelStore_PremultiplyAlpha);
return JS::BooleanValue(mPixelStorePremultiplyAlpha);
// uint, WebGL-specific
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
return JS::NumberValue(uint32_t(mPixelStore_ColorspaceConversion));
return JS::NumberValue(uint32_t(mPixelStoreColorspaceConversion));
////////////////////////////////
// Complex values

View File

@ -52,43 +52,31 @@
namespace mozilla {
static bool
IsValidTexTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexTarget,
TexTarget* const out)
IsValidTexTarget(WebGLContext* webgl, GLenum rawTexTarget, TexTarget* const out)
{
uint8_t targetDims;
switch (rawTexTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP:
targetDims = 2;
break;
case LOCAL_GL_TEXTURE_3D:
case LOCAL_GL_TEXTURE_2D_ARRAY:
if (!webgl->IsWebGL2())
return false;
targetDims = 3;
break;
default:
return false;
}
// Some funcs (like GenerateMipmap) doesn't know the dimension, so don't check it.
if (funcDims && targetDims != funcDims)
return false;
*out = rawTexTarget;
return true;
}
static bool
IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageTarget,
IsValidTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
TexImageTarget* const out)
{
uint8_t targetDims;
switch (rawTexImageTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@ -97,38 +85,31 @@ IsValidTexImageTarget(WebGLContext* webgl, uint8_t funcDims, GLenum rawTexImageT
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
targetDims = 2;
break;
case LOCAL_GL_TEXTURE_3D:
case LOCAL_GL_TEXTURE_2D_ARRAY:
if (!webgl->IsWebGL2())
return false;
targetDims = 3;
break;
default:
return false;
}
if (targetDims != funcDims)
return false;
*out = rawTexImageTarget;
return true;
}
bool
ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
GLenum rawTexTarget, TexTarget* const out_texTarget,
WebGLTexture** const out_tex)
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, funcDims, rawTexTarget, &texTarget)) {
if (!IsValidTexTarget(webgl, rawTexTarget, &texTarget)) {
webgl->ErrorInvalidEnum("%s: Invalid texTarget.", funcName);
return false;
}
@ -145,15 +126,15 @@ ValidateTexTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
}
bool
ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDims,
GLenum rawTexImageTarget, TexImageTarget* const out_texImageTarget,
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, funcDims, rawTexImageTarget, &texImageTarget)) {
if (!IsValidTexImageTarget(webgl, rawTexImageTarget, &texImageTarget)) {
webgl->ErrorInvalidEnum("%s: Invalid texImageTarget.", funcName);
return false;
}
@ -169,7 +150,7 @@ ValidateTexImageTarget(WebGLContext* webgl, const char* funcName, uint8_t funcDi
return true;
}
/*virtual*/ bool
bool
WebGLContext::IsTexParamValid(GLenum pname) const
{
switch (pname) {
@ -203,38 +184,32 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
// 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_2D:
currentTexPtr = &mBound2DTextures[mActiveTexture];
break;
case LOCAL_GL_TEXTURE_CUBE_MAP:
currentTexPtr = &mBoundCubeMapTextures[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");
case LOCAL_GL_TEXTURE_3D:
if (IsWebGL2())
currentTexPtr = &mBound3DTextures[mActiveTexture];
break;
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
if (IsWebGL2())
currentTexPtr = &mBound2DArrayTextures[mActiveTexture];
break;
default:
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
}
if (!currentTexPtr) {
ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
return;
}
const TexTarget texTarget(rawTarget);
MakeContextCurrent();
if (newTex) {
if (!newTex->BindTexture(texTarget))
return;
} else {
if (newTex && !newTex->BindTexture(texTarget))
return;
if (!newTex) {
gl->fBindTexture(texTarget.get(), 0);
}
@ -244,12 +219,9 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
void
WebGLContext::GenerateMipmap(GLenum rawTexTarget)
{
const char funcName[] = "generateMipmap";
const uint8_t funcDims = 0;
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return;
tex->GenerateMipmap(texTarget);
@ -258,12 +230,9 @@ WebGLContext::GenerateMipmap(GLenum rawTexTarget)
JS::Value
WebGLContext::GetTexParameter(GLenum rawTexTarget, GLenum pname)
{
const char funcName[] = "getTexParameter";
const uint8_t funcDims = 0;
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return JS::NullValue();
if (!IsTexParamValid(pname)) {
@ -292,12 +261,9 @@ WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeI
{
MOZ_ASSERT(maybeIntParam || maybeFloatParam);
const char funcName[] = "texParameter";
const uint8_t funcDims = 0;
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, funcName, funcDims, rawTexTarget, &texTarget, &tex))
if (!ValidateTexTarget(this, rawTexTarget, "texParameter", &texTarget, &tex))
return;
tex->TexParameter(texTarget, pname, maybeIntParam, maybeFloatParam);
@ -308,232 +274,140 @@ WebGLContext::TexParameter_base(GLenum rawTexTarget, GLenum pname, GLint* maybeI
// 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::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult&)
ErrorResult& out_rv)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
&tex))
{
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, maybeView);
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&)
dom::ImageData* imageData, ErrorResult& out_rv)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texImage2D", &texImageTarget,
&tex))
{
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, imageData);
tex->TexImage2D(texImageTarget, level, internalFormat, unpackFormat, unpackType,
imageData, &out_rv);
}
//////////////////////////////////////////////////////////////////////////////////////////
// TexSubImage
void
WebGLContext::TexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLenum unpackFormat, GLenum unpackType, dom::Element* elem,
ErrorResult* const out_error)
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_rv)
{
const char funcName[] = "texImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
const bool isSubImage = false;
const GLint xOffset = 0;
const GLint yOffset = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, elem, out_error);
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
elem, out_rv);
}
////////////////////////////////////////
// TexSubImage
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLsizei width, GLsizei height,
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView,
ErrorResult&)
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
const GLsizei depth = 1;
const GLint border = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, width, height, depth, border, unpackFormat,
unpackType, maybeView);
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&)
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset, GLint yOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
if (!ValidateTexImageTarget(this, rawTexImageTarget, "texSubImage2D", &texImageTarget,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, imageData);
tex->TexSubImage2D(texImageTarget, level, xOffset, yOffset, unpackFormat, unpackType,
imageData, &out_rv);
}
void
WebGLContext::TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOffset,
GLint yOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_error)
{
const char funcName[] = "texSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const bool isSubImage = true;
const GLenum internalFormat = 0;
const GLint zOffset = 0;
tex->TexOrSubImage(isSubImage, funcName, target, level, internalFormat, xOffset,
yOffset, zOffset, unpackFormat, unpackType, elem, out_error);
}
////////////////////////////////////////
// CompressedTex(Sub)Image
void
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border,
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const char funcName[] = "compressedTexImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const GLsizei depth = 1;
tex->CompressedTexImage(funcName, target, level, internalFormat, width, height, depth,
border, view);
}
void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum sizedUnpackFormat,
const dom::ArrayBufferViewOrSharedArrayBufferView& view)
{
const char funcName[] = "compressedTexSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
{
return;
}
const GLint zOffset = 0;
const GLsizei depth = 1;
tex->CompressedTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, width,
height, depth, sizedUnpackFormat, view);
}
////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// CopyTex(Sub)Image
void
WebGLContext::CopyTexImage2D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border)
{
const char funcName[] = "copyTexImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexImage2D",
&texImageTarget, &tex))
{
return;
}
tex->CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
tex->CopyTexImage2D(texImageTarget, level, internalFormat, x, y, width, height,
border);
}
void
@ -541,21 +415,55 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xOf
GLint yOffset, GLint x, GLint y, GLsizei width,
GLsizei height)
{
const char funcName[] = "copyTexSubImage2D";
const uint8_t funcDims = 2;
TexImageTarget target;
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, funcName, funcDims, rawTexImageTarget, &target,
&tex))
if (!ValidateTexImageTarget(this, rawTexImageTarget, "copyTexSubImage2D",
&texImageTarget, &tex))
{
return;
}
const GLint zOffset = 0;
tex->CopyTexSubImage2D(texImageTarget, level, xOffset, yOffset, x, y, width, height);
}
tex->CopyTexSubImage(funcName, target, level, xOffset, yOffset, zOffset, x, y, width,
height);
//////////////////////////////////////////////////////////////////////////////////////////
// CompressedTex(Sub)Image
void
WebGLContext::CompressedTexImage2D(GLenum rawTexImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& 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::ArrayBufferViewOrSharedArrayBufferView& 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

View File

@ -27,10 +27,38 @@
namespace mozilla {
bool
IsGLDepthFormat(TexInternalFormat internalformat)
{
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
return unsizedformat == LOCAL_GL_DEPTH_COMPONENT;
}
bool
IsGLDepthStencilFormat(TexInternalFormat internalformat)
{
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
return unsizedformat == LOCAL_GL_DEPTH_STENCIL;
}
bool
FormatHasAlpha(TexInternalFormat internalformat)
{
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
return unsizedformat == LOCAL_GL_RGBA ||
unsizedformat == LOCAL_GL_LUMINANCE_ALPHA ||
unsizedformat == LOCAL_GL_ALPHA ||
unsizedformat == LOCAL_GL_SRGB_ALPHA ||
unsizedformat == LOCAL_GL_RGBA_INTEGER;
}
TexTarget
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
{
switch (texImageTarget.get()) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_3D:
return texImageTarget.get();
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
@ -38,9 +66,10 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return LOCAL_GL_TEXTURE_CUBE_MAP;
default:
return texImageTarget.get();
MOZ_ASSERT(false, "Bad texture target");
// Should be caught by the constructor for TexTarget
return LOCAL_GL_NONE;
}
}
@ -56,6 +85,387 @@ StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
return JS::StringValue(str);
}
GLComponents::GLComponents(TexInternalFormat internalformat)
{
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
mComponents = 0;
switch (unsizedformat.get()) {
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGBA8:
case LOCAL_GL_RGB5_A1:
// Luminance + Alpha can be converted
// to and from RGBA
case LOCAL_GL_LUMINANCE_ALPHA:
mComponents |= Components::Alpha;
// Drops through
case LOCAL_GL_RGB:
case LOCAL_GL_RGB565:
// Luminance can be converted to and from RGB
case LOCAL_GL_LUMINANCE:
mComponents |= Components::Red | Components::Green | Components::Blue;
break;
case LOCAL_GL_ALPHA:
mComponents |= Components::Alpha;
break;
case LOCAL_GL_DEPTH_COMPONENT:
mComponents |= Components::Depth;
break;
case LOCAL_GL_DEPTH_STENCIL:
mComponents |= Components::Stencil;
break;
default:
MOZ_ASSERT(false, "Unhandled case - GLComponents");
break;
}
}
bool
GLComponents::IsSubsetOf(const GLComponents& other) const
{
return (mComponents | other.mComponents) == other.mComponents;
}
TexType
TypeFromInternalFormat(TexInternalFormat internalformat)
{
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
if (internalformat == table_effectiveinternalformat) { \
return table_type; \
}
#include "WebGLInternalFormatsTable.h"
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
return LOCAL_GL_NONE; // no size, no type
}
TexInternalFormat
UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat)
{
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
if (internalformat == table_effectiveinternalformat) { \
return table_internalformat; \
}
#include "WebGLInternalFormatsTable.h"
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
// so we can just return it.
return internalformat;
}
/*
* Note that the following two functions are inverse of each other:
* EffectiveInternalFormatFromInternalFormatAndType and
* InternalFormatAndTypeFromEffectiveInternalFormat both implement OpenGL ES 3.0.3 Table 3.2
* but in opposite directions.
*/
TexInternalFormat
EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
TexType type)
{
MOZ_ASSERT(TypeFromInternalFormat(internalformat) == LOCAL_GL_NONE);
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
if (internalformat == table_internalformat && type == table_type) { \
return table_effectiveinternalformat; \
}
#include "WebGLInternalFormatsTable.h"
// If we're here, that means that type was incompatible with the given internalformat.
return LOCAL_GL_NONE;
}
void
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
TexInternalFormat* const out_internalformat,
TexType* const out_type)
{
MOZ_ASSERT(TypeFromInternalFormat(effectiveinternalformat) != LOCAL_GL_NONE);
MOZ_ASSERT(out_internalformat);
MOZ_ASSERT(out_type);
GLenum internalformat = LOCAL_GL_NONE;
GLenum type = LOCAL_GL_NONE;
switch (effectiveinternalformat.get()) {
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
case table_effectiveinternalformat: \
internalformat = table_internalformat; \
type = table_type; \
break;
#include "WebGLInternalFormatsTable.h"
default:
MOZ_CRASH(); // impossible to get here
}
*out_internalformat = internalformat;
*out_type = type;
}
TexInternalFormat
EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
TexType type)
{
TexType typeOfInternalFormat = TypeFromInternalFormat(internalformat);
if (typeOfInternalFormat == LOCAL_GL_NONE)
return EffectiveInternalFormatFromUnsizedInternalFormatAndType(internalformat, type);
if (typeOfInternalFormat == type)
return internalformat;
return LOCAL_GL_NONE;
}
/**
* Convert effective internalformat into GL function parameters
* valid for underlying driver.
*/
void
DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
TexInternalFormat effectiveinternalformat,
GLenum* const out_driverInternalFormat,
GLenum* const out_driverFormat,
GLenum* const out_driverType)
{
MOZ_ASSERT(out_driverInternalFormat);
MOZ_ASSERT(out_driverFormat);
MOZ_ASSERT(out_driverType);
TexInternalFormat unsizedinternalformat = LOCAL_GL_NONE;
TexType type = LOCAL_GL_NONE;
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(effectiveinternalformat,
&unsizedinternalformat,
&type);
// driverType: almost always the generic type that we just got, except on ES
// we must replace HALF_FLOAT by HALF_FLOAT_OES
GLenum driverType = type.get();
if (gl->IsGLES() && type == LOCAL_GL_HALF_FLOAT)
driverType = LOCAL_GL_HALF_FLOAT_OES;
// driverFormat: always just the unsized internalformat that we just got
GLenum driverFormat = unsizedinternalformat.get();
// driverInternalFormat: almost always the same as driverFormat, but on desktop GL,
// in some cases we must pass a different value. On ES, they are equal by definition
// as it is an error to pass internalformat!=format.
GLenum driverInternalFormat = driverFormat;
if (gl->IsCompatibilityProfile()) {
// Cases where desktop OpenGL requires a tweak to 'format'
if (driverFormat == LOCAL_GL_SRGB)
driverFormat = LOCAL_GL_RGB;
else if (driverFormat == LOCAL_GL_SRGB_ALPHA)
driverFormat = LOCAL_GL_RGBA;
// WebGL2's new formats are not legal values for internalformat,
// as using unsized internalformat is deprecated.
if (driverFormat == LOCAL_GL_RED ||
driverFormat == LOCAL_GL_RG ||
driverFormat == LOCAL_GL_RED_INTEGER ||
driverFormat == LOCAL_GL_RG_INTEGER ||
driverFormat == LOCAL_GL_RGB_INTEGER ||
driverFormat == LOCAL_GL_RGBA_INTEGER)
{
driverInternalFormat = effectiveinternalformat.get();
}
// Cases where desktop OpenGL requires a sized internalformat,
// as opposed to the unsized internalformat that had the same
// GLenum value as 'format', in order to get the precise
// semantics that we want. For example, for floating-point formats,
// we seem to need a sized internalformat to get non-clamped floating
// point texture sampling. Can't find the spec reference for that,
// but that's at least the case on my NVIDIA driver version 331.
if (unsizedinternalformat == LOCAL_GL_DEPTH_COMPONENT ||
unsizedinternalformat == LOCAL_GL_DEPTH_STENCIL ||
type == LOCAL_GL_FLOAT ||
type == LOCAL_GL_HALF_FLOAT)
{
driverInternalFormat = effectiveinternalformat.get();
}
}
// OpenGL core profile removed texture formats ALPHA, LUMINANCE and LUMINANCE_ALPHA
if (gl->IsCoreProfile()) {
switch (driverFormat) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
driverInternalFormat = driverFormat = LOCAL_GL_RED;
break;
case LOCAL_GL_LUMINANCE_ALPHA:
driverInternalFormat = driverFormat = LOCAL_GL_RG;
break;
}
}
*out_driverInternalFormat = driverInternalFormat;
*out_driverFormat = driverFormat;
*out_driverType = driverType;
}
// Map R to A
static const GLenum kLegacyAlphaSwizzle[4] = {
LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_RED
};
// Map R to RGB
static const GLenum kLegacyLuminanceSwizzle[4] = {
LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_ONE
};
// Map R to RGB, G to A
static const GLenum kLegacyLuminanceAlphaSwizzle[4] = {
LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_GREEN
};
void
SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat)
{
if (!gl->IsCoreProfile())
return;
/* Only support swizzling on core profiles. */
// Bug 1159117: Fix this.
// MOZ_RELEASE_ASSERT(gl->IsSupported(gl::GLFeature::texture_swizzle));
switch (internalformat) {
case LOCAL_GL_ALPHA:
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
(GLint*) kLegacyAlphaSwizzle);
break;
case LOCAL_GL_LUMINANCE:
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
(GLint*) kLegacyLuminanceSwizzle);
break;
case LOCAL_GL_LUMINANCE_ALPHA:
gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA,
(GLint*) kLegacyLuminanceAlphaSwizzle);
break;
}
}
/**
* Return the bits per texel for format & type combination.
* Assumes that format & type are a valid combination as checked with
* ValidateTexImageFormatAndType().
*/
size_t
GetBitsPerTexel(TexInternalFormat effectiveinternalformat)
{
switch (effectiveinternalformat.get()) {
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
return 2;
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case LOCAL_GL_ATC_RGB:
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
case LOCAL_GL_ETC1_RGB8_OES:
return 4;
case LOCAL_GL_ALPHA8:
case LOCAL_GL_LUMINANCE8:
case LOCAL_GL_R8:
case LOCAL_GL_R8I:
case LOCAL_GL_R8UI:
case LOCAL_GL_R8_SNORM:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
return 8;
case LOCAL_GL_LUMINANCE8_ALPHA8:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_DEPTH_COMPONENT16:
case LOCAL_GL_RG8:
case LOCAL_GL_R16I:
case LOCAL_GL_R16UI:
case LOCAL_GL_RGB565:
case LOCAL_GL_R16F:
case LOCAL_GL_RG8I:
case LOCAL_GL_RG8UI:
case LOCAL_GL_RG8_SNORM:
case LOCAL_GL_ALPHA16F_EXT:
case LOCAL_GL_LUMINANCE16F_EXT:
return 16;
case LOCAL_GL_RGB8:
case LOCAL_GL_DEPTH_COMPONENT24:
case LOCAL_GL_SRGB8:
case LOCAL_GL_RGB8UI:
case LOCAL_GL_RGB8I:
case LOCAL_GL_RGB8_SNORM:
return 24;
case LOCAL_GL_RGBA8:
case LOCAL_GL_RGB10_A2:
case LOCAL_GL_R32F:
case LOCAL_GL_RG16F:
case LOCAL_GL_R32I:
case LOCAL_GL_R32UI:
case LOCAL_GL_RG16I:
case LOCAL_GL_RG16UI:
case LOCAL_GL_DEPTH24_STENCIL8:
case LOCAL_GL_R11F_G11F_B10F:
case LOCAL_GL_RGB9_E5:
case LOCAL_GL_SRGB8_ALPHA8:
case LOCAL_GL_DEPTH_COMPONENT32F:
case LOCAL_GL_RGBA8UI:
case LOCAL_GL_RGBA8I:
case LOCAL_GL_RGBA8_SNORM:
case LOCAL_GL_RGB10_A2UI:
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
case LOCAL_GL_ALPHA32F_EXT:
case LOCAL_GL_LUMINANCE32F_EXT:
return 32;
case LOCAL_GL_DEPTH32F_STENCIL8:
return 40;
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGB16UI:
case LOCAL_GL_RGB16I:
return 48;
case LOCAL_GL_RG32F:
case LOCAL_GL_RG32I:
case LOCAL_GL_RG32UI:
case LOCAL_GL_RGBA16F:
case LOCAL_GL_RGBA16UI:
case LOCAL_GL_RGBA16I:
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
return 64;
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGB32UI:
case LOCAL_GL_RGB32I:
return 96;
case LOCAL_GL_RGBA32F:
case LOCAL_GL_RGBA32UI:
case LOCAL_GL_RGBA32I:
return 128;
default:
MOZ_ASSERT(false, "Unhandled format");
return 0;
}
}
void
WebGLContext::GenerateWarning(const char* fmt, ...)
{
@ -110,6 +520,27 @@ WebGLContext::ShouldGenerateWarnings() const
return mAlreadyGeneratedWarnings < mMaxWarnings;
}
CheckedUint32
WebGLContext::GetImageSize(GLsizei height, GLsizei width, GLsizei depth,
uint32_t pixelSize, uint32_t packOrUnpackAlignment)
{
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
// alignedRowSize = row size rounded up to next multiple of packAlignment
CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
// if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
CheckedUint32 checked_2dImageSize = 0;
if (height >= 1) {
checked_2dImageSize = (height-1) * checked_alignedRowSize +
checked_plainRowSize;
}
// FIXME - we should honor UNPACK_IMAGE_HEIGHT
CheckedUint32 checked_imageSize = checked_2dImageSize * depth;
return checked_imageSize;
}
void
WebGLContext::SynthesizeGLError(GLenum err)
{
@ -681,7 +1112,7 @@ WebGLContext::AssertCachedBindings()
GetAndFlushUnderlyingGLErrors();
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
}
@ -737,20 +1168,10 @@ WebGLContext::AssertCachedState()
GetAndFlushUnderlyingGLErrors();
////////////////
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
if (IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
{
MOZ_ASSERT(mImplMaxColorAttachments == std::min(mGLMaxColorAttachments,
mGLMaxDrawBuffers));
MOZ_ASSERT(mImplMaxDrawBuffers == mGLMaxDrawBuffers);
} else {
MOZ_ASSERT(mImplMaxColorAttachments == 1);
MOZ_ASSERT(mImplMaxDrawBuffers == 1);
// extensions
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
}
// Draw state
@ -813,19 +1234,8 @@ WebGLContext::AssertCachedState()
int4[2] == mViewportWidth &&
int4[3] == mViewportHeight);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStore_PackAlignment);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStore_UnpackAlignment);
if (IsWebGL2()) {
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_IMAGE_HEIGHT, mPixelStore_UnpackImageHeight);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_IMAGES , mPixelStore_UnpackSkipImages);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ROW_LENGTH , mPixelStore_UnpackRowLength);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_ROWS , mPixelStore_UnpackSkipRows);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_PIXELS , mPixelStore_UnpackSkipPixels);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ROW_LENGTH , mPixelStore_PackRowLength);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_ROWS , mPixelStore_PackSkipRows);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_PIXELS , mPixelStore_PackSkipPixels);
}
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
#endif

View File

@ -15,6 +15,35 @@
namespace mozilla {
bool IsGLDepthFormat(TexInternalFormat webGLFormat);
bool IsGLDepthStencilFormat(TexInternalFormat webGLFormat);
bool FormatHasAlpha(TexInternalFormat webGLFormat);
void
DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
TexInternalFormat internalformat,
GLenum* const out_driverInternalFormat,
GLenum* const out_driverFormat,
GLenum* const out_driverType);
TexInternalFormat
EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
TexType type);
TexInternalFormat
EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
TexType type);
void
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
TexInternalFormat* const out_internalformat,
TexType* const out_type);
TexType TypeFromInternalFormat(TexInternalFormat internalformat);
TexInternalFormat
UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat);
void SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat);
size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
// For use with the different texture calls, i.e.
// TexImage2D, CopyTex[Sub]Image2D, ...
// that take a "target" parameter. This parameter is not always the same as
@ -32,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;
@ -64,7 +96,7 @@ WebGLContext::WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType* object,
if (!object)
return JS::NullValue();
MOZ_ASSERT(this == object->mContext);
MOZ_ASSERT(this == object->Context());
JS::Rooted<JS::Value> v(cx);
JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
JSAutoCompartment ac(cx, wrapper);

File diff suppressed because it is too large Load Diff

View File

@ -358,11 +358,8 @@ WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
return JS::NumberValue(uint32_t(mBoundVertexArray->mAttribs[index].type));
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
if (IsWebGL2() ||
IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
{
if (IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays))
return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
}
break;
case LOCAL_GL_CURRENT_VERTEX_ATTRIB:

View File

@ -9,31 +9,32 @@
#include "WebGLContext.h"
#include "WebGLFormats.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
auto& fua = webgl->mFormatUsage;
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
auto fnUpdateUsage = [&fua](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto usage = fua->EditUsage(effFormat);
usage->isRenderable = true;
fua->AllowRBFormat(sizedFormat, usage);
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->asRenderbuffer = usage->isRenderable = true;
};
#define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
// Ensure require formats are initialized.
WebGLExtensionTextureFloat::InitWebGLFormats(authority);
// The extension doesn't actually add RGB32F; only RGBA32F.
FOO(RGBA32F);
#undef FOO
// Update usage to allow asRenderbuffer and isRenderable
updateUsage(EffectiveFormat::RGBA32F);
updateUsage(EffectiveFormat::RGB32F);
updateUsage(EffectiveFormat::Luminance32FAlpha32F);
updateUsage(EffectiveFormat::Luminance32F);
updateUsage(EffectiveFormat::Alpha32F);
}
WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()

View File

@ -9,31 +9,32 @@
#include "WebGLContext.h"
#include "WebGLFormats.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
auto& fua = webgl->mFormatUsage;
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
auto fnUpdateUsage = [&fua](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto usage = fua->EditUsage(effFormat);
usage->isRenderable = true;
fua->AllowRBFormat(sizedFormat, usage);
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->asRenderbuffer = usage->isRenderable = true;
};
#define FOO(x) fnUpdateUsage(LOCAL_GL_ ## x, webgl::EffectiveFormat::x)
// Ensure require formats are initialized.
WebGLExtensionTextureHalfFloat::InitWebGLFormats(authority);
FOO(RGBA16F);
FOO(RGB16F);
#undef FOO
// Update usage to allow asRenderbuffer and isRenderable
updateUsage(EffectiveFormat::RGBA16F);
updateUsage(EffectiveFormat::RGB16F);
updateUsage(EffectiveFormat::Luminance16FAlpha16F);
updateUsage(EffectiveFormat::Luminance16F);
updateUsage(EffectiveFormat::Alpha16F);
}
WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()

View File

@ -7,33 +7,14 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
WebGLExtensionCompressedTextureATC::WebGLExtensionCompressedTextureATC(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto& fua = webgl_->mFormatUsage;
auto usage = fua->EditUsage(effFormat);
usage->isFilterable = true;
fua->AllowSizedTexFormat(sizedFormat, usage);
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
};
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
fnAdd(FOO(ATC_RGB_AMD));
fnAdd(FOO(ATC_RGBA_EXPLICIT_ALPHA_AMD));
fnAdd(FOO(ATC_RGBA_INTERPOLATED_ALPHA_AMD));
#undef FOO
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGB);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA);
}
WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()

View File

@ -7,31 +7,12 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto& fua = webgl_->mFormatUsage;
auto usage = fua->EditUsage(effFormat);
usage->isFilterable = true;
fua->AllowSizedTexFormat(sizedFormat, usage);
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
};
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
fnAdd(FOO(ETC1_RGB8_OES));
#undef FOO
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ETC1_RGB8_OES);
}
WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()

View File

@ -7,34 +7,15 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto& fua = webgl_->mFormatUsage;
auto usage = fua->EditUsage(effFormat);
usage->isFilterable = true;
fua->AllowSizedTexFormat(sizedFormat, usage);
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
};
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1));
fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1));
fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1));
fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1));
#undef FOO
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
}
WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()

View File

@ -7,34 +7,15 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#ifdef FOO
#error FOO is already defined! We use FOO() macros to keep things succinct in this file.
#endif
namespace mozilla {
WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
const auto fnAdd = [&webgl_](GLenum sizedFormat, webgl::EffectiveFormat effFormat) {
auto& fua = webgl_->mFormatUsage;
auto usage = fua->EditUsage(effFormat);
usage->isFilterable = true;
fua->AllowSizedTexFormat(sizedFormat, usage);
webgl_->mCompressedTextureFormats.AppendElement(sizedFormat);
};
#define FOO(x) LOCAL_GL_ ## x, webgl::EffectiveFormat::x
fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT));
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT));
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT));
fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT));
#undef FOO
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
}
WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()

View File

@ -13,29 +13,6 @@ namespace mozilla {
WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
auto& fua = webgl->mFormatUsage;
const auto fnAdd = [&fua](webgl::EffectiveFormat effFormat, GLenum unpackFormat,
GLenum unpackType)
{
auto usage = fua->EditUsage(effFormat);
usage->isRenderable = true;
const webgl::PackingInfo pi = {unpackFormat, unpackType};
const webgl::DriverUnpackInfo dui = {unpackFormat, unpackFormat, unpackType};
fua->AddTexUnpack(usage, pi, dui);
fua->AllowUnsizedTexFormat(pi, usage);
};
fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT16, LOCAL_GL_DEPTH_COMPONENT,
LOCAL_GL_UNSIGNED_SHORT);
fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24, LOCAL_GL_DEPTH_COMPONENT,
LOCAL_GL_UNSIGNED_INT);
fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8, LOCAL_GL_DEPTH_STENCIL,
LOCAL_GL_UNSIGNED_INT_24_8);
}
WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()

View File

@ -20,12 +20,26 @@ WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* webgl)
{
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
// WEBGL_draw_buffers:
// "The value of the MAX_COLOR_ATTACHMENTS_WEBGL parameter must be greater than or
// equal to that of the MAX_DRAW_BUFFERS_WEBGL parameter."
webgl->mImplMaxColorAttachments = webgl->mGLMaxColorAttachments;
webgl->mImplMaxDrawBuffers = std::min(webgl->mGLMaxDrawBuffers,
webgl->mImplMaxColorAttachments);
GLint maxColorAttachments = 0;
GLint maxDrawBuffers = 0;
webgl->MakeContextCurrent();
gl::GLContext* gl = webgl->GL();
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
gl->fGetIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
// WEBGL_draw_buffers specifications don't give a maximal value reachable by MAX_COLOR_ATTACHMENTS.
maxColorAttachments = std::min(maxColorAttachments, GLint(WebGLContext::kMaxColorAttachments));
if (webgl->MinCapabilityMode())
maxColorAttachments = std::min(maxColorAttachments, GLint(kMinColorAttachments));
// WEBGL_draw_buffers specifications request MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
maxDrawBuffers = std::min(maxDrawBuffers, GLint(maxColorAttachments));
webgl->mGLMaxColorAttachments = maxColorAttachments;
webgl->mGLMaxDrawBuffers = maxDrawBuffers;
}
WebGLExtensionDrawBuffers::~WebGLExtensionDrawBuffers()
@ -51,12 +65,20 @@ WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
if (!gl->IsSupported(gl::GLFeature::draw_buffers))
return false;
GLint supportedColorAttachments = 0;
GLint supportedDrawBuffers = 0;
webgl->MakeContextCurrent();
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedColorAttachments);
gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedDrawBuffers);
// WEBGL_draw_buffers requires at least 4 color attachments.
if (webgl->mGLMaxDrawBuffers < webgl->kMinMaxDrawBuffers ||
webgl->mGLMaxColorAttachments < webgl->kMinMaxColorAttachments)
{
if (size_t(supportedColorAttachments) < kMinColorAttachments)
return false;
if (size_t(supportedDrawBuffers) < kMinDrawBuffers)
return false;
}
return true;
}

View File

@ -12,6 +12,9 @@
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
@ -25,32 +28,20 @@ WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
}
auto& fua = webgl->mFormatUsage;
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
RefPtr<gl::GLContext> gl_ = gl; // Bug 1201275
const auto fnAdd = [&fua, &gl_](webgl::EffectiveFormat effFormat, GLenum format,
GLenum desktopUnpackFormat)
{
auto usage = fua->EditUsage(effFormat);
usage->isFilterable = true;
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat,
GLenum unpackFormat, GLenum unpackType,
bool asRenderbuffer)
{
if (!authority->GetUsage(effectiveFormat)) {
authority->AddFormat(effectiveFormat, asRenderbuffer, asRenderbuffer, true, true);
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
}
};
webgl::DriverUnpackInfo dui = {format, format, LOCAL_GL_UNSIGNED_BYTE};
const auto pi = dui.ToPacking();
if (!gl_->IsGLES())
dui.unpackFormat = desktopUnpackFormat;
fua->AddTexUnpack(usage, pi, dui);
fua->AllowUnsizedTexFormat(pi, usage);
};
fnAdd(webgl::EffectiveFormat::SRGB8, LOCAL_GL_SRGB, LOCAL_GL_RGB);
fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA, LOCAL_GL_RGBA);
auto usage = fua->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8);
usage->isRenderable = true;
fua->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8, usage);
addFormatIfMissing(EffectiveFormat::SRGB8 , LOCAL_GL_SRGB , LOCAL_GL_UNSIGNED_BYTE, false);
addFormatIfMissing(EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA, LOCAL_GL_UNSIGNED_BYTE, true);
}
WebGLExtensionSRGB::~WebGLExtensionSRGB()

View File

@ -4,112 +4,63 @@
#include "WebGLExtensions.h"
#include "GLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#include "WebGLFormats.h"
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
void
WebGLExtensionTextureFloat::InitWebGLFormats(webgl::FormatUsageAuthority* authority)
{
MOZ_ASSERT(authority);
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat)
{
if (!authority->GetUsage(effectiveFormat)) {
authority->AddFormat(effectiveFormat, false, false, false, false);
}
};
// Populate authority with any missing effective formats.
addFormatIfMissing(EffectiveFormat::RGBA32F);
addFormatIfMissing(EffectiveFormat::RGB32F);
addFormatIfMissing(EffectiveFormat::Luminance32FAlpha32F);
addFormatIfMissing(EffectiveFormat::Luminance32F);
addFormatIfMissing(EffectiveFormat::Alpha32F);
}
WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
MOZ_ASSERT(IsSupported(webgl));
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
auto& fua = webgl->mFormatUsage;
gl::GLContext* gl = webgl->GL();
auto updateUsage = [authority](EffectiveFormat effectiveFormat,
GLenum unpackFormat, GLenum unpackType)
{
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->asTexture = true;
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
};
webgl::PackingInfo pi;
webgl::DriverUnpackInfo dui;
const GLint* swizzle = nullptr;
// Ensure require formats are initialized.
InitWebGLFormats(authority);
const auto fnAdd = [&fua, &pi, &dui, &swizzle](webgl::EffectiveFormat effFormat)
{
auto usage = fua->EditUsage(effFormat);
usage->textureSwizzleRGBA = swizzle;
fua->AddTexUnpack(usage, pi, dui);
fua->AllowUnsizedTexFormat(pi, usage);
};
const bool needSizedInternal = !gl->IsGLES();
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
////////////////
pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
if (needSizedInternal) {
dui.internalFormat = LOCAL_GL_RGBA32F;
}
fnAdd(webgl::EffectiveFormat::RGBA32F);
//////
pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
if (needSizedInternal) {
dui.internalFormat = LOCAL_GL_RGB32F;
}
fnAdd(webgl::EffectiveFormat::RGB32F);
//////
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Luminance32F);
//////
pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Alpha32F);
//////
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
dui = {pi.format, pi.format, pi.type};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT};
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
// Update usage to allow asTexture and add unpack
updateUsage(EffectiveFormat::RGBA32F , LOCAL_GL_RGBA , LOCAL_GL_FLOAT);
updateUsage(EffectiveFormat::RGB32F , LOCAL_GL_RGB , LOCAL_GL_FLOAT);
updateUsage(EffectiveFormat::Luminance32FAlpha32F, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT);
updateUsage(EffectiveFormat::Luminance32F , LOCAL_GL_LUMINANCE , LOCAL_GL_FLOAT);
updateUsage(EffectiveFormat::Alpha32F , LOCAL_GL_ALPHA , LOCAL_GL_FLOAT);
}
WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
{
}
bool
WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl)
{
gl::GLContext* gl = webgl->GL();
if (!gl->IsSupported(gl::GLFeature::texture_float))
return false;
const bool needSizedInternal = !gl->IsGLES();
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
if (needSizedInternal && !hasSwizzle)
return false;
return true;
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat, OES_texture_float)
} // namespace mozilla

View File

@ -10,16 +10,32 @@
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
auto& fua = webgl->mFormatUsage;
// This update requires that the authority already be populated by
// WebGLExtensionTextureFloat. Enabling extensions to control
// features is a mess in WebGL
fua->EditUsage(webgl::EffectiveFormat::RGBA32F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::RGB32F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Luminance32F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Alpha32F)->isFilterable = true;
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->isFilterable = true;
};
// Ensure require formats are initialized.
WebGLExtensionTextureFloat::InitWebGLFormats(authority);
// Update usage to allow isFilterable
updateUsage(EffectiveFormat::RGBA32F);
updateUsage(EffectiveFormat::RGB32F);
updateUsage(EffectiveFormat::Luminance32FAlpha32F);
updateUsage(EffectiveFormat::Luminance32F);
updateUsage(EffectiveFormat::Alpha32F);
}
WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()

View File

@ -4,119 +4,62 @@
#include "WebGLExtensions.h"
#include "GLContext.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "WebGLContext.h"
#include "WebGLFormats.h"
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
void
WebGLExtensionTextureHalfFloat::InitWebGLFormats(webgl::FormatUsageAuthority* authority)
{
MOZ_ASSERT(authority);
auto addFormatIfMissing = [authority](EffectiveFormat effectiveFormat)
{
if (!authority->GetUsage(effectiveFormat)) {
authority->AddFormat(effectiveFormat, false, false, false, false);
}
};
// Populate authority with any missing effective formats.
addFormatIfMissing(EffectiveFormat::RGBA16F);
addFormatIfMissing(EffectiveFormat::RGB16F);
addFormatIfMissing(EffectiveFormat::Luminance16FAlpha16F);
addFormatIfMissing(EffectiveFormat::Luminance16F);
addFormatIfMissing(EffectiveFormat::Alpha16F);
}
WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
auto& fua = webgl->mFormatUsage;
gl::GLContext* gl = webgl->GL();
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
webgl::PackingInfo pi;
webgl::DriverUnpackInfo dui;
const GLint* swizzle = nullptr;
auto updateUsage = [authority](EffectiveFormat effectiveFormat,
GLenum unpackFormat, GLenum unpackType)
{
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->asTexture = true;
authority->AddUnpackOption(unpackFormat, unpackType, effectiveFormat);
};
const auto fnAdd = [&fua, &pi, &dui, &swizzle](webgl::EffectiveFormat effFormat)
{
auto usage = fua->EditUsage(effFormat);
usage->textureSwizzleRGBA = swizzle;
fua->AddTexUnpack(usage, pi, dui);
InitWebGLFormats(authority);
fua->AllowUnsizedTexFormat(pi, usage);
};
const bool needSizedInternal = !gl->IsGLES();
MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle));
GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
driverUnpackType = LOCAL_GL_HALF_FLOAT_OES;
}
////////////////
pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
if (needSizedInternal) {
dui.internalFormat = LOCAL_GL_RGBA16F;
}
fnAdd(webgl::EffectiveFormat::RGBA16F);
//////
pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
if (needSizedInternal) {
dui.internalFormat = LOCAL_GL_RGB16F;
}
fnAdd(webgl::EffectiveFormat::RGB16F);
//////
pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Luminance16F);
//////
pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Alpha16F);
//////
pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
dui = {pi.format, pi.format, driverUnpackType};
swizzle = nullptr;
if (needSizedInternal) {
dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType};
swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
}
fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
// Update usage to allow asTexture and add unpack
updateUsage(EffectiveFormat::RGBA16F , LOCAL_GL_RGBA , LOCAL_GL_HALF_FLOAT_OES);
updateUsage(EffectiveFormat::RGB16F , LOCAL_GL_RGB , LOCAL_GL_HALF_FLOAT_OES);
updateUsage(EffectiveFormat::Luminance16FAlpha16F, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES);
updateUsage(EffectiveFormat::Luminance16F , LOCAL_GL_LUMINANCE , LOCAL_GL_HALF_FLOAT_OES);
updateUsage(EffectiveFormat::Alpha16F , LOCAL_GL_ALPHA , LOCAL_GL_HALF_FLOAT_OES);
}
WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
{
}
bool
WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl)
{
gl::GLContext* gl = webgl->GL();
if (!gl->IsSupported(gl::GLFeature::texture_half_float) &&
!gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float))
{
return false;
}
const bool needSizedInternal = !gl->IsGLES();
const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
if (needSizedInternal && !hasSwizzle)
return false;
return true;
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat, OES_texture_half_float)
} // namespace mozilla

View File

@ -10,16 +10,32 @@
namespace mozilla {
using mozilla::webgl::EffectiveFormat;
WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(WebGLContext* webgl)
: WebGLExtensionBase(webgl)
{
auto& fua = webgl->mFormatUsage;
// This update requires that the authority already be populated by
// WebGLExtensionTextureHalfFloat. Enabling extensions to control
// features is a mess in WebGL
fua->EditUsage(webgl::EffectiveFormat::RGBA16F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::RGB16F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Luminance16F)->isFilterable = true;
fua->EditUsage(webgl::EffectiveFormat::Alpha16F)->isFilterable = true;
webgl::FormatUsageAuthority* authority = webgl->mFormatUsage.get();
auto updateUsage = [authority](EffectiveFormat effectiveFormat) {
webgl::FormatUsageInfo* usage = authority->GetUsage(effectiveFormat);
MOZ_ASSERT(usage);
usage->isFilterable = true;
};
// Ensure require formats are initialized.
WebGLExtensionTextureHalfFloat::InitWebGLFormats(authority);
// Update usage to allow isFilterable
updateUsage(EffectiveFormat::RGBA16F);
updateUsage(EffectiveFormat::RGB16F);
updateUsage(EffectiveFormat::Luminance16FAlpha16F);
updateUsage(EffectiveFormat::Luminance16F);
updateUsage(EffectiveFormat::Alpha16F);
}
WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()

View File

@ -38,7 +38,7 @@ public:
explicit WebGLExtensionBase(WebGLContext* webgl);
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
void MarkLost();
@ -219,8 +219,6 @@ public:
explicit WebGLExtensionTextureFloat(WebGLContext*);
virtual ~WebGLExtensionTextureFloat();
static bool IsSupported(const WebGLContext*);
DECL_WEBGL_EXTENSION_GOOP
};
@ -243,8 +241,6 @@ public:
explicit WebGLExtensionTextureHalfFloat(WebGLContext*);
virtual ~WebGLExtensionTextureHalfFloat();
static bool IsSupported(const WebGLContext*);
DECL_WEBGL_EXTENSION_GOOP
};
@ -293,6 +289,14 @@ public:
static bool IsSupported(const WebGLContext*);
static const size_t kMinColorAttachments = 4;
static const size_t kMinDrawBuffers = 4;
/*
WEBGL_draw_buffers does not give a minal value for GL_MAX_DRAW_BUFFERS. But, we request
for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachments.
See DrawBuffersWEBGL in WebGLExtensionDrawBuffers.cpp inner comments for more informations.
*/
DECL_WEBGL_EXTENSION_GOOP
};

File diff suppressed because it is too large Load Diff

View File

@ -93,7 +93,10 @@ enum class EffectiveFormat : EffectiveFormatValueT {
// GLES 3.0.4, p205-206, "Required Renderbuffer Formats"
STENCIL_INDEX8,
////////////////////////////////////
// GLES 3.0.4, p128, table 3.12.
Luminance8Alpha8,
Luminance8,
Alpha8,
// GLES 3.0.4, p147, table 3.19
// GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
@ -114,10 +117,10 @@ enum class EffectiveFormat : EffectiveFormatValueT {
ATC_RGBA_INTERPOLATED_ALPHA_AMD,
// EXT_texture_compression_s3tc
COMPRESSED_RGB_S3TC_DXT1_EXT,
COMPRESSED_RGBA_S3TC_DXT1_EXT,
COMPRESSED_RGBA_S3TC_DXT3_EXT,
COMPRESSED_RGBA_S3TC_DXT5_EXT,
COMPRESSED_RGB_S3TC_DXT1,
COMPRESSED_RGBA_S3TC_DXT1,
COMPRESSED_RGBA_S3TC_DXT3,
COMPRESSED_RGBA_S3TC_DXT5,
// IMG_texture_compression_pvrtc
COMPRESSED_RGB_PVRTC_4BPPV1,
@ -126,14 +129,7 @@ enum class EffectiveFormat : EffectiveFormatValueT {
COMPRESSED_RGBA_PVRTC_2BPPV1,
// OES_compressed_ETC1_RGB8_texture
ETC1_RGB8_OES,
////////////////////////////////////
// GLES 3.0.4, p128, table 3.12.
Luminance8Alpha8,
Luminance8,
Alpha8,
ETC1_RGB8,
// OES_texture_float
Luminance32FAlpha32F,
@ -161,151 +157,116 @@ enum class UnsizedFormat : uint8_t {
DS,
};
// GLES 3.0.4 p114 Table 3.4, p240
// GLES 3.0.4 p114 Table 3.4
enum class ComponentType : uint8_t {
None,
None, // DEPTH_COMPONENT32F
Int, // RGBA32I
UInt, // RGBA32UI, STENCIL_INDEX8
UInt, // RGBA32UI
NormInt, // RGBA8_SNORM
NormUInt, // RGBA8, DEPTH_COMPONENT16
NormUInt, // RGBA8
NormUIntSRGB, // SRGB8_ALPHA8
Float, // RGBA32F
Special, // DEPTH24_STENCIL8
SharedExp, // RGB9_E5
};
enum class CompressionFamily : uint8_t {
ETC1,
ES3, // ETC2 or EAC
ATC,
S3TC,
PVRTC,
enum class SubImageUpdateBehavior : uint8_t {
Forbidden,
FullOnly,
BlockAligned,
};
////////////////////////////////////////////////////////////////////////////////
struct CompressedFormatInfo
{
struct CompressedFormatInfo {
const EffectiveFormat effectiveFormat;
const uint8_t bytesPerBlock;
const uint8_t blockWidth;
const uint8_t blockHeight;
const CompressionFamily family;
const bool requirePOT;
const SubImageUpdateBehavior subImageUpdateBehavior;
};
struct FormatInfo
{
struct FormatInfo {
const EffectiveFormat effectiveFormat;
const char* const name;
const GLenum sizedFormat;
const UnsizedFormat unsizedFormat;
const ComponentType componentType;
const uint8_t estimatedBytesPerPixel; // 0 iff `!!compression`. Only use this for
const bool isColorFormat; // memory usage estimation. Use
const bool isSRGB; // BytesPerPixel(packingFormat, packingType) for
const bool hasAlpha; // calculating pack/unpack byte count.
const ComponentType colorComponentType;
const uint8_t bytesPerPixel; // 0 iff `!!compression`.
const bool hasColor;
const bool hasAlpha;
const bool hasDepth;
const bool hasStencil;
const CompressedFormatInfo* const compression;
};
struct PackingInfo
{
GLenum format;
GLenum type;
bool operator <(const PackingInfo& x) const
{
if (format != x.format)
return format < x.format;
return type < x.type;
}
};
struct DriverUnpackInfo
{
GLenum internalFormat;
GLenum unpackFormat;
GLenum unpackType;
PackingInfo ToPacking() const {
return {unpackFormat, unpackType};
}
};
//////////////////////////////////////////////////////////////////////////////////////////
const FormatInfo* GetFormat(EffectiveFormat format);
uint8_t BytesPerPixel(const PackingInfo& packing);
/*
GLint ComponentSize(const FormatInfo* format, GLenum component);
GLenum ComponentType(const FormatInfo* format);
*/
const FormatInfo* GetFormatInfo(EffectiveFormat format);
const FormatInfo* GetInfoByUnpackTuple(GLenum unpackFormat, GLenum unpackType);
const FormatInfo* GetInfoBySizedFormat(GLenum sizedFormat);
////////////////////////////////////////
struct FormatUsageInfo
{
const FormatInfo* const format;
struct UnpackTuple {
const GLenum format;
const GLenum type;
bool operator <(const UnpackTuple& x) const
{
if (format == x.format) {
return type < x.type;
}
return format < x.format;
}
};
struct FormatUsageInfo {
const FormatInfo* const formatInfo;
bool asRenderbuffer;
bool isRenderable;
bool asTexture;
bool isFilterable;
std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
const DriverUnpackInfo* idealUnpack;
const GLint* textureSwizzleRGBA;
std::set<UnpackTuple> validUnpacks;
static const GLint kLuminanceSwizzleRGBA[4];
static const GLint kAlphaSwizzleRGBA[4];
static const GLint kLumAlphaSwizzleRGBA[4];
explicit FormatUsageInfo(const FormatInfo* _format)
: format(_format)
, isRenderable(false)
, isFilterable(false)
, idealUnpack(nullptr)
, textureSwizzleRGBA(nullptr)
{ }
bool IsUnpackValid(const PackingInfo& key,
const DriverUnpackInfo** const out_value) const;
bool CanUnpackWith(GLenum unpackFormat, GLenum unpackType) const;
};
class FormatUsageAuthority
{
std::map<EffectiveFormat, FormatUsageInfo> mUsageMap;
std::map<GLenum, const FormatUsageInfo*> mRBFormatMap;
std::map<GLenum, const FormatUsageInfo*> mSizedTexFormatMap;
std::map<PackingInfo, const FormatUsageInfo*> mUnsizedTexFormatMap;
std::set<GLenum> mValidTexInternalFormats;
std::set<GLenum> mValidTexUnpackFormats;
std::set<GLenum> mValidTexUnpackTypes;
std::map<EffectiveFormat, FormatUsageInfo> mInfoMap;
public:
static UniquePtr<FormatUsageAuthority> CreateForWebGL1(gl::GLContext* gl);
static UniquePtr<FormatUsageAuthority> CreateForWebGL2(gl::GLContext* gl);
static UniquePtr<FormatUsageAuthority> CreateForWebGL1();
static UniquePtr<FormatUsageAuthority> CreateForWebGL2();
private:
FormatUsageAuthority() { }
public:
FormatUsageInfo* EditUsage(EffectiveFormat format);
const FormatUsageInfo* GetUsage(EffectiveFormat format) const;
void AddFormat(EffectiveFormat format, bool asRenderbuffer, bool isRenderable,
bool asTexture, bool isFilterable);
void AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi,
const DriverUnpackInfo& dui);
void AddUnpackOption(GLenum unpackFormat, GLenum unpackType,
EffectiveFormat effectiveFormat);
bool IsInternalFormatEnumValid(GLenum internalFormat) const;
bool AreUnpackEnumsValid(GLenum unpackFormat, GLenum unpackType) const;
FormatUsageInfo* GetUsage(EffectiveFormat format);
FormatUsageInfo* GetUsage(const FormatInfo* format)
{
if (!format)
return nullptr;
void AllowRBFormat(GLenum sizedFormat, const FormatUsageInfo* usage);
void AllowSizedTexFormat(GLenum sizedFormat, const FormatUsageInfo* usage);
void AllowUnsizedTexFormat(const PackingInfo& pi, const FormatUsageInfo* usage);
const FormatUsageInfo* GetRBUsage(GLenum sizedFormat) const;
const FormatUsageInfo* GetSizedTexUsage(GLenum sizedFormat) const;
const FormatUsageInfo* GetUnsizedTexUsage(const PackingInfo& pi) const;
return GetUsage(format->effectiveFormat);
}
};
////////////////////////////////////////////////////////////////////////////////
GLint GetComponentSize(EffectiveFormat format, GLenum component);
GLenum GetComponentType(EffectiveFormat format);
GLenum GetColorEncoding(EffectiveFormat format);
} // namespace webgl
} // namespace mozilla

File diff suppressed because it is too large Load Diff

View File

@ -21,9 +21,6 @@ class WebGLFramebuffer;
class WebGLRenderbuffer;
class WebGLTexture;
template<typename T>
class PlacementArray;
namespace gl {
class GLContext;
} // namespace gl
@ -32,39 +29,34 @@ class WebGLFBAttachPoint
{
public:
WebGLFramebuffer* const mFB;
const GLenum mAttachmentPoint;
private:
WebGLRefPtr<WebGLTexture> mTexturePtr;
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
FBAttachment mAttachmentPoint;
TexImageTarget mTexImageTarget;
GLint mTexImageLayer;
GLint mTexImageLevel;
// PlacementArray needs a default constructor.
template<typename T>
friend class PlacementArray;
WebGLFBAttachPoint()
: mFB(nullptr)
, mAttachmentPoint(0)
{ }
public:
WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
WebGLFBAttachPoint(WebGLFramebuffer* fb, FBAttachment attachmentPoint);
~WebGLFBAttachPoint();
void Unlink();
void Unlink() {
mRenderbufferPtr = nullptr;
mTexturePtr = nullptr;
}
bool IsDefined() const;
bool IsDeleteRequested() const;
const webgl::FormatUsageInfo* Format() const;
TexInternalFormat EffectiveInternalFormat() const;
bool HasAlpha() const;
bool IsReadableFloat() const;
void Clear();
void Clear() {
SetRenderbuffer(nullptr);
}
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level,
@ -96,68 +88,15 @@ public:
bool HasUninitializedImageData() const;
void SetImageDataStatus(WebGLImageDataStatus x);
void Size(uint32_t* const out_width, uint32_t* const out_height) const;
//const WebGLRectangleObject& RectangleObject() const;
const WebGLRectangleObject& RectangleObject() const;
bool HasImage() const;
bool IsComplete(WebGLContext* webgl) const;
bool IsComplete() const;
void FinalizeAttachment(gl::GLContext* gl, GLenum attachmentLoc) const;
void FinalizeAttachment(gl::GLContext* gl,
FBAttachment attachmentLoc) const;
JS::Value GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx,
GLenum target, GLenum attachment, GLenum pname,
ErrorResult* const out_error);
void OnBackingStoreRespecified() const;
};
template<typename T>
class PlacementArray
{
public:
const size_t mCapacity;
protected:
size_t mSize;
T* const mArray;
public:
explicit PlacementArray(size_t capacity)
: mCapacity(capacity)
, mSize(0)
, mArray((T*)moz_xmalloc(sizeof(T) * capacity))
{ }
~PlacementArray() {
for (auto& cur : *this) {
cur.~T();
}
free(mArray);
}
T* begin() const {
return mArray;
}
T* end() const {
return mArray + mSize;
}
T& operator [](size_t offset) const {
MOZ_ASSERT(offset < mSize);
return mArray[offset];
}
const size_t& Size() const { return mSize; }
template<typename A, typename B>
void AppendNew(A a, B b) {
if (mSize == mCapacity)
MOZ_CRASH("Bad EmplaceAppend.");
// Placement `new`:
new (&(mArray[mSize])) T(a, b);
++mSize;
}
JS::Value GetParameter(WebGLContext* context, GLenum pname);
};
class WebGLFramebuffer final
@ -175,7 +114,7 @@ public:
const GLuint mGLName;
private:
mutable bool mIsKnownFBComplete;
mutable GLenum mStatus;
GLenum mReadBufferMode;
@ -184,17 +123,7 @@ private:
WebGLFBAttachPoint mDepthAttachment;
WebGLFBAttachPoint mStencilAttachment;
WebGLFBAttachPoint mDepthStencilAttachment;
PlacementArray<WebGLFBAttachPoint> mMoreColorAttachments;
std::vector<GLenum> mDrawBuffers;
bool IsDrawBuffer(size_t n) const {
if (n < mDrawBuffers.size())
return bool(mDrawBuffers[n]);
return false;
}
nsTArray<WebGLFBAttachPoint> mMoreColorAttachments;
#ifdef ANDROID
// Bug 1140459: Some drivers (including our test slaves!) don't
@ -218,11 +147,14 @@ private:
public:
void Delete();
void FramebufferRenderbuffer(GLenum attachment, RBTarget rbtarget,
void FramebufferRenderbuffer(FBAttachment attachment, RBTarget rbtarget,
WebGLRenderbuffer* rb);
void FramebufferTexture2D(GLenum attachment, TexImageTarget texImageTarget,
WebGLTexture* tex, GLint level);
void FramebufferTextureLayer(GLenum attachment, WebGLTexture* tex, GLint level,
void FramebufferTexture2D(FBAttachment attachment,
TexImageTarget texImageTarget, WebGLTexture* tex,
GLint level);
void FramebufferTextureLayer(FBAttachment attachment, WebGLTexture* tex, GLint level,
GLint layer);
bool HasDefinedAttachments() const;
@ -231,11 +163,20 @@ public:
FBStatus PrecheckFramebufferStatus() const;
FBStatus CheckFramebufferStatus() const;
const webgl::FormatUsageInfo*
GLenum
GetFormatForAttachment(const WebGLFBAttachPoint& attachment) const;
bool HasDepthStencilConflict() const {
return int(mDepthAttachment.IsDefined()) +
int(mStencilAttachment.IsDefined()) +
int(mDepthStencilAttachment.IsDefined()) >= 2;
}
size_t ColorAttachmentCount() const {
return 1 + mMoreColorAttachments.Length();
}
const WebGLFBAttachPoint& ColorAttachment(size_t colorAttachmentId) const {
MOZ_ASSERT(colorAttachmentId < 1 + mMoreColorAttachments.Size());
MOZ_ASSERT(colorAttachmentId < ColorAttachmentCount());
return colorAttachmentId ? mMoreColorAttachments[colorAttachmentId - 1]
: mColorAttachment0;
}
@ -252,16 +193,16 @@ public:
return mDepthStencilAttachment;
}
protected:
WebGLFBAttachPoint* GetAttachPoint(GLenum attachment); // Fallible
WebGLFBAttachPoint& GetAttachPoint(FBAttachment attachPointEnum);
public:
void DetachTexture(const WebGLTexture* tex);
void DetachRenderbuffer(const WebGLRenderbuffer* rb);
const WebGLRectangleObject& RectangleObject() const;
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
void FinalizeAttachments() const;
@ -276,17 +217,19 @@ public:
bool CheckAndInitializeAttachments();
bool CheckColorAttachmentNumber(FBAttachment attachment,
const char* funcName) const;
void EnsureColorAttachPoints(size_t colorAttachmentId);
void InvalidateFramebufferStatus() const {
mIsKnownFBComplete = false;
mStatus = 0;
}
bool ValidateForRead(const char* info,
const webgl::FormatUsageInfo** const out_format,
uint32_t* const out_width, uint32_t* const out_height);
bool ValidateForRead(const char* info, TexInternalFormat* const out_format);
JS::Value GetAttachmentParameter(const char* funcName, JSContext* cx, GLenum target,
GLenum attachment, GLenum pname,
ErrorResult* const out_error);
JS::Value GetAttachmentParameter(JSContext* cx, GLenum attachment, GLenum pname,
ErrorResult& rv);
};
} // namespace mozilla

View File

@ -269,8 +269,10 @@ public:
bool IsCompatibleWithContext(WebGLContext* other);
WebGLContext* const mContext;
WebGLContext* Context() const { return mContext; }
protected:
WebGLContext* const mContext;
const uint32_t mContextGeneration;
};

View File

@ -167,7 +167,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
#endif
const bool isArray = false;
AddActiveInfo(prog->mContext, elemCount, elemType, isArray, userName, mappedName,
AddActiveInfo(prog->Context(), elemCount, elemType, isArray, userName, mappedName,
&info->activeAttribs, &info->attribMap);
// Collect active locations:
@ -232,7 +232,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
printf_stderr(" isArray: %d\n", (int)isArray);
#endif
AddActiveInfo(prog->mContext, elemCount, elemType, isArray, baseUserName,
AddActiveInfo(prog->Context(), elemCount, elemType, isArray, baseUserName,
baseMappedName, &info->activeUniforms, &info->uniformMap);
}
@ -327,9 +327,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
}
AddActiveInfo(prog->mContext, size, type, isArray, baseUserName, mappedName,
&info->transformFeedbackVaryings,
&info->transformFeedbackVaryingsMap);
AddActiveInfo(prog->Context(), size, type, isArray, baseUserName, mappedName,
&info->transformFeedbackVaryings, &info->transformFeedbackVaryingsMap);
}
}
@ -338,6 +337,7 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
////////////////////////////////////////////////////////////////////////////////
webgl::LinkedProgramInfo::LinkedProgramInfo(WebGLProgram* prog)
: prog(prog)
, fragDataMap(nullptr)

View File

@ -196,7 +196,7 @@ public:
}
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;

View File

@ -33,7 +33,7 @@ public:
// nsWrapperCache
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
// NS

View File

@ -51,10 +51,10 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
: WebGLContextBoundObject(webgl)
, mPrimaryRB(0)
, mSecondaryRB(0)
, mFormat(nullptr)
, mInternalFormat(0)
, mInternalFormatForGL(0)
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
, mSamples(1)
, mIsUsingSecondary(false)
#ifdef ANDROID
, mIsRB(false)
#endif
@ -86,21 +86,62 @@ WebGLRenderbuffer::Delete()
int64_t
WebGLRenderbuffer::MemoryUsage() const
{
int64_t pixels = int64_t(Width()) * int64_t(Height());
GLenum primaryFormat = InternalFormatForGL();
// If there is no defined format, we're not taking up any memory
if (!mFormat)
if (!primaryFormat)
return 0;
auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
uint64_t pixels = uint64_t(mWidth) * uint64_t(mHeight);
uint64_t totalSize = pixels * bytesPerPixel;
// If we have the same bytesPerPixel whether or not we have a secondary RB.
if (mSecondaryRB && !mIsUsingSecondary) {
totalSize += 2; // 1x1xRGBA4
int64_t secondarySize = 0;
if (mSecondaryRB) {
if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
primaryFormat = DepthStencilDepthFormat(mContext->gl);
secondarySize = 1*pixels; // STENCIL_INDEX8
} else {
secondarySize = 1*1*2; // 1x1xRGBA4
}
}
return int64_t(totalSize);
int64_t primarySize = 0;
switch (primaryFormat) {
case LOCAL_GL_STENCIL_INDEX8:
primarySize = 1*pixels;
break;
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_RGB565:
case LOCAL_GL_DEPTH_COMPONENT16:
primarySize = 2*pixels;
break;
case LOCAL_GL_RGB8:
case LOCAL_GL_DEPTH_COMPONENT24:
primarySize = 3*pixels;
break;
case LOCAL_GL_RGBA8:
case LOCAL_GL_SRGB8_ALPHA8_EXT:
case LOCAL_GL_DEPTH24_STENCIL8:
case LOCAL_GL_DEPTH_COMPONENT32:
primarySize = 4*pixels;
break;
case LOCAL_GL_RGB16F:
primarySize = 2*3*pixels;
break;
case LOCAL_GL_RGBA16F:
primarySize = 2*4*pixels;
break;
case LOCAL_GL_RGB32F:
primarySize = 4*3*pixels;
break;
case LOCAL_GL_RGBA32F:
primarySize = 4*4*pixels;
break;
default:
MOZ_ASSERT(false, "Unknown `primaryFormat`.");
break;
}
return primarySize + secondarySize;
}
void
@ -131,60 +172,27 @@ RenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
MOZ_ASSERT(samples >= 0);
MOZ_ASSERT(samples <= gl->MaxSamples());
// certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
GLenum internalFormatForGL = internalFormat;
switch (internalFormat) {
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
// 16-bit RGBA formats are not supported on desktop GL
if (!gl->IsGLES())
internalFormatForGL = LOCAL_GL_RGBA8;
break;
case LOCAL_GL_RGB565:
// the RGB565 format is not supported on desktop GL
if (!gl->IsGLES())
internalFormatForGL = LOCAL_GL_RGB8;
break;
case LOCAL_GL_DEPTH_COMPONENT16:
if (!gl->IsGLES() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
internalFormatForGL = LOCAL_GL_DEPTH_COMPONENT24;
else if (gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil))
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
break;
case LOCAL_GL_DEPTH_STENCIL:
// We emulate this in WebGLRenderbuffer if we don't have the requisite extension.
internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
break;
default:
break;
}
if (samples > 0) {
gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
internalFormatForGL, width, height);
internalFormat, width, height);
} else {
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormatForGL, width,
gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormat, width,
height);
}
}
void
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
const webgl::FormatUsageInfo* format,
GLsizei width, GLsizei height)
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples, GLenum internalFormat,
GLsizei width, GLsizei height) const
{
MOZ_ASSERT(mContext->mBoundRenderbuffer == this);
InvalidateStatusOfAttachedFBs();
gl::GLContext* gl = mContext->gl;
MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.
GLenum primaryFormat = format->format->sizedFormat;
GLenum primaryFormat = internalFormat;
GLenum secondaryFormat = 0;
if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
@ -195,42 +203,35 @@ WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
RenderbufferStorageMaybeMultisample(gl, samples, primaryFormat, width,
height);
if (mSecondaryRB) {
// We can't leave the secondary RB unspecified either, since we should
// handle the case where we attach a non-depth-stencil RB to a
// depth-stencil attachment point, or attach this depth-stencil RB to a
// non-depth-stencil attachment point.
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
if (secondaryFormat) {
RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
height);
} else {
RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
}
if (!mSecondaryRB) {
MOZ_ASSERT(!secondaryFormat);
return;
}
// We can't leave the secondary RB unspecified either, since we should
// handle the case where we attach a non-depth-stencil RB to a
// depth-stencil attachment point, or attach this depth-stencil RB to a
// non-depth-stencil attachment point.
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
if (secondaryFormat) {
RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
height);
} else {
RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
}
mSamples = samples;
mFormat = format;
mWidth = width;
mHeight = height;
mImageDataStatus = WebGLImageDataStatus::UninitializedImageData;
mIsUsingSecondary = bool(secondaryFormat);
InvalidateStatusOfAttachedFBs();
}
void
WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const
WebGLRenderbuffer::FramebufferRenderbuffer(FBAttachment attachment) const
{
gl::GLContext* gl = mContext->gl;
if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment.get(),
LOCAL_GL_RENDERBUFFER, mPrimaryRB);
return;
}
GLuint stencilRB = mPrimaryRB;
if (mIsUsingSecondary) {
if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
MOZ_ASSERT(mSecondaryRB);
stencilRB = mSecondaryRB;
}
@ -250,13 +251,20 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
switch (pname.get()) {
case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
if (!mFormat)
return 0;
if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
if (gl->WorkAroundDriverBugs() &&
gl->Renderer() == gl::GLRenderer::Tegra)
{
return 8;
}
if (!mFormat->format->hasStencil)
return 0;
gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
return 8;
GLint i = 0;
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
return i;
}
// Fall through otherwise.
case LOCAL_GL_RENDERBUFFER_WIDTH:
case LOCAL_GL_RENDERBUFFER_HEIGHT:
@ -270,19 +278,6 @@ WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
return i;
}
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
{
GLenum ret = 0;
if (mFormat) {
ret = mFormat->format->sizedFormat;
if (!mContext->IsWebGL2() && ret == LOCAL_GL_DEPTH24_STENCIL8) {
ret = LOCAL_GL_DEPTH_STENCIL;
}
}
return ret;
}
}
MOZ_ASSERT(false,

View File

@ -14,9 +14,6 @@
#include "WebGLStrongTypes.h"
namespace mozilla {
namespace webgl {
struct FormatUsageInfo;
}
class WebGLRenderbuffer final
: public nsWrapperCache
@ -32,34 +29,40 @@ public:
void Delete();
bool HasUninitializedImageData() const {
MOZ_ASSERT(mImageDataStatus != WebGLImageDataStatus::NoImageData);
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
}
bool IsDefined() const {
if (!mFormat) {
MOZ_ASSERT(!mWidth && !mHeight);
return false;
}
return true;
void SetImageDataStatus(WebGLImageDataStatus x) {
// there is no way to go from having image data to not having any
MOZ_ASSERT(x != WebGLImageDataStatus::NoImageData ||
mImageDataStatus == WebGLImageDataStatus::NoImageData);
mImageDataStatus = x;
}
GLsizei Samples() const { return mSamples; }
void SetSamples(GLsizei samples) { mSamples = samples; }
GLuint PrimaryGLName() const { return mPrimaryRB; }
const webgl::FormatUsageInfo* Format() const { return mFormat; }
GLenum InternalFormat() const { return mInternalFormat; }
void SetInternalFormat(GLenum internalFormat) {
mInternalFormat = internalFormat;
}
GLenum InternalFormatForGL() const { return mInternalFormatForGL; }
void SetInternalFormatForGL(GLenum internalFormatForGL) {
mInternalFormatForGL = internalFormatForGL;
}
int64_t MemoryUsage() const;
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
void BindRenderbuffer() const;
void RenderbufferStorage(GLsizei samples, const webgl::FormatUsageInfo* format,
GLsizei width, GLsizei height);
void FramebufferRenderbuffer(GLenum attachment) const;
void RenderbufferStorage(GLsizei samples, GLenum internalFormat,
GLsizei width, GLsizei height) const;
void FramebufferRenderbuffer(FBAttachment attachment) const;
// Only handles a subset of `pname`s.
GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
@ -75,10 +78,10 @@ protected:
GLuint mPrimaryRB;
GLuint mSecondaryRB;
const webgl::FormatUsageInfo* mFormat;
GLenum mInternalFormat;
GLenum mInternalFormatForGL;
WebGLImageDataStatus mImageDataStatus;
GLsizei mSamples;
bool mIsUsingSecondary;
#ifdef ANDROID
// Bug 1140459: Some drivers (including our test slaves!) don't
// give reasonable answers for IsRenderbuffer, maybe others.
@ -90,7 +93,6 @@ protected:
friend class WebGLContext;
friend class WebGLFramebuffer;
friend class WebGLFBAttachPoint;
};
} // namespace mozilla

View File

@ -35,7 +35,7 @@ WebGLSampler::Delete()
WebGLContext*
WebGLSampler::GetParentObject() const
{
return mContext;
return Context();
}
JSObject*

View File

@ -11,7 +11,6 @@
#include "mozilla/MemoryReporting.h"
#include "nsPrintfCString.h"
#include "nsString.h"
#include "prenv.h"
#include "WebGLContext.h"
#include "WebGLObjectModel.h"
#include "WebGLShaderValidator.h"
@ -168,7 +167,7 @@ WebGLShader::ShaderSource(const nsAString& source)
// We checked that the source stripped of comments is in the
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
const NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
if (mContext->gl->WorkAroundDriverBugs()) {
const size_t maxSourceLength = 0x3ffff;
@ -180,24 +179,23 @@ WebGLShader::ShaderSource(const nsAString& source)
}
}
if (PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS")) {
printf_stderr("////////////////////////////////////////\n");
printf_stderr("// MOZ_WEBGL_DUMP_SHADERS:\n");
// Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
// internal size, so long strings are truncated.
// HACK - dump shader source
{
/*
printf_stderr("//-*- glsl -*-\n");
// Wow - Roll Your Own For Each Lines because printf_stderr has a hard-coded internal size, so long strings are truncated.
const nsString& src = shader->Source();
int32_t start = 0;
int32_t end = sourceCString.Find("\n", false, start, -1);
int32_t end = src.Find("\n", false, start, -1);
while (end > -1) {
const nsCString line(sourceCString.BeginReading() + start, end - start);
printf_stderr("%s\n", line.BeginReading());
printf_stderr("%s\n", NS_ConvertUTF16toUTF8(nsDependentSubstring(src, start, end - start)).get());
start = end + 1;
end = sourceCString.Find("\n", false, start, -1);
end = src.Find("\n", false, start, -1);
}
printf_stderr("////////////////////////////////////////\n");
printf_stderr("//\n");
*/
}
// HACK
mSource = source;
mCleanSource = sourceCString;

View File

@ -76,7 +76,7 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
void Delete();
WebGLContext* GetParentObject() const { return mContext; }
WebGLContext* GetParentObject() const { return Context(); }
virtual JSObject* WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto) override;

View File

@ -118,16 +118,16 @@ WebGLContext::CreateShaderValidator(GLenum shaderType) const
resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
resources.MaxDrawBuffers = mGLMaxDrawBuffers;
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
resources.EXT_frag_depth = 1;
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
resources.OES_standard_derivatives = 1;
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
resources.EXT_draw_buffers = 1;
if (IsWebGL2() || IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
resources.EXT_shader_texture_lod = 1;
// Tell ANGLE to allow highp in frag shaders. (unless disabled)

View File

@ -223,7 +223,6 @@ STRONG_GLENUM_BEGIN(TexImageTarget)
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Y),
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_POSITIVE_Z),
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP_NEGATIVE_Z),
STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY),
STRONG_GLENUM_END(TexImageTarget)
STRONG_GLENUM_BEGIN(TexTarget)
@ -231,7 +230,6 @@ STRONG_GLENUM_BEGIN(TexTarget)
STRONG_GLENUM_VALUE(TEXTURE_2D),
STRONG_GLENUM_VALUE(TEXTURE_3D),
STRONG_GLENUM_VALUE(TEXTURE_CUBE_MAP),
STRONG_GLENUM_VALUE(TEXTURE_2D_ARRAY),
STRONG_GLENUM_END(TexTarget)
STRONG_GLENUM_BEGIN(TexType)
@ -400,6 +398,28 @@ STRONG_GLENUM_BEGIN(RBTarget)
STRONG_GLENUM_VALUE(RENDERBUFFER),
STRONG_GLENUM_END(RBTarget)
STRONG_GLENUM_BEGIN(FBAttachment)
STRONG_GLENUM_VALUE(DEPTH_STENCIL_ATTACHMENT),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT0),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT1),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT2),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT3),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT4),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT5),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT6),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT7),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT8),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT9),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT10),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT11),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT12),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT13),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT14),
STRONG_GLENUM_VALUE(COLOR_ATTACHMENT15),
STRONG_GLENUM_VALUE(DEPTH_ATTACHMENT),
STRONG_GLENUM_VALUE(STENCIL_ATTACHMENT),
STRONG_GLENUM_END(FBAttachment)
STRONG_GLENUM_BEGIN(FBStatus)
STRONG_GLENUM_VALUE(FRAMEBUFFER_COMPLETE),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_ATTACHMENT),
@ -413,7 +433,6 @@ STRONG_GLENUM_END(FBStatus)
STRONG_GLENUM_BEGIN(RBParam)
STRONG_GLENUM_VALUE(RENDERBUFFER_WIDTH),
STRONG_GLENUM_VALUE(RENDERBUFFER_HEIGHT),
STRONG_GLENUM_VALUE(RENDERBUFFER_INTERNAL_FORMAT),
STRONG_GLENUM_VALUE(RENDERBUFFER_RED_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_GREEN_SIZE),
STRONG_GLENUM_VALUE(RENDERBUFFER_BLUE_SIZE),

View File

@ -34,7 +34,7 @@ WebGLSync::Delete()
WebGLContext*
WebGLSync::GetParentObject() const
{
return mContext;
return Context();
}
// -------------------------------------------------------------------------

View File

@ -326,73 +326,73 @@ public:
} // end anonymous namespace
bool
ConvertImage(size_t width, size_t height,
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
WebGLTexelFormat dstFormat, bool dstPremultiplied)
WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
const uint8_t* src, uint8_t* dst,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
WebGLTexelFormat dstFormat, bool dstPremultiplied,
size_t dstTexelSize)
{
if (width <= 0 || height <= 0)
return true;
const bool FormatsRequireNoPremultiplicationOp =
!HasAlpha(srcFormat) ||
!HasColor(srcFormat) ||
!HasColor(dstFormat);
if (srcFormat == dstFormat &&
(FormatsRequireNoPremultiplicationOp || srcPremultiplied == dstPremultiplied))
{
// fast exit path: we just have to memcpy all the rows.
//
// The case where absolutely nothing needs to be done is supposed to have
// been handled earlier (in TexImage2D_base, etc).
//
// So the case we're handling here is when even though no format conversion is needed,
// we still might have to flip vertically and/or to adjust to a different stride.
MOZ_ASSERT(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
const uint8_t* ptr = src;
const uint8_t* src_end = src + height * srcStride;
uint8_t* dst_row = mPixelStoreFlipY
? dst + (height-1) * dstStride
: dst;
ptrdiff_t dstStrideSigned(dstStride);
ptrdiff_t dst_delta = mPixelStoreFlipY ? -dstStrideSigned : dstStrideSigned;
while(ptr != src_end) {
memcpy(dst_row, ptr, row_size);
ptr += srcStride;
dst_row += dst_delta;
}
return true;
}
if (srcFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion ||
dstFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion)
{
return false;
}
if (!width || !height)
return true;
const bool shouldYFlip = (srcOrigin != dstOrigin);
const bool canSkipPremult = (!HasAlpha(srcFormat) ||
!HasColor(srcFormat) ||
!HasColor(dstFormat));
WebGLTexelPremultiplicationOp premultOp;
if (canSkipPremult) {
premultOp = WebGLTexelPremultiplicationOp::None;
} else if (!srcPremultiplied && dstPremultiplied) {
premultOp = WebGLTexelPremultiplicationOp::Premultiply;
} else if (srcPremultiplied && !dstPremultiplied) {
premultOp = WebGLTexelPremultiplicationOp::Unpremultiply;
} else {
premultOp = WebGLTexelPremultiplicationOp::None;
uint8_t* dstStart = dst;
ptrdiff_t signedDstStride = dstStride;
if (mPixelStoreFlipY) {
dstStart = dst + (height - 1) * dstStride;
signedDstStride = -signedDstStride;
}
const uint8_t* srcItr = (const uint8_t*)srcBegin;
const uint8_t* const srcEnd = srcItr + srcStride * height;
uint8_t* dstItr = (uint8_t*)dstBegin;
ptrdiff_t dstItrStride = dstStride;
if (shouldYFlip) {
dstItr = dstItr + dstStride * (height - 1);
dstItrStride = -dstItrStride;
}
WebGLImageConverter converter(width, height, src, dstStart, srcStride, signedDstStride);
if (srcFormat == dstFormat && premultOp == WebGLTexelPremultiplicationOp::None) {
// Fast exit path: we just have to memcpy all the rows.
//
// The case where absolutely nothing needs to be done is supposed to have
// been handled earlier (in TexImage2D_base, etc).
//
// So the case we're handling here is when even though no format conversion is
// needed, we still might have to flip vertically and/or to adjust to a different
// stride.
const WebGLTexelPremultiplicationOp premultiplicationOp
= FormatsRequireNoPremultiplicationOp ? WebGLTexelPremultiplicationOp::None
: (!srcPremultiplied && dstPremultiplied) ? WebGLTexelPremultiplicationOp::Premultiply
: (srcPremultiplied && !dstPremultiplied) ? WebGLTexelPremultiplicationOp::Unpremultiply
: WebGLTexelPremultiplicationOp::None;
MOZ_ASSERT(shouldYFlip || srcStride != dstStride,
"Performance trap -- should handle this case earlier to avoid memcpy");
const auto bytesPerPixel = TexelBytesForFormat(srcFormat);
const size_t bytesPerRow = bytesPerPixel * width;
while (srcItr != srcEnd) {
memcpy(dstItr, srcItr, bytesPerRow);
srcItr += srcStride;
dstItr += dstItrStride;
}
return true;
}
WebGLImageConverter converter(width, height, srcItr, dstItr, srcStride, dstItrStride);
converter.run(srcFormat, dstFormat, premultOp);
converter.run(srcFormat, dstFormat, premultiplicationOp);
if (!converter.Success()) {
// the dst image may be left uninitialized, so we better not try to

View File

@ -38,14 +38,6 @@
namespace mozilla {
bool ConvertImage(size_t width, size_t height,
const void* srcBegin, size_t srcStride, gl::OriginPos srcOrigin,
WebGLTexelFormat srcFormat, bool srcPremultiplied,
void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
WebGLTexelFormat dstFormat, bool dstPremultiplied);
//////////////////////////////////////////////////////////////////////////////////////////
// single precision float
// seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@
#define WEBGL_TEXTURE_H_
#include <algorithm>
#include <map>
#include "mozilla/Assertions.h"
#include "mozilla/CheckedInt.h"
@ -21,7 +20,6 @@
namespace mozilla {
class ErrorResult;
class WebGLContext;
namespace dom {
class Element;
@ -29,16 +27,18 @@ class ImageData;
class ArrayBufferViewOrSharedArrayBufferView;
} // namespace dom
namespace webgl {
class TexUnpackBlob;
} // namespace webgl
// Zero is not an integer power of two.
inline bool
IsPOTAssumingNonnegative(GLsizei x)
{
MOZ_ASSERT(x >= 0);
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
@ -46,145 +46,33 @@ class WebGLTexture final
, public WebGLRefCountedObject<WebGLTexture>
, public LinkedListElement<WebGLTexture>
, public WebGLContextBoundObject
, public WebGLFramebufferAttachable
{
// Friends
friend class WebGLContext;
friend class WebGLFramebuffer;
////////////////////////////////////
// Members
public:
const GLuint mGLName;
protected:
TexTarget mTarget;
static const uint8_t kMaxFaceCount = 6;
uint8_t mFaceCount; // 6 for cube maps, 1 otherwise.
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS, mWrapT;
bool mImmutable; // Set by texStorage*
uint8_t mImmutableLevelCount;
uint32_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
uint32_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
// You almost certainly don't want to query mMaxMipmapLevel.
// You almost certainly want MaxEffectiveMipmapLevel().
GLenum mTexCompareMode;
// Resolvable optimizations:
bool mIsResolved;
FakeBlackType mResolved_FakeBlack;
const GLint* mResolved_Swizzle; // nullptr means 'default swizzle'.
public:
class ImageInfo;
// numLevels = log2(size) + 1
// numLevels(16k) = log2(16k) + 1 = 14 + 1 = 15
// numLevels(1M) = log2(1M) + 1 = 19.9 + 1 ~= 21
// Or we can just max this out to 31, which is the number of unsigned bits in GLsizei.
static const uint8_t kMaxLevelCount = 31;
const GLuint mGLName;
// And in turn, it needs these forwards:
protected:
// We need to forward these.
void SetImageInfo(ImageInfo* target, const ImageInfo& newInfo);
void SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo);
GLenum mTarget;
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS, mWrapT;
public:
// We store information about the various images that are part of this
// texture. (cubemap faces, mipmap levels)
class ImageInfo
{
friend void WebGLTexture::SetImageInfo(ImageInfo* target,
const ImageInfo& newInfo);
friend void WebGLTexture::SetImageInfosAtLevel(uint32_t level,
const ImageInfo& newInfo);
size_t mFacesCount, mMaxLevelWithCustomImages;
nsTArray<ImageInfo> mImageInfos;
public:
static const ImageInfo kUndefined;
bool mHaveGeneratedMipmap; // Set by generateMipmap
bool mImmutable; // Set by texStorage*
// This is the "effective internal format" of the texture, an official
// OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page
// 126 and below.
const webgl::FormatUsageInfo* const mFormat;
size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0)
size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000)
const uint32_t mWidth;
const uint32_t mHeight;
const uint32_t mDepth;
WebGLTextureFakeBlackStatus mFakeBlackStatus;
protected:
bool mIsDataInitialized;
std::set<WebGLFBAttachPoint*> mAttachPoints;
public:
ImageInfo()
: mFormat(LOCAL_GL_NONE)
, mWidth(0)
, mHeight(0)
, mDepth(0)
, mIsDataInitialized(false)
{ }
ImageInfo(const webgl::FormatUsageInfo* format, uint32_t width, uint32_t height,
uint32_t depth, bool isDataInitialized)
: mFormat(format)
, mWidth(width)
, mHeight(height)
, mDepth(depth)
, mIsDataInitialized(isDataInitialized)
{
MOZ_ASSERT(mFormat);
}
void Clear();
~ImageInfo() {
if (!IsDefined())
Clear();
}
protected:
ImageInfo& operator =(const ImageInfo& a);
public:
uint32_t MaxMipmapLevels() const {
// GLES 3.0.4, 3.8 - Mipmapping: `floor(log2(largest_of_dims)) + 1`
uint32_t largest = std::max(std::max(mWidth, mHeight), mDepth);
return FloorLog2Size(largest) + 1;
}
bool IsPowerOfTwo() const;
void AddAttachPoint(WebGLFBAttachPoint* attachPoint);
void RemoveAttachPoint(WebGLFBAttachPoint* attachPoint);
void OnRespecify() const;
size_t MemoryUsage() const;
bool IsDefined() const {
if (mFormat == LOCAL_GL_NONE) {
MOZ_ASSERT(!mWidth && !mHeight && !mDepth);
return false;
}
return true;
}
bool IsDataInitialized() const { return mIsDataInitialized; }
void SetIsDataInitialized(bool isDataInitialized, WebGLTexture* tex);
};
ImageInfo mImageInfoArr[kMaxLevelCount * kMaxFaceCount];
////////////////////////////////////
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture)
@ -194,10 +82,10 @@ public:
void Delete();
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
TexTarget Target() const { return mTarget; }
GLenum Target() const { return mTarget; }
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
@ -206,7 +94,6 @@ protected:
~WebGLTexture() {
DeleteOnce();
}
public:
////////////////////////////////////
// GL calls
@ -220,129 +107,290 @@ public:
////////////////////////////////////
// WebGLTextureUpload.cpp
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferViewOrSharedArrayBufferView>& maybeView);
void CompressedTexImage2D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLint border, const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
dom::ImageData* imageData);
void CompressedTexImage3D(TexImageTarget texImageTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border, GLsizei imageSize,
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
GLint zOffset, GLenum unpackFormat, GLenum unpackType,
dom::Element* elem, ErrorResult* const out_error);
protected:
void TexOrSubImage(bool isSubImage, const char* funcName, TexImageTarget target,
GLint level, GLenum internalFormat, GLint xOffset, GLint yOffset,
GLint zOffset, GLint border, GLenum unpackFormat,
GLenum unpackType, webgl::TexUnpackBlob* blob);
void CompressedTexSubImage2D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLsizei width,
GLsizei height, GLenum unpackFormat,
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
bool ValidateTexImageSpecification(const char* funcName, TexImageTarget target,
GLint level, GLsizei width, GLsizei height,
GLsizei depth, GLint border,
WebGLTexture::ImageInfo** const out_imageInfo);
bool ValidateTexImageSelection(const char* funcName, TexImageTarget target,
GLint level, GLint xOffset, GLint yOffset,
GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth,
WebGLTexture::ImageInfo** const out_imageInfo);
void CompressedTexSubImage3D(TexImageTarget texImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum unpackFormat, GLsizei imageSize,
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
public:
void TexStorage(const char* funcName, TexTarget target, GLsizei levels,
GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth);
protected:
void TexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLint border, GLenum unpackFormat,
GLenum unpackType, webgl::TexUnpackBlob* blob);
void TexSubImage(const char* funcName, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLenum unpackFormat,
GLenum unpackType, webgl::TexUnpackBlob* blob);
public:
void CompressedTexImage(const char* funcName, TexImageTarget target, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
GLsizei depth, GLint border,
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CompressedTexSubImage(const char* funcName, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
const dom::ArrayBufferViewOrSharedArrayBufferView& view);
void CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
void CopyTexImage2D(TexImageTarget texImageTarget, GLint level, GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void CopyTexSubImage(const char* funcName, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y,
GLsizei width, GLsizei height);
////////////////////////////////////
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::ArrayBufferViewOrSharedArrayBufferView>& 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::ArrayBufferViewOrSharedArrayBufferView>& 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::ArrayBufferViewOrSharedArrayBufferView>& 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::ArrayBufferViewOrSharedArrayBufferView>& 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:
void ClampLevelBaseAndMax();
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
/** 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);
uint32_t MaxEffectiveMipmapLevel() const;
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);
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
GLenum rawTexImageTarget = texImageTarget.get();
switch (rawTexImageTarget) {
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:
return rawTexImageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level, TexInternalFormat internalFormat,
GLint xoffset, GLint yoffset, GLint x, GLint y,
GLsizei width, GLsizei height, bool isSub);
default:
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
{
public:
ImageInfo()
: mEffectiveInternalFormat(LOCAL_GL_NONE)
, mDepth(0)
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
{}
ImageInfo(GLsizei width, GLsizei height, GLsizei depth,
TexInternalFormat effectiveInternalFormat,
WebGLImageDataStatus status)
: WebGLRectangleObject(width, height)
, mEffectiveInternalFormat(effectiveInternalFormat)
, mDepth(depth)
, mImageDataStatus(status)
{
// shouldn't use this constructor to construct a null ImageInfo
MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
}
bool operator==(const ImageInfo& a) const {
return mImageDataStatus == a.mImageDataStatus &&
mWidth == a.mWidth &&
mHeight == a.mHeight &&
mDepth == a.mDepth &&
mEffectiveInternalFormat == a.mEffectiveInternalFormat;
}
bool operator!=(const ImageInfo& a) const {
return !(*this == a);
}
bool IsSquare() const {
return mWidth == mHeight;
}
bool IsPositive() const {
return mWidth > 0 && mHeight > 0 && mDepth > 0;
}
bool IsPowerOfTwo() const {
MOZ_ASSERT(mWidth >= 0);
MOZ_ASSERT(mHeight >= 0);
return IsPOTAssumingNonnegative(mWidth) &&
IsPOTAssumingNonnegative(mHeight);
}
bool HasUninitializedImageData() const {
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
}
size_t MemoryUsage() const;
TexInternalFormat EffectiveInternalFormat() const {
return mEffectiveInternalFormat;
}
GLsizei Depth() const { return mDepth; }
protected:
// This is the "effective internal format" of the texture, an official
// OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page
// 126 and below.
TexInternalFormat mEffectiveInternalFormat;
/* Used only for 3D textures.
* Note that mWidth and mHeight are inherited from WebGLRectangleObject.
* It's a pity to store a useless mDepth on non-3D texture images, but
* the size of GLsizei is negligible compared to the typical size of a texture image.
*/
GLsizei mDepth;
WebGLImageDataStatus mImageDataStatus;
friend class WebGLTexture;
};
private:
static size_t FaceForTarget(TexImageTarget texImageTarget) {
if (texImageTarget == LOCAL_GL_TEXTURE_2D ||
texImageTarget == LOCAL_GL_TEXTURE_3D)
{
return 0;
}
return texImageTarget.get() - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
}
ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) {
MOZ_ASSERT(face < mFaceCount);
MOZ_ASSERT(level < kMaxLevelCount);
size_t pos = (level * mFaceCount) + face;
return mImageInfoArr[pos];
ImageInfo& ImageInfoAtFace(size_t face, GLint level) {
MOZ_ASSERT(face < mFacesCount,
"Wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D,"
" and at most 5 for cube maps.");
// No need to check level as a wrong value would be caught by
// ElementAt().
return mImageInfos.ElementAt(level * mFacesCount + face);
}
const ImageInfo& ImageInfoAtFace(uint8_t face, uint32_t level) const {
return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level);
const ImageInfo& ImageInfoAtFace(size_t face, GLint level) const {
return const_cast<const ImageInfo&>(
const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level)
);
}
public:
ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) {
auto face = FaceForTarget(texImageTarget);
ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) {
size_t face = FaceForTarget(imageTarget);
return ImageInfoAtFace(face, level);
}
const ImageInfo& ImageInfoAt(TexImageTarget texImageTarget, GLint level) const {
return const_cast<WebGLTexture*>(this)->ImageInfoAt(texImageTarget, level);
}
void SetImageInfoAt(TexImageTarget texImageTarget, GLint level,
const ImageInfo& val)
const ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) const
{
ImageInfo* target = &ImageInfoAt(texImageTarget, level);
SetImageInfo(target, val);
return const_cast<WebGLTexture*>(this)->ImageInfoAt(imageTarget, level);
}
const ImageInfo& BaseImageInfo() const {
if (mBaseMipmapLevel >= kMaxLevelCount)
return ImageInfo::kUndefined;
bool HasImageInfoAt(TexImageTarget imageTarget, GLint level) const {
size_t face = FaceForTarget(imageTarget);
CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
return checked_index.isValid() &&
checked_index.value() < mImageInfos.Length() &&
ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
}
return ImageInfoAtFace(0, mBaseMipmapLevel);
ImageInfo& ImageInfoBase() {
return ImageInfoAtFace(0, 0);
}
const ImageInfo& ImageInfoBase() const {
return ImageInfoAtFace(0, 0);
}
size_t MemoryUsage() const;
bool InitializeImageData(const char* funcName, TexImageTarget target, uint32_t level);
void SetImageDataStatus(TexImageTarget imageTarget, GLint level,
WebGLImageDataStatus newStatus)
{
MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
// There is no way to go from having image data to not having any.
MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
if (imageInfo.mImageDataStatus != newStatus)
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
imageInfo.mImageDataStatus = newStatus;
}
bool EnsureInitializedImageData(TexImageTarget imageTarget, GLint level);
protected:
bool EnsureImageDataInitialized(const char* funcName, TexImageTarget target,
uint32_t level);
void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) {
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages,
maxLevelWithCustomImages);
mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
}
bool CheckFloatTextureFilterParams() const {
// Without OES_texture_float_linear, only NEAREST and
@ -357,7 +405,33 @@ protected:
mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
}
bool DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
public:
void Bind(TexTarget texTarget);
void SetImageInfo(TexImageTarget target, GLint level, GLsizei width,
GLsizei height, GLsizei depth, TexInternalFormat format,
WebGLImageDataStatus status);
void SetMinFilter(TexMinFilter minFilter) {
mMinFilter = minFilter;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}
void SetMagFilter(TexMagFilter magFilter) {
mMagFilter = magFilter;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}
void SetWrapS(TexWrap wrapS) {
mWrapS = wrapS;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}
void SetWrapT(TexWrap wrapT) {
mWrapT = wrapT;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}
TexMinFilter MinFilter() const { return mMinFilter; }
bool DoesMinFilterRequireMipmap() const {
return !(mMinFilter == LOCAL_GL_NEAREST ||
mMinFilter == LOCAL_GL_LINEAR);
@ -367,31 +441,51 @@ public:
void SetCustomMipmap();
bool IsFirstImagePowerOfTwo() const {
return ImageInfoBase().IsPowerOfTwo();
}
bool AreAllLevel0ImageInfosEqual() const;
bool IsMipmapComplete() const;
bool IsCubeComplete() const;
bool IsComplete(const char** const out_reason) const;
bool IsMipmapCubeComplete() const;
bool IsCubeMap() const { return (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); }
void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x);
// Resolve cache optimizations
protected:
bool GetFakeBlackType(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack);
public:
bool ResolveForDraw(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack);
bool IsImmutable() const { return mImmutable; }
void SetImmutable() { mImmutable = true; }
void InvalidateResolveCache() { mIsResolved = false; }
void SetBaseMipmapLevel(size_t level) { mBaseMipmapLevel = level; }
void SetMaxMipmapLevel(size_t level) { mMaxMipmapLevel = level; }
// Clamping (from ES 3.0.4, section 3.8 - Texturing). When not immutable,
// the ranges must be guarded.
size_t EffectiveBaseMipmapLevel() const {
if (IsImmutable())
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
return mBaseMipmapLevel;
}
size_t EffectiveMaxMipmapLevel() const {
if (IsImmutable()) {
return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(),
mMaxLevelWithCustomImages);
}
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
}
bool IsMipmapRangeValid() const;
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
// Returns the current fake-black-status, except if it was Unknown,
// in which case this function resolves it first, so it never returns Unknown.
WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
};
inline TexImageTarget
TexImageTargetForTargetAndFace(TexTarget target, uint8_t face)
TexImageTargetForTargetAndFace(TexTarget target, size_t face)
{
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D:
@ -406,23 +500,6 @@ TexImageTargetForTargetAndFace(TexTarget target, uint8_t face)
}
}
already_AddRefed<mozilla::layers::Image>
ImageFromVideo(dom::HTMLVideoElement* elem);
GLenum
DoTexImage(gl::GLContext* gl, TexImageTarget target, GLint level,
const webgl::DriverUnpackInfo* dui, GLsizei width, GLsizei height,
GLsizei depth, const void* data);
GLenum
DoTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level, GLint xOffset,
GLint yOffset, GLint zOffset, GLsizei width, GLsizei height,
GLsizei depth, const webgl::PackingInfo& pi, const void* data);
GLenum
DoCompressedTexSubImage(gl::GLContext* gl, TexImageTarget target, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset, GLsizei width,
GLsizei height, GLsizei depth, GLenum sizedUnpackFormat,
GLsizei dataSize, const void* data);
} // namespace mozilla
#endif // WEBGL_TEXTURE_H_

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ WebGLTimerQuery::Delete()
WebGLContext*
WebGLTimerQuery::GetParentObject() const
{
return mContext;
return Context();
}

View File

@ -41,7 +41,7 @@ WebGLTransformFeedback::Delete()
WebGLContext*
WebGLTransformFeedback::GetParentObject() const
{
return mContext;
return Context();
}
JSObject*

View File

@ -18,10 +18,12 @@ typedef bool WebGLboolean;
namespace mozilla {
/*
* WebGLTextureFakeBlackStatus is an enum to track what needs to use a dummy 1x1 black
* texture, which we refer to as a 'fake black' texture.
* WebGLContextFakeBlackStatus and WebGLTextureFakeBlackStatus are enums to
* track what needs to use a dummy 1x1 black texture, which we refer to as a
* 'fake black' texture.
*
* There are two things that can cause us to use such 'fake black' textures:
* There are generally two things that can cause us to use such 'fake black'
* textures:
*
* (1) OpenGL ES rules on sampling incomplete textures specify that they
* must be sampled as RGBA(0, 0, 0, 1) (opaque black). We have to implement these rules
@ -36,12 +38,23 @@ namespace mozilla {
* uninitialized image data must be exposed to WebGL as if it were filled
* with zero bytes, which means it's either opaque or transparent black
* depending on whether the image format has alpha.
*
* Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
* and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
*/
enum class WebGLContextFakeBlackStatus : uint8_t {
Unknown,
NotNeeded,
Needed
};
enum class FakeBlackType : uint8_t {
None,
RGBA0001, // Incomplete textures and uninitialized no-alpha color textures.
RGBA0000, // Uninitialized with-alpha color textures.
enum class WebGLTextureFakeBlackStatus : uint8_t {
Unknown,
NotNeeded,
IncompleteTexture,
UninitializedImageData
};
/*
@ -102,7 +115,6 @@ enum class WebGLTexelFormat : uint8_t {
RA32F, // OES_texture_float
// 3-channel formats
RGB8,
RGBX8, // used for DOM elements. Source format only.
BGRX8, // used for DOM elements. Source format only.
RGB565,
RGB16F, // OES_texture_half_float

View File

@ -47,7 +47,7 @@ public:
bool IsVertexArray();
WebGLContext* GetParentObject() const {
return mContext;
return Context();
}
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;

View File

@ -54,7 +54,6 @@ UNIFIED_SOURCES += [
# WebGL Sources
UNIFIED_SOURCES += [
'MurmurHash3.cpp',
'TexUnpackBlob.cpp',
'WebGL1Context.cpp',
'WebGL1ContextBuffers.cpp',
'WebGL1ContextUniforms.cpp',

View File

@ -78,27 +78,26 @@ function expectResult(target, successMessage, failureMessage) {
}
}
function createGreySRGBATexture(gl, color) {
function createGreysRGBTexture(gl, color) {
var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight;
var size = numPixels * 4;
var size = numPixels * 3;
var buf = new Uint8Array(size);
for (var ii = 0; ii < numPixels; ++ii) {
var off = ii * 3;
buf[off + 0] = color;
buf[off + 1] = color;
buf[off + 2] = color;
buf[off + 3] = 0xff;
}
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D,
0,
ext.SRGB_ALPHA_EXT,
ext.SRGB_EXT,
gl.drawingBufferWidth,
gl.drawingBufferHeight,
0,
ext.SRGB_ALPHA_EXT,
ext.SRGB_EXT,
gl.UNSIGNED_BYTE,
buf);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
@ -267,11 +266,11 @@ function runTextureReadConversionTest() {
gl.uniform1i(gl.getUniformLocation(program, "tex2d"), 0);
for (var ii = 0; ii < conversions.length; ii++) {
var tex = createGreySRGBATexture(gl, conversions[ii][0]);
var tex = createGreysRGBTexture(gl, conversions[ii][0]);
wtu.drawQuad(gl);
expectResult(conversions[ii][1],
"sRGBA texture read returned correct data",
"sRGBA texture read returned incorrect data");
"sRGB texture read returned correct data",
"sRGB texture read returned incorrect data");
}
}
@ -280,14 +279,13 @@ function runFramebufferTextureConversionTest() {
debug("Test the conversion of colors from linear to sRGB on framebuffer (texture) write");
var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]);
var tex = createGreySRGBATexture(gl, 0);
var tex = createGreysRGBTexture(gl, 0);
var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Draw
@ -309,7 +307,6 @@ function runFramebufferTextureConversionTest() {
"framebuffer (texture) read returned incorrect data");
}
glErrorShouldBe(gl, gl.NO_ERROR);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
@ -330,7 +327,6 @@ function runFramebufferRenderbufferConversionTest() {
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT');
glErrorShouldBe(gl, gl.NO_ERROR);
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
return fbo;
@ -356,8 +352,6 @@ function runFramebufferRenderbufferConversionTest() {
"framebuffer (renderbuffer) read returned the correct data",
"framebuffer (renderbuffer) read returned incorrect data");
}
glErrorShouldBe(gl, gl.NO_ERROR);
}
debug("");

View File

@ -131,8 +131,7 @@ function runTextureCreationTest(testProgram, extensionEnabled)
}
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, data);
if (expectFailure) {
wtu.glErrorShouldBeIn(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION],
"floating-point texture allocation must be disallowed if OES_texture_float isn't enabled");
glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point texture allocation must be disallowed if OES_texture_float isn't enabled");
return;
} else {
glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled");

View File

@ -76,7 +76,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
// Deleting a texture bound to the currently-bound fbo is the same as
// detaching the textue from fbo first, then delete the texture.
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "null");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldBeFalse("gl.isTexture(tex)");
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
@ -128,7 +128,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
// Deleting a renderbuffer bound to the currently-bound fbo is the same as
// detaching the renderbuffer from fbo first, then delete the renderbuffer.
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "null");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldBeFalse("gl.isRenderbuffer(rbo)");
shouldBeNull("gl.getParameter(gl.RENDERBUFFER_BINDING)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
@ -263,7 +263,7 @@ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
shouldNotBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");

View File

@ -58,53 +58,53 @@ function teardown(gl, tex) {
gl.deleteTexture(tex);
}
function testrunner(gl, expectedList, desc, fn) {
function testrunner(gl, expected, desc, fn) {
var tex = setup(gl);
fn();
wtu.glErrorShouldBeIn(gl, expectedList, desc);
glErrorShouldBe(gl, expected, desc);
teardown(gl, tex);
}
var data = new Uint8Array(4);
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,1,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
});
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,2,0,gl.RGBA,gl.UNSIGNED_BYTE, data);
});
testrunner(gl, [gl.INVALID_ENUM], "bad target", function(){
testrunner(gl, gl.INVALID_ENUM, "bad target", function(){
gl.texImage2D(gl.FLOAT, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_ENUM, gl.INVALID_VALUE], "bad internal format/format", function(){
testrunner(gl, gl.INVALID_ENUM, "bad internal format/format", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.FLOAT, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_VALUE], "border > 0", function(){
testrunner(gl, gl.INVALID_VALUE, "border > 0", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,48,gl.RGBA,gl.UNSIGNED_BYTE, null);
});
// The spec says zero size is OK. If you disagree please list the section
// in the spec that details this issue.
testrunner(gl, [gl.NO_ERROR], "zero size", function(){
testrunner(gl, gl.NO_ERROR, "zero size", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0,0,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_VALUE], "negative width", function(){
testrunner(gl, gl.INVALID_VALUE, "negative width", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, -1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_VALUE], "negative height", function(){
testrunner(gl, gl.INVALID_VALUE, "negative height", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,-1,0,gl.RGBA,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], "bad format", function(){
testrunner(gl, gl.INVALID_ENUM, "bad format", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.FLOAT,gl.UNSIGNED_BYTE, null);
});
testrunner(gl, [gl.INVALID_ENUM], "bad type", function(){
testrunner(gl, gl.INVALID_ENUM, "bad type", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.TEXTURE_2D, null);
});
testrunner(gl, [gl.INVALID_OPERATION], "not enough data", function(){
testrunner(gl, gl.INVALID_OPERATION, "not enough data", function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array(3));
});
testrunner(gl, [gl.INVALID_OPERATION], "format and type incompatible",function(){
testrunner(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1,0,gl.RGBA,gl.UNSIGNED_SHORT_5_6_5, null);
});
testrunner(gl, [gl.INVALID_OPERATION], "format and type incompatible",function(){
testrunner(gl, gl.INVALID_OPERATION, "format and type incompatible",function(){
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1,1,0,gl.RGB,gl.UNSIGNED_SHORT_4_4_4_4, null);
});

View File

@ -31,7 +31,6 @@ OTHER DEALINGS IN THE SOFTWARE.
<link rel="stylesheet" type="text/css" href="../unit.css" />
<script type="application/x-javascript" src="../unit.js"></script>
<script type="application/x-javascript" src="../util.js"></script>
<script src="../../resources/webgl-test-utils.js"></script>
<script type="application/x-javascript">
Tests.startUnit = function () {
@ -52,7 +51,7 @@ Tests.teardown = function(gl,tex) {
}
Tests.testTexImage2D = function(gl) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]));
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2,2,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]));
assertGLError(gl, gl.INVALID_OPERATION, "not enough data", function(){
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 2,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
});
@ -71,10 +70,10 @@ Tests.testTexImage2D = function(gl) {
assertOk("zero size", function(){
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 0,0,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
});
assertGLError(gl, gl.INVALID_VALUE, "negative width", function(){
assertSomeGLError(gl, "negative width", function(){
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, -1,1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
});
assertGLError(gl, gl.INVALID_VALUE, "negative height", function(){
assertSomeGLError(gl, "negative height", function(){
gl.texSubImage2D(gl.TEXTURE_2D, 0,0, 0, 1,-1,gl.RGBA,gl.UNSIGNED_BYTE, new Uint8Array([0,0,0,0]));
});
assertGLError(gl, gl.INVALID_VALUE, "negative x", function(){

View File

@ -1001,11 +1001,12 @@ function wrapGLContext(gl) {
// Assert that f generates a specific GL error.
function assertGLError(gl, err, name, f) {
if (f == null) { f = name; name = null; }
var r = false;
var glErr = 0;
try { f(); } catch(e) { glErr = e.glError; }
try { f(); } catch(e) { r=true; glErr = e.glError; }
if (glErr !== err) {
if (glErr === undefined) {
testFailed("assertGLError: UNEXPECTED EXCEPTION", name, f);
testFailed("assertGLError: UNEXPCETED EXCEPTION", name, f);
} else {
testFailed("assertGLError: expected: " + getGLErrorAsString(gl, err) +
" actual: " + getGLErrorAsString(gl, glErr), name, f);
@ -1015,40 +1016,6 @@ function assertGLError(gl, err, name, f) {
return true;
}
// Assert that f generates a specific GL error.
function assertGLErrorIn(gl, expectedErrorList, name, f) {
if (f == null) { f = name; name = null; }
var actualError = 0;
try {
f();
} catch(e) {
if ('glError' in e) {
actualError = e.glError;
} else {
testFailed("assertGLErrorIn: UNEXPECTED EXCEPTION", name, f);
return false;
}
}
var expectedErrorStrList = [];
var expectedErrorSet = {};
for (var i in expectedErrorList) {
var cur = expectedErrorList[i];
expectedErrorSet[cur] = true;
expectedErrorStrList.push(getGLErrorAsString(gl, cur));
}
var expectedErrorListStr = "[" + expectedErrorStrList.join(", ") + "]";
if (actualError in expectedErrorSet) {
return true;
}
testFailed("assertGLErrorIn: expected: " + expectedErrorListStr +
" actual: " + getGLErrorAsString(gl, actualError), name, f);
return false;
}
// Assert that f generates some GL error. Used in situations where it's
// ambigious which of multiple possible errors will be generated.
function assertSomeGLError(gl, name, f) {

View File

@ -132,17 +132,16 @@ if (!gl) {
glErrorShouldBe(gl, gl.INVALID_ENUM,
"calling framebufferRenderbuffer with attachment = COLOR_ATTACHMENT1 should generate INVALID_ENUM.");
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
glErrorShouldBe(gl, gl.NO_ERROR,
"attaching a texture to a framebuffer should succeed.");
// Must have a valid attachment, otherwise may also generate INVALID_OPERATION.
gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER,
gl.COLOR_ATTACHMENT0,
desktopGL.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
glErrorShouldBe(gl, gl.INVALID_ENUM,
"calling getFramebufferAttachmentParameter with pname = GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING should generate INVALID_ENUM.");
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);
glErrorShouldBe(gl, gl.NO_ERROR,
"attaching a texture to a framebuffer should succeed.");
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
glErrorShouldBe(gl, gl.NO_ERROR,
"detaching a texture from a framebuffer should succeed.");

View File

@ -634,6 +634,31 @@ function create3DContextWithWrapperThatThrowsOnGLError(canvas) {
return wrap;
};
/**
* Tests that an evaluated expression generates a specific GL error.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {number} glError The expected gl error.
* @param {string} evalSTr The string to evaluate.
*/
var shouldGenerateGLError = function(gl, glError, evalStr) {
var exception;
try {
eval(evalStr);
} catch (e) {
exception = e;
}
if (exception) {
testFailed(evalStr + " threw exception " + exception);
} else {
var err = gl.getError();
if (err != glError) {
testFailed(evalStr + " expected: " + getGLErrorAsString(gl, glError) + ". Was " + getGLErrorAsString(gl, err) + ".");
} else {
testPassed(evalStr + " was expected value: " + getGLErrorAsString(gl, glError) + ".");
}
}
};
/**
* Tests that the first error GL returns is the specified error.
* @param {!WebGLContext} gl The WebGLContext to use.
@ -652,84 +677,6 @@ var glErrorShouldBe = function(gl, glError, opt_msg) {
}
};
/**
* Tests that the first error GL returns is in the specified error list.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {!Array.<number>} expectedErrorList The list of expected gl errors.
* @param {string} opt_msg
*/
var glErrorShouldBeIn = function(gl, expectedErrorList, opt_msg) {
opt_msg = opt_msg || "";
var expectedErrorStrList = [];
var expectedErrorSet = {};
for (var i in expectedErrorList) {
var cur = expectedErrorList[i];
expectedErrorStrList.push(getGLErrorAsString(gl, cur));
expectedErrorSet[cur] = true;
}
var expectedErrorStr = "[" + expectedErrorStrList.join(", ") + "]";
var actualError = gl.getError();
if (actualError in expectedErrorSet) {
testPassed("getError was in expected values: " + expectedErrorStr + " : " + opt_msg);
} else {
testFailed("getError expected: " + expectedErrorStr +
". Was " + getGLErrorAsString(gl, actualError) + " : " + opt_msg);
}
};
/**
* Tests that an evaluated expression generates a specific GL error.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {number} glError The expected gl error.
* @param {string} evalSTr The string to evaluate.
*/
var shouldGenerateGLError = function(gl, glError, evalStr) {
glErrorShouldBe(gl, 0,
"Should not be pre-existing errors during call to"
+ " shouldGenerateGLError().");
var exception;
try {
eval(evalStr);
} catch (e) {
exception = e;
}
if (exception) {
testFailed(evalStr + " threw exception " + exception);
} else {
glErrorShouldBe(gl, glError, evalStr);
}
};
/**
* Tests that an evaluated expression generates a GL error from a list.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {!Array.<number>} expectedErrorList The list of expected gl errors.
* @param {string} evalSTr The string to evaluate.
*/
var shouldGenerateGLErrorIn = function(gl, expectedErrorList, evalStr) {
glErrorShouldBe(gl, 0,
"Should not be pre-existing errors during call to"
+ " shouldGenerateGLErrorIn().");
var exception;
try {
eval(evalStr);
} catch (e) {
exception = e;
}
if (exception) {
testFailed(evalStr + " threw exception " + exception);
} else {
glErrorShouldBeIn(gl, expectedErrorList, evalStr);
}
};
/**
* Links a WebGL program, throws if there are errors.
* @param {!WebGLContext} gl The WebGLContext to use.
@ -1418,7 +1365,6 @@ return {
getUrlArguments: getUrlArguments,
glEnumToString: glEnumToString,
glErrorShouldBe: glErrorShouldBe,
glErrorShouldBeIn: glErrorShouldBeIn,
fillTexture: fillTexture,
insertImage: insertImage,
loadImageAsync: loadImageAsync,

View File

@ -39,8 +39,8 @@ function testTexImage2D(testCase)
" border: " + testCase.border;
gl.texImage2D(testCase.target, level, testCase.internalFormat, width, height, testCase.border, testCase.format, testCase.type, null);
errors = testCase.expectedErrors;
wtu.glErrorShouldBeIn(gl, errors, msg);
error = testCase.expectedError;
glErrorShouldBe(gl, error, msg);
}
function testTexSubImage2D(testCase)
@ -55,26 +55,26 @@ function testTexSubImage2D(testCase)
" type: " + enumToString(testCase.type);
var array = new Uint8Array(width * height * 4);
gl.texSubImage2D(testCase.target, level, xoffset, yoffset, width, height, testCase.format, testCase.type, array);
errors = testCase.expectedErrors;
wtu.glErrorShouldBeIn(gl, errors, msg);
error = testCase.expectedError;
glErrorShouldBe(gl, error, msg);
}
function testTexParameter(testCase)
{
var msg = "paramName: " + enumToString(testCase.pname);
errors = testCase.expectedErrors;
error = testCase.expectedError;
gl.texParameteri(testCase.target, testCase.pname, testCase.param);
wtu.glErrorShouldBeIn(gl, errors, msg);
glErrorShouldBe(gl, error, msg);
gl.texParameterf(testCase.target, testCase.pname, testCase.param);
wtu.glErrorShouldBeIn(gl, errors, msg);
glErrorShouldBe(gl, error, msg);
}
function testGetTexParameter(testCase)
{
var msg = "paramName: " + enumToString(testCase.pname);
errors = testCase.expectedErrors;
error = testCase.expectedError;
gl.getTexParameter(testCase.target, testCase.pname);
wtu.glErrorShouldBeIn(gl, errors, msg);
glErrorShouldBe(gl, error, msg);
}
function testCopyTexImage2D(testCase)
@ -96,8 +96,8 @@ function testCopyTexImage2D(testCase)
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
gl.copyTexImage2D(testCase.target, level, testCase.internalFormat, x, y, width, height, testCase.border);
errors = testCase.expectedErrors;
wtu.glErrorShouldBeIn(gl, errors, msg);
error = testCase.expectedError;
glErrorShouldBe(gl, error, msg);
}
function testCopyTexSubImage2D(testCase)
@ -124,8 +124,8 @@ function testCopyTexSubImage2D(testCase)
glErrorShouldBe(gl, gl.NO_ERROR);
gl.copyTexSubImage2D(testCase.target, level, xoffset, yoffset, x, y, width, height);
errors = testCase.expectedErrors;
wtu.glErrorShouldBeIn(gl, errors, msg);
error = testCase.expectedError;
glErrorShouldBe(gl, error, msg);
}
function testCopyFromInternalFBO(testCase)
@ -159,8 +159,8 @@ function testCopyFromInternalFBO(testCase)
glErrorShouldBe(gl, gl.NO_ERROR);
gl.copyTexImage2D(target, level, testCase.internalFormat, x, y, width, height, border);
}
errors = testCase.expectedErrors;
wtu.glErrorShouldBeIn(gl, errors, msg);
error = testCase.expectedError;
glErrorShouldBe(gl, error, msg);
}
description("Validate tex functions input parameters");
@ -179,37 +179,37 @@ var testCases =
border: 0,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
internalFormat: 0x1903, // GL_RED
border: 0,
format: 0x1903, // GL_RED
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_VALUE]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
internalFormat: gl.RGBA,
border: 1,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.INVALID_VALUE]},
expectedError: gl.INVALID_VALUE},
{target: gl.TEXTURE_2D,
internalFormat: gl.RGBA,
border: 0,
format: gl.RGB,
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.INVALID_OPERATION]},
expectedError: gl.INVALID_OPERATION},
{target: gl.TEXTURE_2D,
internalFormat: gl.RGBA,
border: 0,
format: gl.RGBA,
type: gl.BYTE,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
internalFormat: gl.RGBA,
border: 0,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.NO_ERROR]} ];
expectedError: gl.NO_ERROR} ];
for (var ii = 0; ii < testCases.length; ++ii)
testTexImage2D(testCases[ii]);
@ -221,15 +221,15 @@ testCases =
[ {target: gl.TEXTURE_2D,
format: 0x1903, // GL_RED
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_OPERATION]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
format: gl.RGBA,
type: gl.BYTE,
expectedErrors: [gl.INVALID_ENUM, gl.INVALID_OPERATION]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
format: gl.RGBA,
type: gl.UNSIGNED_BYTE,
expectedErrors: [gl.NO_ERROR]} ];
expectedError: gl.NO_ERROR} ];
for (var ii = 0; ii < testCases.length; ++ii)
testTexSubImage2D(testCases[ii]);
@ -241,19 +241,19 @@ testCases =
[ {target: 0x0DE0, // GL_TEXTURE_1D
pname: gl.TEXTURE_WRAP_T,
param: gl.REPEAT,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
pname: 0x813A, // GL_TEXTURE_MIN_LOD
param: 0,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
pname: gl.TEXTURE_WRAP_T,
param: 0x2900, // GL_CLAMP
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
pname: gl.TEXTURE_WRAP_T,
param: gl.REPEAT,
expectedErrors: [gl.NO_ERROR]} ];
expectedError: gl.NO_ERROR} ];
for (var ii = 0; ii < testCases.length; ++ii)
testTexParameter(testCases[ii]);
@ -264,13 +264,13 @@ debug("Checking GetTexParameter: a set of inputs that are valid in GL but invali
testCases =
[ {target: 0x0DE0, // GL_TEXTURE_1D
pname: gl.TEXTURE_WRAP_T,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
pname: 0x813A, // GL_TEXTURE_MIN_LOD
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
pname: gl.TEXTURE_WRAP_T,
expectedErrors: [gl.NO_ERROR]} ];
expectedError: gl.NO_ERROR} ];
for (var ii = 0; ii < testCases.length; ++ii)
testGetTexParameter(testCases[ii]);
@ -293,22 +293,22 @@ testCases =
colorBufferFormat: gl.RGB565,
internalFormat: 0x8054, // GL_RGB16
border: 0,
expectedErrors: [gl.INVALID_ENUM]},
expectedError: gl.INVALID_ENUM},
{target: gl.TEXTURE_2D,
colorBufferFormat: gl.RGB565,
internalFormat: gl.RGBA,
border: 1,
expectedErrors: [gl.INVALID_VALUE]},
expectedError: gl.INVALID_VALUE},
{target: gl.TEXTURE_2D,
colorBufferFormat: gl.RGB565,
internalFormat: gl.RGBA,
border: 0,
expectedErrors: [gl.INVALID_OPERATION]},
expectedError: gl.INVALID_OPERATION},
{target: gl.TEXTURE_2D,
colorBufferFormat: gl.RGB565,
internalFormat: gl.RGB,
border: 0,
expectedErrors: [gl.NO_ERROR]} ];
expectedError: gl.NO_ERROR} ];
for (var ii = 0; ii < testCases.length; ++ii)
testCopyTexImage2D(testCases[ii]);
@ -320,11 +320,11 @@ testCases =
[ {target: gl.TEXTURE_2D,
colorBufferFormat: gl.RGB5_A1,
internalFormat: gl.RGBA,
expectedErrors: [gl.NO_ERROR]},
expectedError: gl.NO_ERROR},
{target: gl.TEXTURE_2D,
colorBufferFormat: gl.RGB565,
internalFormat: gl.RGBA,
expectedErrors: [gl.INVALID_OPERATION]} ];
expectedError: gl.INVALID_OPERATION} ];
for (var ii = 0; ii < testCases.length; ++ii)
testCopyTexSubImage2D(testCases[ii]);
@ -336,19 +336,19 @@ testCases =
[ {contextAlpha: true,
internalFormat: gl.RGBA,
subImage: false,
expectedErrors: [gl.NO_ERROR]},
expectedError: gl.NO_ERROR},
{contextAlpha: false,
internalFormat: gl.RGBA,
subImage: false,
expectedErrors: [gl.INVALID_OPERATION]},
expectedError: gl.INVALID_OPERATION},
{contextAlpha: true,
internalFormat: gl.RGBA,
subImage: true,
expectedErrors: [gl.NO_ERROR]},
expectedError: gl.NO_ERROR},
{contextAlpha: false,
internalFormat: gl.RGBA,
subImage: true,
expectedErrors: [gl.INVALID_OPERATION]} ];
expectedError: gl.INVALID_OPERATION} ];
for (var ii = 0; ii < testCases.length; ++ii)
testCopyFromInternalFBO(testCases[ii]);

View File

@ -66,9 +66,9 @@ if (!gl) {
var err = gl.getError();
if (err == gl.NO_ERROR) {
testFailed("should NOT be able to create texture of type " + formatName);
} else if (err == gl.INVALID_ENUM ||
err == gl.INVALID_OPERATION)
{
} else if (err == gl.INVALID_OPERATION) {
testFailed("should return gl.INVALID_ENUM for type " + formatName);
} else if (err == gl.INVALID_ENUM) {
testPassed("not able to create invalid format: " + formatName);
}
}

View File

@ -35,10 +35,10 @@ function IsFormatValidForTex(gl, format, type) {
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
var error = gl.getError();
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
return error == gl.NO_ERROR;
}
@ -50,10 +50,10 @@ function IsFormatValidForTexFB(gl, format, type) {
gl.texImage2D(gl.TEXTURE_2D, 0, format, 4, 4, 0, format, type, null);
var error = gl.getError();
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
@ -75,10 +75,10 @@ function IsFormatValidForTexFBRead(gl, texFormat, texType, readType) {
null);
var error = gl.getError();
if (error == gl.INVALID_ENUM || error == gl.INVALID_OPERATION)
if (error == gl.INVALID_ENUM)
return false;
ok(error == gl.NO_ERROR, 'Error should be INVALID_{ENUM,OPERATION} or NO_ERROR.');
ok(error == gl.NO_ERROR, 'Error should be INVALID_ENUM or NO_ERROR.');
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

View File

@ -478,8 +478,7 @@ skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_compressedTexImage2D.html]
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_compressedTexSubImage2D.html]
skip-if = true # Bug 1226336
#skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_texImage2D.html]
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_texSubImage2D.html]

View File

@ -344,40 +344,30 @@ interface WebGL2RenderingContext : WebGLRenderingContext
void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
GLsizei depth);
void texImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width,
GLsizei height, GLsizei depth, GLint border, GLenum format,
[Throws]
void texImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format,
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] // Can't actually throw.
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
(ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] // Can't actually throw.
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLenum format, GLenum type, ImageData? data);
[Throws]
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLenum format, GLenum type, HTMLImageElement image);
[Throws]
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLenum format, GLenum type,
HTMLCanvasElement canvas);
[Throws]
void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLenum format, GLenum type, HTMLVideoElement video);
void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLint x, GLint y, GLsizei width,
GLsizei height);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
(ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, ImageData? data);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, HTMLImageElement image);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, HTMLCanvasElement canvas);
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, HTMLVideoElement video);
void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height);
void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth, GLint border,
(ArrayBufferView or SharedArrayBufferView) data);
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLint zoffset, GLsizei width, GLsizei height,
GLsizei depth, GLenum format,
(ArrayBufferView or SharedArrayBufferView) data);
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, (ArrayBufferView or SharedArrayBufferView) data);
/* Programs and shaders */
[WebGLHandlesContextLoss] GLint getFragDataLocation(WebGLProgram? program, DOMString name);

View File

@ -694,12 +694,11 @@ interface WebGLRenderingContext {
void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
// Overloads must share [Throws].
[Throws] // Can't actually throw.
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border, GLenum format,
GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] // Can't actually throw.
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLenum format, GLenum type, ImageData? pixels);
[Throws]
@ -715,11 +714,11 @@ interface WebGLRenderingContext {
void texParameterf(GLenum target, GLenum pname, GLfloat param);
void texParameteri(GLenum target, GLenum pname, GLint param);
[Throws] // Can't actually throw.
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLenum type,
(ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws] // Can't actually throw.
GLsizei width, GLsizei height,
GLenum format, GLenum type, (ArrayBufferView or SharedArrayBufferView)? pixels);
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, ImageData? pixels);
[Throws]

View File

@ -89,7 +89,7 @@ struct DrawOptions {
operation is multiplied. */
CompositionOp mCompositionOp; /**< The operator that indicates how the source and
destination patterns are blended. */
AntialiasMode mAntialiasMode; /**< The AntiAlias mode used for this drawing
AntialiasMode mAntialiasMode; /**< The AntiAlias mode used for this drawing
operation. */
};
@ -415,25 +415,25 @@ public:
}
}
uint8_t* GetData() const
uint8_t* GetData()
{
MOZ_ASSERT(mIsMapped);
return mMap.mData;
}
int32_t GetStride() const
int32_t GetStride()
{
MOZ_ASSERT(mIsMapped);
return mMap.mStride;
}
const MappedSurface* GetMappedSurface() const
MappedSurface* GetMappedSurface()
{
MOZ_ASSERT(mIsMapped);
return &mMap;
}
bool IsMapped() const { return mIsMapped; }
bool IsMapped() { return mIsMapped; }
private:
RefPtr<DataSourceSurface> mSurface;
@ -527,7 +527,7 @@ class Path : public RefCounted<Path>
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(Path)
virtual ~Path();
virtual BackendType GetBackendType() const = 0;
/** This returns a PathBuilder object that contains a copy of the contents of
@ -803,7 +803,7 @@ public:
/** @see CopySurface
* Same as CopySurface, except uses itself as the source.
*
*
* Some backends may be able to optimize this better
* than just taking a snapshot and using CopySurface.
*/
@ -863,7 +863,7 @@ public:
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions = StrokeOptions(),
const DrawOptions &aOptions = DrawOptions()) = 0;
/**
* Fill a path on the draw target with a certain source pattern.
*
@ -968,7 +968,7 @@ public:
* Create a DrawTarget that captures the drawing commands and can be replayed
* onto a compatible DrawTarget afterwards.
*
* @param aSize Size of the area this DT will capture.
* @param aSize Size of the area this DT will capture.
*/
virtual already_AddRefed<DrawTargetCapture> CreateCaptureDT(const IntSize& aSize);
@ -1170,7 +1170,7 @@ public:
static already_AddRefed<DrawTarget>
CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
static already_AddRefed<DrawTarget>
CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);

View File

@ -17,7 +17,7 @@ namespace gfx {
uint8_t*
DataAtOffset(DataSourceSurface* aSurface,
const DataSourceSurface::MappedSurface* aMap,
DataSourceSurface::MappedSurface* aMap,
IntPoint aPoint)
{
if (!SurfaceContainsPoint(aSurface, aPoint)) {

View File

@ -874,8 +874,11 @@ Factory::CreateWrappingDataSourceSurface(uint8_t *aData, int32_t aStride,
RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData();
newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false);
return newSurf.forget();
if (newSurf->InitWrappingData(aData, aSize, aStride, aFormat, false)) {
return newSurf.forget();
}
return nullptr;
}
already_AddRefed<DataSourceSurface>

View File

@ -12,7 +12,7 @@
namespace mozilla {
namespace gfx {
void
bool
SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
const IntSize &aSize,
int32_t aStride,
@ -24,6 +24,8 @@ SourceSurfaceRawData::InitWrappingData(uint8_t *aData,
mStride = aStride;
mFormat = aFormat;
mOwnData = aOwnData;
return true;
}
void

View File

@ -33,7 +33,7 @@ public:
virtual IntSize GetSize() const override { return mSize; }
virtual SurfaceFormat GetFormat() const override { return mFormat; }
void InitWrappingData(unsigned char *aData,
bool InitWrappingData(unsigned char *aData,
const IntSize &aSize,
int32_t aStride,
SurfaceFormat aFormat,

View File

@ -42,7 +42,6 @@ EXPORTS.mozilla.gfx += [
'ScaleFactor.h',
'ScaleFactors2D.h',
'SourceSurfaceCairo.h',
'SourceSurfaceRawData.h',
'StackArray.h',
'Tools.h',
'Types.h',

View File

@ -141,9 +141,6 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const
bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
{
if (image->isDirty())
return false;
if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
{
return false;

View File

@ -505,13 +505,6 @@ gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
return gl::Error(GL_NO_ERROR);
}
static bool
IsEmpty(const RECT& rect)
{
return rect.left == rect.right ||
rect.top == rect.bottom;
}
gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture)
{
ASSERT(surface);
@ -523,10 +516,7 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
// Copy the render target into a texture
IDirect3DTexture9 *texture;
HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left,
sourceRect.bottom - sourceRect.top, 1,
D3DUSAGE_RENDERTARGET, sourceDesc.Format,
D3DPOOL_DEFAULT, &texture, NULL);
HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
if (FAILED(result))
{
@ -544,82 +534,13 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
}
D3DSURFACE_DESC destDesc;
textureSurface->GetDesc(&destDesc);
RECT subsetSourceRect = sourceRect;
RECT subsetDestRect = { 0, 0, destDesc.Width, destDesc.Height };
if (sourceRect.left < 0) {
LONG diff = 0 - sourceRect.left;
ASSERT(diff > 0);
subsetSourceRect.left += diff;
subsetDestRect.left += diff;
}
if (sourceRect.top < 0) {
LONG diff = 0 - sourceRect.top;
ASSERT(diff > 0);
subsetSourceRect.top += diff;
subsetDestRect.top += diff;
}
if (sourceRect.right > LONG(sourceDesc.Width)) {
LONG diff = sourceRect.right - sourceDesc.Width;
ASSERT(diff > 0);
subsetSourceRect.right -= diff;
subsetDestRect.right -= diff;
}
if (sourceRect.bottom > LONG(sourceDesc.Height)) {
LONG diff = sourceRect.bottom - sourceDesc.Height;
ASSERT(diff > 0);
subsetSourceRect.bottom -= diff;
subsetDestRect.bottom -= diff;
}
ASSERT(subsetSourceRect.left <= subsetSourceRect.right);
ASSERT(subsetSourceRect.top <= subsetSourceRect.bottom);
ASSERT(subsetDestRect.left <= subsetDestRect.right);
ASSERT(subsetDestRect.top <= subsetDestRect.bottom);
ASSERT(subsetSourceRect.right - subsetSourceRect.left == subsetDestRect.right - subsetDestRect.left);
ASSERT(subsetSourceRect.bottom - subsetSourceRect.top == subsetDestRect.bottom - subsetDestRect.top);
mRenderer->endScene();
if (!IsEmpty(subsetSourceRect)) {
result = device->StretchRect(surface, &subsetSourceRect, textureSurface, &subsetDestRect, D3DTEXF_NONE);
}
result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
SafeRelease(textureSurface);
if (FAILED(result))
{
if (!(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)) {
std::printf("Bad result: 0x%x\n", result);
std::printf("sourceRect: %i,%i - %i,%i\n", sourceRect.left, sourceRect.top,
sourceRect.right, sourceRect.bottom);
std::printf("sourceDesc: Format: %u, Type: %u, Usage: %u, Pool: %u,"
" MSType: %u, MSQuality: %u, Width: %u, Height: %u\n",
sourceDesc.Format, sourceDesc.Type, sourceDesc.Usage,
sourceDesc.Pool, sourceDesc.MultiSampleType,
sourceDesc.MultiSampleQuality, sourceDesc.Width,
sourceDesc.Height);
std::printf("subsetSourceRect: %i,%i - %i,%i\n", subsetSourceRect.left, subsetSourceRect.top,
subsetSourceRect.right, subsetSourceRect.bottom);
std::printf("destDesc: Format: %u, Type: %u, Usage: %u, Pool: %u, MSType: %u,"
" MSQuality: %u, Width: %u, Height: %u\n",
destDesc.Format, destDesc.Type, destDesc.Usage, destDesc.Pool,
destDesc.MultiSampleType, destDesc.MultiSampleQuality,
destDesc.Width, destDesc.Height);
std::printf("subsetDestRect: %i,%i - %i,%i\n", subsetDestRect.left, subsetDestRect.top,
subsetDestRect.right, subsetDestRect.bottom);
}
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(texture);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);

View File

@ -934,18 +934,6 @@ GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
return;
}
DrawBlitTextureToFramebuffer(srcTex, destFB, srcSize, destSize, srcTarget,
internalFBs);
}
void
GLBlitHelper::DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget,
bool internalFBs)
{
BlitType type;
switch (srcTarget) {
case LOCAL_GL_TEXTURE_2D:

View File

@ -143,11 +143,6 @@ public:
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
bool internalFBs = false);
void DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
bool internalFBs = false);
void BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,

View File

@ -647,11 +647,7 @@ public:
MOZ_ASSERT(!mHasBeenChecked);
mHasBeenChecked = true;
const GLenum ret = mGL.fGetError();
while (mGL.fGetError()) {}
return ret;
return mGL.fGetError();
}
~LocalErrorScope() {
@ -2313,7 +2309,6 @@ public:
public:
void fDrawBuffers(GLsizei n, const GLenum* bufs) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDrawBuffers);
mSymbols.fDrawBuffers(n, bufs);
AFTER_GL_CALL;
}

View File

@ -836,15 +836,6 @@ GLContext::InitFeatures()
}
}
if (ShouldDumpExts()) {
for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) {
GLFeature feature = GLFeature(featureId);
printf_stderr("[%s] Feature::%s\n",
IsSupported(feature) ? "enabled" : "disabled",
GetFeatureName(feature));
}
}
if (WorkAroundDriverBugs()) {
#ifdef XP_MACOSX
// MacOSX 10.6 reports to support EXT_framebuffer_sRGB and EXT_texture_sRGB but

View File

@ -114,7 +114,6 @@ GLContextCGL::MakeCurrentImpl(bool aForce)
if (mContext) {
[mContext makeCurrentContext];
MOZ_ASSERT(IsCurrent());
// Use non-blocking swap in "ASAP mode".
// ASAP mode means that rendering is iterated as fast as possible.
// ASAP mode is entered when layout.frame_rate=0 (requires restart).

View File

@ -174,56 +174,34 @@ ScopedRenderbuffer::UnwrapImpl()
}
/* ScopedBindTexture **********************************************************/
static GLuint
GetBoundTexture(GLContext* gl, GLenum texTarget)
void
ScopedBindTexture::Init(GLenum aTarget)
{
GLenum bindingTarget;
switch (texTarget) {
case LOCAL_GL_TEXTURE_2D:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D;
break;
case LOCAL_GL_TEXTURE_CUBE_MAP:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_CUBE_MAP;
break;
case LOCAL_GL_TEXTURE_3D:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_3D;
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D_ARRAY;
break;
case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
break;
case LOCAL_GL_TEXTURE_EXTERNAL:
bindingTarget = LOCAL_GL_TEXTURE_BINDING_EXTERNAL;
break;
default:
MOZ_CRASH("bad texTarget");
}
GLuint ret = 0;
gl->GetUIntegerv(bindingTarget, &ret);
return ret;
mTarget = aTarget;
mOldTex = 0;
GLenum bindingTarget = (aTarget == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
: (aTarget == LOCAL_GL_TEXTURE_3D) ? LOCAL_GL_TEXTURE_BINDING_3D
: (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
: (aTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
: (aTarget == LOCAL_GL_TEXTURE_EXTERNAL) ? LOCAL_GL_TEXTURE_BINDING_EXTERNAL
: LOCAL_GL_NONE;
MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE);
mGL->GetUIntegerv(bindingTarget, &mOldTex);
}
ScopedBindTexture::ScopedBindTexture(GLContext* aGL, GLuint aNewTex, GLenum aTarget)
: ScopedGLWrapper<ScopedBindTexture>(aGL)
, mTarget(aTarget)
, mOldTex(GetBoundTexture(aGL, aTarget))
{
mGL->fBindTexture(mTarget, aNewTex);
}
{
Init(aTarget);
mGL->fBindTexture(aTarget, aNewTex);
}
void
ScopedBindTexture::UnwrapImpl()
{
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fBindTexture(mTarget, mOldTex);
}
@ -336,16 +314,16 @@ ScopedViewportRect::ScopedViewportRect(GLContext* aGL,
GLsizei width, GLsizei height)
: ScopedGLWrapper<ScopedViewportRect>(aGL)
{
mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
mGL->fViewport(x, y, width, height);
mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
mGL->fViewport(x, y, width, height);
}
void ScopedViewportRect::UnwrapImpl()
{
mGL->fViewport(mSavedViewportRect[0],
mSavedViewportRect[1],
mSavedViewportRect[2],
mSavedViewportRect[3]);
mGL->fViewport(mSavedViewportRect[0],
mSavedViewportRect[1],
mSavedViewportRect[2],
mSavedViewportRect[3]);
}
/* ScopedScissorRect **********************************************************/
@ -355,22 +333,22 @@ ScopedScissorRect::ScopedScissorRect(GLContext* aGL,
GLsizei width, GLsizei height)
: ScopedGLWrapper<ScopedScissorRect>(aGL)
{
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
mGL->fScissor(x, y, width, height);
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
mGL->fScissor(x, y, width, height);
}
ScopedScissorRect::ScopedScissorRect(GLContext* aGL)
: ScopedGLWrapper<ScopedScissorRect>(aGL)
{
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
}
void ScopedScissorRect::UnwrapImpl()
{
mGL->fScissor(mSavedScissorRect[0],
mSavedScissorRect[1],
mSavedScissorRect[2],
mSavedScissorRect[3]);
mGL->fScissor(mSavedScissorRect[0],
mSavedScissorRect[1],
mSavedScissorRect[2],
mSavedScissorRect[3]);
}
/* ScopedVertexAttribPointer **************************************************/
@ -481,8 +459,6 @@ ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL)
ScopedGLDrawState::~ScopedGLDrawState()
{
MOZ_ASSERT(mGL->IsCurrent());
mGL->fScissor(scissorBox[0], scissorBox[1],
scissorBox[2], scissorBox[3]);
@ -548,31 +524,5 @@ ScopedPackAlignment::UnwrapImpl() {
}
}
////////////////////////////////////////////////////////////////////////
// ScopedUnpackAlignment
ScopedUnpackAlignment::ScopedUnpackAlignment(GLContext* gl, GLint scopedVal)
: ScopedGLWrapper<ScopedUnpackAlignment>(gl)
{
MOZ_ASSERT(scopedVal == 1 ||
scopedVal == 2 ||
scopedVal == 4 ||
scopedVal == 8);
gl->fGetIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, &mOldVal);
if (scopedVal != mOldVal) {
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, scopedVal);
}
}
void
ScopedUnpackAlignment::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mOldVal);
}
} /* namespace gl */
} /* namespace mozilla */

View File

@ -45,7 +45,6 @@ protected:
public:
void Unwrap() {
MOZ_ASSERT(!mIsUnwrapped);
MOZ_ASSERT(IsContextCurrent(mGL));
Derived* derived = static_cast<Derived*>(this);
derived->UnwrapImpl();
@ -169,8 +168,11 @@ struct ScopedBindTexture
friend struct ScopedGLWrapper<ScopedBindTexture>;
protected:
const GLenum mTarget;
const GLuint mOldTex;
GLuint mOldTex;
GLenum mTarget;
private:
void Init(GLenum aTarget);
public:
ScopedBindTexture(GLContext* aGL, GLuint aNewTex,
@ -356,23 +358,6 @@ public:
protected:
void UnwrapImpl();
};
struct ScopedUnpackAlignment
: public ScopedGLWrapper<ScopedUnpackAlignment>
{
friend struct ScopedGLWrapper<ScopedUnpackAlignment>;
protected:
GLint mOldVal;
public:
ScopedUnpackAlignment(GLContext* gl, GLint scopedVal);
protected:
void UnwrapImpl();
};
} /* namespace gl */
} /* namespace mozilla */

View File

@ -414,9 +414,6 @@ private:
DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",
WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
DECL_GFX_PREF(Live, "webgl.disable-DOM-blit-uploads",
WebGLDisableDOMBlitUploads, bool, false);
DECL_GFX_PREF(Live, "webgl.disabled", WebGLDisabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-draft-extensions", WebGLDraftExtensionsEnabled, bool, false);
@ -430,8 +427,6 @@ private:
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
DECL_GFX_PREF(Live, "webgl.webgl2-compat-mode", WebGL2CompatMode, bool, false);
// WARNING:
// Please make sure that you've added your new preference to the list above in alphabetical order.
// Please do not just append it to the end of the list.

View File

@ -4787,7 +4787,7 @@ nsImageRenderer::PrepareImage()
// prefer SurfaceFromElement as it's more reliable.
mImageElementSurface =
nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement());
if (!mImageElementSurface.GetSourceSurface()) {
if (!mImageElementSurface.mSourceSurface) {
mPaintServerFrame = property->GetReferencedFrame();
if (!mPaintServerFrame) {
mPrepareResult = DrawResult::BAD_IMAGE;
@ -4872,8 +4872,7 @@ nsImageRenderer::ComputeIntrinsicSize()
appUnitsPerDevPixel));
}
} else {
NS_ASSERTION(mImageElementSurface.GetSourceSurface(),
"Surface should be ready.");
NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
IntSize surfaceSize = mImageElementSurface.mSize;
result.SetSize(
nsSize(nsPresContext::CSSPixelsToAppUnits(surfaceSize.width),
@ -5114,9 +5113,9 @@ nsImageRenderer::DrawableForElement(const nsRect& aImageRect,
return drawable.forget();
}
NS_ASSERTION(mImageElementSurface.GetSourceSurface(), "Surface should be ready.");
NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(
mImageElementSurface.GetSourceSurface().get(),
mImageElementSurface.mSourceSurface,
mImageElementSurface.mSize);
return drawable.forget();
}

View File

@ -1137,7 +1137,7 @@ public:
* edge of the presshell area. The aPoint, aScreenRect and aFlags arguments
* function in a similar manner as RenderSelection.
*/
virtual already_AddRefed<mozilla::gfx::SourceSurface>
virtual already_AddRefed<SourceSurface>
RenderNode(nsIDOMNode* aNode,
nsIntRegion* aRegion,
nsIntPoint& aPoint,
@ -1160,7 +1160,7 @@ public:
* point isn't used because the position can be determined from the displayed
* frames.
*/
virtual already_AddRefed<mozilla::gfx::SourceSurface>
virtual already_AddRefed<SourceSurface>
RenderSelection(nsISelection* aSelection,
nsIntPoint& aPoint,
nsIntRect* aScreenRect,
@ -1279,7 +1279,7 @@ public:
nsCOMPtr<nsIContent> mOverrideContent;
bool mReleaseContent;
bool mPrimaryState;
explicit PointerCaptureInfo(nsIContent* aPendingContent, bool aPrimaryState) :
mPendingContent(aPendingContent), mReleaseContent(false), mPrimaryState(aPrimaryState)
{

View File

@ -7176,23 +7176,20 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement,
if (!principal)
return result;
ImageContainer* container = aElement->GetImageContainer();
ImageContainer *container = aElement->GetImageContainer();
if (!container)
return result;
AutoLockImage lockImage(container);
result.mLayersImage = lockImage.GetImage();
if (!result.mLayersImage)
layers::Image* image = lockImage.GetImage();
if (!image) {
return result;
}
result.mSourceSurface = image->GetAsSourceSurface();
if (!result.mSourceSurface)
return result;
if (aTarget) {
// They gave us a DrawTarget to optimize for, so even though we have a layers::Image,
// we should unconditionally grab a SourceSurface and try to optimize it.
result.mSourceSurface = result.mLayersImage->GetAsSourceSurface();
if (!result.mSourceSurface)
return result;
RefPtr<SourceSurface> opt = aTarget->OptimizeSourceSurface(result.mSourceSurface);
if (opt) {
result.mSourceSurface = opt;
@ -7201,7 +7198,7 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement,
result.mCORSUsed = aElement->GetCORSMode() != CORS_NONE;
result.mHasSize = true;
result.mSize = result.mLayersImage->GetSize();
result.mSize = image->GetSize();
result.mPrincipal = principal.forget();
result.mIsWriteOnly = false;
@ -8273,9 +8270,6 @@ nsLayoutUtils::IsAPZTestLoggingEnabled()
return gfxPrefs::APZTestLoggingEnabled();
}
////////////////////////////////////////
// SurfaceFromElementResult
nsLayoutUtils::SurfaceFromElementResult::SurfaceFromElementResult()
// Use safe default values here
: mIsWriteOnly(true)
@ -8286,18 +8280,6 @@ nsLayoutUtils::SurfaceFromElementResult::SurfaceFromElementResult()
{
}
const RefPtr<mozilla::gfx::SourceSurface>&
nsLayoutUtils::SurfaceFromElementResult::GetSourceSurface()
{
if (!mSourceSurface && mLayersImage) {
mSourceSurface = mLayersImage->GetAsSourceSurface();
}
return mSourceSurface;
}
////////////////////////////////////////
bool
nsLayoutUtils::IsNonWrapperBlock(nsIFrame* aFrame)
{

View File

@ -29,7 +29,6 @@
#include "Units.h"
#include "mozilla/ToString.h"
#include "nsHTMLReflowMetrics.h"
#include "ImageContainer.h"
#include <limits>
#include <algorithm>
@ -68,7 +67,6 @@ struct IntrinsicSize;
struct ContainerLayerParameters;
class WritingMode;
namespace dom {
class CanvasRenderingContext2D;
class DOMRectList;
class Element;
class HTMLImageElement;
@ -80,7 +78,6 @@ namespace gfx {
struct RectCornerRadii;
} // namespace gfx
namespace layers {
class Image;
class Layer;
} // namespace layers
} // namespace mozilla
@ -2101,25 +2098,10 @@ public:
};
struct SurfaceFromElementResult {
friend class mozilla::dom::CanvasRenderingContext2D;
friend class nsLayoutUtils;
SurfaceFromElementResult();
/* If SFEResult contains a valid surface, it either mLayersImage or mSourceSurface
* will be non-null, and GetSourceSurface() will not be null.
*
* For valid surfaces, mSourceSurface may be null if mLayersImage is non-null, but
* GetSourceSurface() will create mSourceSurface from mLayersImage when called.
*/
/* Video elements (at least) often are already decoded as layers::Images. */
RefPtr<mozilla::layers::Image> mLayersImage;
protected:
/* GetSourceSurface() fills this and returns its non-null value if this SFEResult
* was successful. */
RefPtr<mozilla::gfx::SourceSurface> mSourceSurface;
public:
/* mSourceSurface will contain the resulting surface, or will be nullptr on error */
RefPtr<SourceSurface> mSourceSurface;
/* Contains info for drawing when there is no mSourceSurface. */
DirectDrawInfo mDrawInfo;
@ -2141,13 +2123,6 @@ public:
bool mCORSUsed;
/* Whether the returned image contains premultiplied pixel data */
bool mIsPremultiplied;
// Methods:
SurfaceFromElementResult();
// Gets mSourceSurface, or makes a SourceSurface from mLayersImage.
const RefPtr<mozilla::gfx::SourceSurface>& GetSourceSurface();
};
static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement,
@ -2672,7 +2647,7 @@ public:
/**
* Log a key/value pair for APZ testing during a paint.
* @param aManager The data will be written to the APZTestData associated
* @param aManager The data will be written to the APZTestData associated
* with this layer manager.
* @param aScrollId Identifies the scroll frame to which the data pertains.
* @param aKey The key under which to log the data.

View File

@ -4202,8 +4202,6 @@ pref("webgl.enable-privileged-extensions", false);
pref("webgl.bypass-shader-validation", false);
pref("webgl.enable-prototype-webgl2", false);
pref("webgl.disable-fail-if-major-performance-caveat", false);
pref("webgl.disable-DOM-blit-uploads", false);
pref("webgl.webgl2-compat-mode", false);
#ifdef RELEASE_BUILD
// Keep this disabled on Release and Beta for now. (see bug 1171228)

Some files were not shown because too many files have changed in this diff Show More