Compare commits

...

5 Commits

Author SHA1 Message Date
roytam1 904f5feaf3 Merge remote-tracking branch 'origin/master' into kmeleon76 1 month ago
roytam1 e7535dc94b import changes from `dev' branch of rmottola/Arctic-Fox: 1 month ago
roytam1 f1d1e16669 import changes from `dev' branch of rmottola/Arctic-Fox: 1 month ago
roytam1 00b0a024a4 import changes from `dev' branch of rmottola/Arctic-Fox: 1 month ago
roytam1 b75b514a74 import changes from `dev' branch of rmottola/Arctic-Fox: 1 month ago
  1. 4
      b2g/app/b2g.js
  2. 24
      build/clang-plugin/clang-plugin.cpp
  3. 8
      build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp
  4. 2
      dom/bindings/Bindings.conf
  5. 91
      dom/canvas/CanvasPath.h
  6. 52
      dom/canvas/CanvasRenderingContext2D.cpp
  7. 77
      dom/canvas/CanvasRenderingContext2D.h
  8. 13
      dom/canvas/WebGL2Context.cpp
  9. 24
      dom/canvas/WebGL2Context.h
  10. 2
      dom/canvas/WebGL2ContextDraw.cpp
  11. 95
      dom/canvas/WebGL2ContextFramebuffers.cpp
  12. 66
      dom/canvas/WebGL2ContextRenderbuffers.cpp
  13. 485
      dom/canvas/WebGL2ContextTextures.cpp
  14. 212
      dom/canvas/WebGLContext.cpp
  15. 281
      dom/canvas/WebGLContext.h
  16. 13
      dom/canvas/WebGLContextFramebufferOperations.cpp
  17. 1173
      dom/canvas/WebGLContextGL.cpp
  18. 469
      dom/canvas/WebGLContextTextures.cpp
  19. 4
      dom/canvas/WebGLContextUtils.cpp
  20. 3
      dom/canvas/WebGLContextUtils.h
  21. 34
      dom/canvas/WebGLContextValidate.cpp
  22. 80
      dom/canvas/WebGLFramebuffer.cpp
  23. 11
      dom/canvas/WebGLFramebuffer.h
  24. 285
      dom/canvas/WebGLTexture.cpp
  25. 206
      dom/canvas/WebGLTexture.h
  26. 1419
      dom/canvas/WebGLTextureUpload.cpp
  27. 4
      dom/canvas/moz.build
  28. 7
      dom/canvas/nsICanvasRenderingContextInternal.h
  29. 18
      dom/canvas/test/test_hitregion_event.html
  30. 15
      dom/html/HTMLCanvasElement.cpp
  31. 7
      dom/html/HTMLCanvasElement.h
  32. 40
      dom/media/CanvasCaptureMediaStream.cpp
  33. 5
      dom/media/CanvasCaptureMediaStream.h
  34. 6
      dom/system/gonk/AudioManager.cpp
  35. 1
      dom/webidl/CanvasRenderingContext2D.webidl
  36. 5
      dom/webidl/WebGL2RenderingContext.webidl
  37. 6
      embedding/test/browser.ini
  38. 87
      embedding/test/browser_bug1204626.js
  39. 3
      embedding/test/bug1204626_doc0.html
  40. 5
      embedding/test/bug1204626_doc1.html
  41. 1
      embedding/test/moz.build
  42. 196
      gfx/2d/MMIHelpers.h
  43. 2
      gfx/2d/RecordedEvent.h
  44. 2
      gfx/2d/SourceSurfaceSkia.cpp
  45. 92
      gfx/2d/convolver.cpp
  46. 77
      gfx/2d/convolverSSE2.cpp
  47. 4
      gfx/2d/convolverSSE2.h
  48. 16
      gfx/2d/image_operations.cpp
  49. 39
      gfx/gl/GLScreenBuffer.cpp
  50. 2
      gfx/gl/GLScreenBuffer.h
  51. 3
      gfx/gl/GLTextureImage.h
  52. 4
      gfx/gl/HeapCopyOfStackArray.h
  53. 4
      gfx/gl/SharedSurface.h
  54. 4
      gfx/layers/Layers.cpp
  55. 4
      gfx/layers/PersistentBufferProvider.cpp
  56. 12
      gfx/layers/PersistentBufferProvider.h
  57. 4
      gfx/layers/basic/TextureClientX11.cpp
  58. 26
      gfx/skia/skia/src/core/SkDraw.cpp
  59. 2
      gfx/skia/skia/src/utils/win/SkDWrite.h
  60. 6
      gfx/thebes/gfxASurface.cpp
  61. 6
      gfx/thebes/gfxASurface.h
  62. 2
      gfx/thebes/gfxPlatform.cpp
  63. 5
      gfx/thebes/gfxPrefs.h
  64. 11
      gfx/thebes/gfxTypes.h
  65. 6
      gfx/thebes/gfxWindowsSurface.cpp
  66. 4
      gfx/thebes/gfxWindowsSurface.h
  67. 11
      gfx/thebes/gfxXlibSurface.cpp
  68. 10
      gfx/thebes/gfxXlibSurface.h
  69. 10
      image/ClippedImage.cpp
  70. 4
      image/ClippedImage.h
  71. 250
      image/CopyOnWrite.h
  72. 31
      image/DecodePool.cpp
  73. 78
      image/Decoder.cpp
  74. 122
      image/Decoder.h
  75. 94
      image/DecoderFactory.cpp
  76. 83
      image/DecoderFactory.h
  77. 42
      image/DecoderFlags.h
  78. 45
      image/Deinterlacer.cpp
  79. 50
      image/Deinterlacer.h
  80. 43
      image/Downscaler.cpp
  81. 16
      image/Downscaler.h
  82. 14
      image/DynamicImage.cpp
  83. 32
      image/FrameAnimator.cpp
  84. 10
      image/FrameAnimator.h
  85. 8
      image/FrozenImage.cpp
  86. 4
      image/FrozenImage.h
  87. 13
      image/Image.h
  88. 46
      image/ImageFactory.cpp
  89. 44
      image/ImageMetadata.cpp
  90. 42
      image/ImageMetadata.h
  91. 4
      image/ImageOps.cpp
  92. 8
      image/ImageWrapper.cpp
  93. 37
      image/MultipartImage.cpp
  94. 2
      image/MultipartImage.h
  95. 4
      image/Orientation.h
  96. 10
      image/OrientedImage.cpp
  97. 4
      image/OrientedImage.h
  98. 180
      image/ProgressTracker.cpp
  99. 61
      image/ProgressTracker.h
  100. 673
      image/RasterImage.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

4
b2g/app/b2g.js

@ -62,7 +62,6 @@ pref("browser.cache.memory_limit", 2048); // 2 MB
/* image cache prefs */
pref("image.cache.size", 1048576); // bytes
pref("image.high_quality_downscaling.enabled", false);
pref("canvas.image.cache.limit", 20971520); // 20 MB
/* offline cache prefs */
@ -326,6 +325,7 @@ pref("media.gonk.enabled", true);
pref("media.video-queue.default-size", 3);
// optimize images' memory usage
pref("image.downscale-during-decode.enabled", true);
pref("image.decode-only-on-draw.enabled", true);
pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */
// Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
@ -904,7 +904,7 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
// falling back to Skia/software for smaller canvases
#ifdef MOZ_WIDGET_GONK
pref("gfx.canvas.azure.backends", "skia");
pref("gfx.canvas.azure.accelerated", true);
pref("gfx.canvas.azure.accelerated", false);
#endif
// Turn on dynamic cache size for Skia

24
build/clang-plugin/clang-plugin.cpp

@ -951,13 +951,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() {
// lambda, where the declaration they reference is not inside the lambda.
// This excludes arguments and local variables, leaving only captured
// variables.
astMatcher.addMatcher(
lambdaExpr(hasDescendant(
declRefExpr(hasType(pointerType(pointee(isRefCounted()))),
to(decl().bind("decl")))
.bind("declref")),
unless(hasDescendant(decl(equalsBoundNode("decl"))))),
&refCountedInsideLambdaChecker);
astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker);
// Older clang versions such as the ones used on the infra recognize these
// conversions as 'operator _Bool', but newer clang versions recognize these
@ -1241,11 +1235,19 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
"Refcounted variable %0 of type %1 cannot be captured by a lambda");
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "Please consider using a smart pointer");
const DeclRefExpr *declref = Result.Nodes.getNodeAs<DeclRefExpr>("declref");
const LambdaExpr *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
for (const LambdaCapture Capture : Lambda->captures()) {
if (Capture.capturesVariable()) {
QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
Diag.Report(declref->getLocStart(), errorID)
<< declref->getFoundDecl() << declref->getType()->getPointeeType();
Diag.Report(declref->getLocStart(), noteID);
if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
Diag.Report(Capture.getLocation(), errorID)
<< Capture.getCapturedVar() << Pointee;
Diag.Report(Capture.getLocation(), noteID);
}
}
}
}
void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(

8
build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp

@ -67,9 +67,9 @@ void foo() {
take(argsp);
take(localsp);
});
take([ptr](R* argptr) {
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
ptr->method();
argptr->method();
localptr->method();
});
@ -79,9 +79,9 @@ void foo() {
argsp->method();
localsp->method();
});
take([ptr](R* argptr) {
take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
R* localptr;
take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
take(ptr);
take(argptr);
take(localptr);
});

2
dom/bindings/Bindings.conf

@ -900,7 +900,7 @@ DOMInterfaces = {
'Path2D': {
'nativeType': 'mozilla::dom::CanvasPath',
'headerFile': 'CanvasRenderingContext2D.h'
'headerFile': 'CanvasPath.h'
},
'PeerConnectionImpl': {

91
dom/canvas/CanvasPath.h

@ -0,0 +1,91 @@
/* 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 CanvasPath_h
#define CanvasPath_h
#include "mozilla/Attributes.h"
#include "mozilla/RefPtr.h"
#include "nsWrapperCache.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/ErrorResult.h"
namespace mozilla {
namespace dom {
enum class CanvasWindingRule : uint32_t;
class SVGMatrix;
class CanvasPath final :
public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
CanvasPath& aCanvasPath,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
const nsAString& aPathString,
ErrorResult& rv);
void ClosePath();
void MoveTo(double x, double y);
void LineTo(double x, double y);
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
void BezierCurveTo(double cp1x, double cp1y,
double cp2x, double cp2y,
double x, double y);
void ArcTo(double x1, double y1, double x2, double y2, double radius,
ErrorResult& error);
void Rect(double x, double y, double w, double h);
void Arc(double x, double y, double radius,
double startAngle, double endAngle, bool anticlockwise,
ErrorResult& error);
void Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error);
void LineTo(const gfx::Point& aPoint);
void BezierTo(const gfx::Point& aCP1,
const gfx::Point& aCP2,
const gfx::Point& aCP3);
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
const gfx::DrawTarget* aTarget) const;
explicit CanvasPath(nsISupports* aParent);
// already_AddRefed arg because the return value from Path::CopyToBuilder()
// is passed directly and we can't drop the only ref to have a raw pointer.
CanvasPath(nsISupports* aParent,
already_AddRefed<gfx::PathBuilder> aPathBuilder);
void AddPath(CanvasPath& aCanvasPath,
const Optional<NonNull<SVGMatrix>>& aMatrix);
private:
virtual ~CanvasPath() {}
nsCOMPtr<nsISupports> mParent;
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
mutable RefPtr<gfx::Path> mPath;
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
void EnsurePathBuilder() const;
};
} // namespace dom
} // namespace mozilla
#endif /* CanvasPath_h */

52
dom/canvas/CanvasRenderingContext2D.cpp

@ -101,6 +101,7 @@
#include "nsCCUncollectableMarker.h"
#include "nsWrapperCacheInlines.h"
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
#include "mozilla/dom/CanvasPath.h"
#include "mozilla/dom/HTMLImageElement.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/SVGMatrix.h"
@ -949,7 +950,9 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
, mIPC(false)
, mDrawObserver(nullptr)
, mIsEntireFrameInvalid(false)
, mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
, mPredictManyRedrawCalls(false)
, mIsCapturedFrameInvalid(false)
, mPathTransformWillUpdate(false)
, mInvalidateCount(0)
{
sNumLivingContexts++;
@ -1054,6 +1057,7 @@ CanvasRenderingContext2D::Reset()
// no longer be valid.
mIsEntireFrameInvalid = false;
mPredictManyRedrawCalls = false;
mIsCapturedFrameInvalid = false;
return NS_OK;
}
@ -1112,6 +1116,8 @@ CanvasRenderingContext2D::StyleColorToString(const nscolor& aColor, nsAString& a
nsresult
CanvasRenderingContext2D::Redraw()
{
mIsCapturedFrameInvalid = true;
if (mIsEntireFrameInvalid) {
return NS_OK;
}
@ -1133,6 +1139,8 @@ CanvasRenderingContext2D::Redraw()
void
CanvasRenderingContext2D::Redraw(const mgfx::Rect &r)
{
mIsCapturedFrameInvalid = true;
++mInvalidateCount;
if (mIsEntireFrameInvalid) {
@ -1170,6 +1178,8 @@ CanvasRenderingContext2D::DidRefresh()
void
CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
{
mIsCapturedFrameInvalid = true;
if (mIsEntireFrameInvalid) {
++mInvalidateCount;
return;
@ -1393,13 +1403,14 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
DemoteOldestContextIfNecessary();
mBufferProvider = nullptr;
#if USE_SKIA_GPU
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
#if USE_SKIA_GPU
if (glue && glue->GetGrContext() && glue->GetGLContext()) {
mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
if (mTarget) {
AddDemotableContext(this);
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
} else {
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
mode = RenderingMode::SoftwareBackendMode;
@ -3351,15 +3362,24 @@ CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
void
CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorResult& error)
{
// check if the path is valid
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
if(!mPath) {
RefPtr<gfx::Path> path;
if (options.mPath) {
path = options.mPath->GetPath(CanvasWindingRule::Nonzero, mTarget);
}
if (!path) {
// check if the path is valid
EnsureUserSpacePath(CanvasWindingRule::Nonzero);
path = mPath;
}
if(!path) {
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
// get the bounds of the current path. They are relative to the canvas
mgfx::Rect bounds(mPath->GetBounds(mTarget->GetTransform()));
mgfx::Rect bounds(path->GetBounds(mTarget->GetTransform()));
if ((bounds.width == 0) || (bounds.height == 0) || !bounds.IsFinite()) {
// The specified region has no pixels.
error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@ -3388,7 +3408,7 @@ CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorRes
RegionInfo info;
info.mId = options.mId;
info.mElement = options.mControl;
RefPtr<PathBuilder> pathBuilder = mPath->TransformedCopyToBuilder(mTarget->GetTransform());
RefPtr<PathBuilder> pathBuilder = path->TransformedCopyToBuilder(mTarget->GetTransform());
info.mPath = pathBuilder->Finish();
mHitRegionsOptions.InsertElementAt(0, info);
@ -5589,12 +5609,7 @@ CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
return nullptr;
}
mBufferProvider = aManager->CreatePersistentBufferProvider(mTarget->GetSize(), mTarget->GetFormat());
RefPtr<SourceSurface> surf = mTarget->Snapshot();
mTarget = mBufferProvider->GetDT(IntRect(IntPoint(), mTarget->GetSize()));
mTarget->CopySurface(surf, IntRect(IntPoint(), mTarget->GetSize()), IntPoint());
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
return mBufferProvider;
}
@ -5710,6 +5725,17 @@ CanvasRenderingContext2D::MarkContextClean()
mInvalidateCount = 0;
}
void
CanvasRenderingContext2D::MarkContextCleanForFrameCapture()
{
mIsCapturedFrameInvalid = false;
}
bool
CanvasRenderingContext2D::IsContextCleanForFrameCapture()
{
return !mIsCapturedFrameInvalid;
}
bool
CanvasRenderingContext2D::ShouldForceInactiveLayer(LayerManager *aManager)

77
dom/canvas/CanvasRenderingContext2D.h

@ -44,77 +44,12 @@ class StringOrCanvasGradientOrCanvasPattern;
class OwningStringOrCanvasGradientOrCanvasPattern;
class TextMetrics;
class CanvasFilterChainObserver;
class CanvasPath;
extern const mozilla::gfx::Float SIGMA_MAX;
template<typename T> class Optional;
class CanvasPath final :
public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
CanvasPath& aCanvasPath,
ErrorResult& rv);
static already_AddRefed<CanvasPath> Constructor(const GlobalObject& aGlobal,
const nsAString& aPathString,
ErrorResult& rv);
void ClosePath();
void MoveTo(double x, double y);
void LineTo(double x, double y);
void QuadraticCurveTo(double cpx, double cpy, double x, double y);
void BezierCurveTo(double cp1x, double cp1y,
double cp2x, double cp2y,
double x, double y);
void ArcTo(double x1, double y1, double x2, double y2, double radius,
ErrorResult& error);
void Rect(double x, double y, double w, double h);
void Arc(double x, double y, double radius,
double startAngle, double endAngle, bool anticlockwise,
ErrorResult& error);
void Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error);
void LineTo(const gfx::Point& aPoint);
void BezierTo(const gfx::Point& aCP1,
const gfx::Point& aCP2,
const gfx::Point& aCP3);
already_AddRefed<gfx::Path> GetPath(const CanvasWindingRule& aWinding,
const gfx::DrawTarget* aTarget) const;
explicit CanvasPath(nsISupports* aParent);
// already_AddRefed arg because the return value from Path::CopyToBuilder()
// is passed directly and we can't drop the only ref to have a raw pointer.
CanvasPath(nsISupports* aParent,
already_AddRefed<gfx::PathBuilder> aPathBuilder);
void AddPath(CanvasPath& aCanvasPath,
const Optional<NonNull<SVGMatrix>>& aMatrix);
private:
virtual ~CanvasPath() {}
nsCOMPtr<nsISupports> mParent;
static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
mutable RefPtr<gfx::Path> mPath;
mutable RefPtr<gfx::PathBuilder> mPathBuilder;
void EnsurePathBuilder() const;
};
struct CanvasBidiProcessor;
class CanvasRenderingContext2DUserData;
class CanvasDrawObserver;
@ -527,6 +462,8 @@ public:
LayerManager *aManager) override;
virtual bool ShouldForceInactiveLayer(LayerManager *aManager) override;
void MarkContextClean() override;
void MarkContextCleanForFrameCapture() override;
bool IsContextCleanForFrameCapture() override;
NS_IMETHOD SetIsIPC(bool isIPC) override;
// this rect is in canvas device space
void Redraw(const mozilla::gfx::Rect &r);
@ -819,6 +756,13 @@ protected:
*/
bool mPredictManyRedrawCalls;
/**
* Flag to avoid unnecessary surface copies to FrameCaptureListeners in the
* case when the canvas is not currently being drawn into and not rendered
* but canvas capturing is still ongoing.
*/
bool mIsCapturedFrameInvalid;
// This is stored after GetThebesSurface has been called once to avoid
// excessive ThebesSurface initialization overhead.
nsRefPtr<gfxASurface> mThebesSurface;
@ -968,6 +912,7 @@ protected:
fillRule(mozilla::gfx::FillRule::FILL_WINDING),
lineCap(mozilla::gfx::CapStyle::BUTT),
lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
filterString(MOZ_UTF16("none")),
imageSmoothingEnabled(true),
fontExplicitLanguage(false)
{ }

13
dom/canvas/WebGL2Context.cpp

@ -77,8 +77,7 @@ static const gl::GLFeature kRequiredFeatures[] = {
gl::GLFeature::element_index_uint,
gl::GLFeature::frag_color_float,
gl::GLFeature::frag_depth,
gl::GLFeature::framebuffer_blit,
gl::GLFeature::framebuffer_multisample,
gl::GLFeature::framebuffer_object,
gl::GLFeature::get_integer_indexed,
gl::GLFeature::get_integer64_indexed,
gl::GLFeature::gpu_shader4,
@ -164,6 +163,16 @@ WebGLContext::InitWebGL2()
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);

24
dom/canvas/WebGL2Context.h

@ -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;
@ -55,13 +61,20 @@ public:
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
void GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat, GLenum pname, JS::MutableHandleValue retval);
void FramebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture* texture, GLint level, GLint layer);
void InvalidateFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments,
ErrorResult& rv);
void InvalidateSubFramebuffer (GLenum target, const dom::Sequence<GLenum>& attachments, GLint x, GLint y,
GLsizei width, GLsizei height, ErrorResult& rv);
void ReadBuffer(GLenum mode);
// -------------------------------------------------------------------------
// Renderbuffer objects - WebGL2ContextRenderbuffers.cpp
void GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat,
GLenum pname, JS::MutableHandleValue retval,
ErrorResult& rv);
void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat,
GLsizei width, GLsizei height);
@ -357,15 +370,10 @@ public:
private:
WebGL2Context();
JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) override;
virtual bool IsTexParamValid(GLenum pname) const override;
void UpdateBoundQuery(GLenum target, WebGLQuery* query);
bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info);
// CreateVertexArrayImpl is assumed to be infallible.
virtual WebGLVertexArray* CreateVertexArrayImpl() override;
virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;

2
dom/canvas/WebGL2ContextDraw.cpp

@ -13,7 +13,7 @@ namespace mozilla {
void
WebGL2Context::DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("drawRangeElements: Not Implemented.");
}
} // namespace mozilla

95
dom/canvas/WebGL2ContextFramebuffers.cpp

@ -330,16 +330,92 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
mask, filter);
}
void
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
static bool
ValidateTextureLayerAttachment(GLenum attachment)
{
MOZ_CRASH("Not Implemented.");
if (LOCAL_GL_COLOR_ATTACHMENT0 < attachment &&
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
{
return true;
}
switch (attachment) {
case LOCAL_GL_DEPTH_ATTACHMENT:
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
case LOCAL_GL_STENCIL_ATTACHMENT:
return true;
}
return false;
}
void
WebGL2Context::GetInternalformatParameter(JSContext*, GLenum target, GLenum internalformat, GLenum pname, JS::MutableHandleValue retval)
WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level, GLint layer)
{
MOZ_CRASH("Not Implemented.");
if (IsContextLost())
return;
if (!ValidateFramebufferTarget(target, "framebufferTextureLayer"))
return;
if (!ValidateTextureLayerAttachment(attachment))
return ErrorInvalidEnumInfo("framebufferTextureLayer: attachment:", attachment);
if (texture) {
if (texture->IsDeleted()) {
return ErrorInvalidValue("framebufferTextureLayer: texture must be a valid "
"texture object.");
}
if (level < 0)
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
switch (texture->Target()) {
case LOCAL_GL_TEXTURE_3D:
if ((GLuint) layer >= mGLMax3DTextureSize) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_3D_TEXTURE_SIZE");
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
if ((GLuint) layer >= mGLMaxArrayTextureLayers) {
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
"MAX_ARRAY_TEXTURE_LAYERS");
}
break;
default:
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;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("Bad target.");
}
if (!fb) {
return ErrorInvalidOperation("framebufferTextureLayer: cannot modify"
" framebuffer 0.");
}
fb->FramebufferTextureLayer(attachment, texture, level, layer);
}
// Map attachments intended for the default buffer, to attachments for a non-
@ -522,13 +598,4 @@ WebGL2Context::ReadBuffer(GLenum mode)
gl->Screen()->SetReadBuffer(mode);
}
void
WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
RenderbufferStorage_base("renderbufferStorageMultisample", target, samples,
internalFormat, width, height);
}
} // namespace mozilla

66
dom/canvas/WebGL2ContextRenderbuffers.cpp

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "WebGL2Context.h"
#include "GLContext.h"
#include "WebGLContextUtils.h"
namespace mozilla {
void
WebGL2Context::GetInternalformatParameter(JSContext* cx, GLenum target,
GLenum internalformat, GLenum pname,
JS::MutableHandleValue retval,
ErrorResult& rv)
{
if (IsContextLost())
return;
if (target != LOCAL_GL_RENDERBUFFER) {
return ErrorInvalidEnumInfo("getInternalfomratParameter: target must be "
"RENDERBUFFER. Was:", target);
}
// GL_INVALID_ENUM is generated if internalformat is not color-,
// depth-, or stencil-renderable.
// TODO: When format table queries lands.
if (pname != LOCAL_GL_SAMPLES) {
return ErrorInvalidEnumInfo("getInternalformatParameter: pname must be SAMPLES. "
"Was:", pname);
}
GLint* samples = nullptr;
GLint sampleCount = 0;
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
if (sampleCount > 0) {
samples = new GLint[sampleCount];
gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
sampleCount, samples);
}
JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
if (!obj) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
delete[] samples;
retval.setObjectOrNull(obj);
}
void
WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
GLenum internalFormat,
GLsizei width, GLsizei height)
{
RenderbufferStorage_base("renderbufferStorageMultisample", target, samples,
internalFormat, width, height);
}
} // namespace mozilla

485
dom/canvas/WebGL2ContextTextures.cpp

@ -10,485 +10,126 @@
namespace mozilla {
bool
WebGL2Context::ValidateSizedInternalFormat(GLenum internalformat, const char* info)
{
switch (internalformat) {
// Sized Internal Formats
// https://www.khronos.org/opengles/sdk/docs/man3/html/glTexStorage2D.xhtml
case LOCAL_GL_R8:
case LOCAL_GL_R8_SNORM:
case LOCAL_GL_R16F:
case LOCAL_GL_R32F:
case LOCAL_GL_R8UI:
case LOCAL_GL_R8I:
case LOCAL_GL_R16UI:
case LOCAL_GL_R16I:
case LOCAL_GL_R32UI:
case LOCAL_GL_R32I:
case LOCAL_GL_RG8:
case LOCAL_GL_RG8_SNORM:
case LOCAL_GL_RG16F:
case LOCAL_GL_RG32F:
case LOCAL_GL_RG8UI:
case LOCAL_GL_RG8I:
case LOCAL_GL_RG16UI:
case LOCAL_GL_RG16I:
case LOCAL_GL_RG32UI:
case LOCAL_GL_RG32I:
case LOCAL_GL_RGB8:
case LOCAL_GL_SRGB8:
case LOCAL_GL_RGB565:
case LOCAL_GL_RGB8_SNORM:
case LOCAL_GL_R11F_G11F_B10F:
case LOCAL_GL_RGB9_E5:
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGB8UI:
case LOCAL_GL_RGB8I:
case LOCAL_GL_RGB16UI:
case LOCAL_GL_RGB16I:
case LOCAL_GL_RGB32UI:
case LOCAL_GL_RGB32I:
case LOCAL_GL_RGBA8:
case LOCAL_GL_SRGB8_ALPHA8:
case LOCAL_GL_RGBA8_SNORM:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB10_A2:
case LOCAL_GL_RGBA16F:
case LOCAL_GL_RGBA32F:
case LOCAL_GL_RGBA8UI:
case LOCAL_GL_RGBA8I:
case LOCAL_GL_RGB10_A2UI:
case LOCAL_GL_RGBA16UI:
case LOCAL_GL_RGBA16I:
case LOCAL_GL_RGBA32I:
case LOCAL_GL_RGBA32UI:
case LOCAL_GL_DEPTH_COMPONENT16:
case LOCAL_GL_DEPTH_COMPONENT24:
case LOCAL_GL_DEPTH_COMPONENT32F:
case LOCAL_GL_DEPTH24_STENCIL8:
case LOCAL_GL_DEPTH32F_STENCIL8:
return true;
}
if (IsCompressedTextureFormat(internalformat))
return true;
nsCString name;
EnumName(internalformat, &name);
ErrorInvalidEnum("%s: invalid internal format %s", info, name.get());
return false;
}
/** Validates parameters to texStorage{2D,3D} */
bool
WebGL2Context::ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info)
{
// GL_INVALID_OPERATION is generated if the default texture object is curently bound to target.
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
if (!tex) {
ErrorInvalidOperation("%s: no texture is bound to target %s", info, EnumName(target));
return false;
}
// GL_INVALID_OPERATION is generated if the texture object currently bound to target already has
// GL_TEXTURE_IMMUTABLE_FORMAT set to GL_TRUE.
if (tex->IsImmutable()) {
ErrorInvalidOperation("%s: texture bound to target %s is already immutable", info, EnumName(target));
return false;
}
// GL_INVALID_ENUM is generated if internalformat is not a valid sized internal format.
if (!ValidateSizedInternalFormat(internalformat, info))
return false;
// GL_INVALID_VALUE is generated if width, height or levels are less than 1.
if (width < 1) { ErrorInvalidValue("%s: width is < 1", info); return false; }
if (height < 1) { ErrorInvalidValue("%s: height is < 1", info); return false; }
if (depth < 1) { ErrorInvalidValue("%s: depth is < 1", info); return false; }
if (levels < 1) { ErrorInvalidValue("%s: levels is < 1", info); return false; }
// GL_INVALID_OPERATION is generated if levels is greater than floor(log2(max(width, height, depth)))+1.
if (FloorLog2(std::max(std::max(width, height), depth)) + 1 < levels) {
ErrorInvalidOperation("%s: too many levels for given texture dimensions", info);
return false;
}
return true;
}
// -------------------------------------------------------------------------
// Texture objects
void
WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
WebGL2Context::TexStorage2D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
{
if (IsContextLost())
const char funcName[] = "TexStorage2D";
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_2D && target != LOCAL_GL_TEXTURE_CUBE_MAP)
return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP");
if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage2D(target, levels, internalformat, width, height);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage2D generated error %s", ErrorName(error));
}
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
tex->SetImmutable();
const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
GLsizei w = width;
GLsizei h = height;
for (size_t l = 0; l < size_t(levels); l++) {
for (size_t f = 0; f < facesCount; f++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, f),
l, w, h, 1,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
}
w = std::max(1, w / 2);
h = std::max(1, h / 2);
}
tex->TexStorage2D(texTarget, levels, internalFormat, width, height);
}
void
WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
WebGL2Context::TexStorage3D(GLenum rawTexTarget, GLsizei levels, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth)
{
if (IsContextLost())
const char funcName[] = "texStorage3D";
TexTarget texTarget;
WebGLTexture* tex;
if (!ValidateTexTarget(this, rawTexTarget, funcName, &texTarget, &tex))
return;
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_3D)
return ErrorInvalidEnum("texStorage3D: target is not TEXTURE_3D");
if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
return;
GetAndFlushUnderlyingGLErrors();
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texStorage3D generated error %s", ErrorName(error));
}
WebGLTexture* tex = ActiveBoundTextureForTarget(target);
tex->SetImmutable();
GLsizei w = width;
GLsizei h = height;
GLsizei d = depth;
for (size_t l = 0; l < size_t(levels); l++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, 0),
l, w, h, d,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
w = std::max(1, w >> 1);
h = std::max(1, h >> 1);
d = std::max(1, d >> 1);
}
tex->TexStorage3D(texTarget, levels, internalFormat, width, height, depth);
}
void
WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
WebGL2Context::TexImage3D(GLenum rawTexImageTarget, GLint level, GLenum internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView> &pixels,
ErrorResult& rv)
GLint border, GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
if (IsContextLost())
return;
void* data;
size_t dataLength;
js::Scalar::Type jsArrayType;
if (pixels.IsNull()) {
data = nullptr;
dataLength = 0;
jsArrayType = js::Scalar::MaxTypedArrayViewType;
} else {
const dom::ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
data = view.Data();
dataLength = view.Length();
jsArrayType = view.Type();
}
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
if (!ValidateTexImageTarget(target, func, dims))
return;
TexImageTarget texImageTarget = target;
if (!ValidateTexImage(texImageTarget, level, internalformat,
0, 0, 0,
width, height, depth,
border, format, type, func, dims))
const char funcName[] = "texImage3D";
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
TexInternalFormat effectiveInternalFormat =
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
if (effectiveInternalFormat == LOCAL_GL_NONE) {
return ErrorInvalidOperation("texImage3D: bad combination of internalformat and type");
}
// we need to find the exact sized format of the source data. Slightly abusing
// EffectiveInternalFormatFromInternalFormatAndType for that purpose. Really, an unsized source format
// is the same thing as an unsized internalformat.
TexInternalFormat effectiveSourceFormat =
EffectiveInternalFormatFromInternalFormatAndType(format, type);
MOZ_ASSERT(effectiveSourceFormat != LOCAL_GL_NONE); // should have validated format/type combo earlier
const size_t srcbitsPerTexel = GetBitsPerTexel(effectiveSourceFormat);
MOZ_ASSERT((srcbitsPerTexel % 8) == 0); // should not have compressed formats here.
size_t srcTexelSize = srcbitsPerTexel / 8;
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength && dataLength < bytesNeeded)
return ErrorInvalidOperation("texImage3D: not enough data for operation (need %d, have %d)",
bytesNeeded, dataLength);
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex)
return ErrorInvalidOperation("texImage3D: no texture is bound to this target");
if (tex->IsImmutable()) {
return ErrorInvalidOperation(
"texImage3D: disallowed because the texture "
"bound to this target has already been made immutable by texStorage3D");
}
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
effectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
&driverType);
MakeContextCurrent();
GetAndFlushUnderlyingGLErrors();
gl->fTexImage3D(texImageTarget.get(), level,
driverInternalFormat,
width, height, depth,
0, driverFormat, driverType,
data);
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
return GenerateWarning("texImage3D generated error %s", ErrorName(error));
}
tex->SetImageInfo(texImageTarget, level,
width, height, depth,
effectiveInternalFormat,
data ? WebGLImageDataStatus::InitializedImageData
: WebGLImageDataStatus::UninitializedImageData);
tex->TexImage3D(texImageTarget, level, internalFormat, width, height, depth, border,
unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
WebGL2Context::TexSubImage3D(GLenum rawTexImageTarget, GLint level,
GLint xOffset, GLint yOffset, GLint zOffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& rv)
GLenum unpackFormat, GLenum unpackType,
const dom::Nullable<dom::ArrayBufferView>& maybeView,
ErrorResult& out_rv)
{
if (IsContextLost())
return;
if (pixels.IsNull())
return ErrorInvalidValue("texSubImage3D: pixels must not be null!");
const dom::ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
if (!ValidateTexImageTarget(rawTarget, func, dims))
return;
TexImageTarget texImageTarget(rawTarget);
WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
if (!tex) {
return ErrorInvalidOperation("texSubImage3D: no texture bound on active texture unit");
}
if (!tex->HasImageInfoAt(texImageTarget, level)) {
return ErrorInvalidOperation("texSubImage3D: no previously defined texture image");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
TexInternalFormat existingUnsizedInternalFormat = LOCAL_GL_NONE;
TexType existingType = LOCAL_GL_NONE;
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(existingEffectiveInternalFormat,
&existingUnsizedInternalFormat,
&existingType);
if (!ValidateTexImage(texImageTarget, level, existingEffectiveInternalFormat.get(),
xoffset, yoffset, zoffset,
width, height, depth,
0, format, type, func, dims))
const char funcName[] = "texSubImage3D";
TexImageTarget texImageTarget;
WebGLTexture* tex;
if (!ValidateTexImageTarget(this, rawTexImageTarget, funcName, &texImageTarget, &tex))
{
return;
}
if (type != existingType) {
return ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
}
js::Scalar::Type jsArrayType = view.Type();
void* data = view.Data();
size_t dataLength = view.Length();
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
const size_t bitsPerTexel = GetBitsPerTexel(existingEffectiveInternalFormat);
MOZ_ASSERT((bitsPerTexel % 8) == 0); // should not have compressed formats here.
size_t srcTexelSize = bitsPerTexel / 8;
if (width == 0 || height == 0 || depth == 0)
return; // no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
if (imageInfo.HasUninitializedImageData()) {
bool coversWholeImage = xoffset == 0 &&
yoffset == 0 &&
zoffset == 0 &&
width == imageInfo.Width() &&
height == imageInfo.Height() &&
depth == imageInfo.Depth();
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
if (!tex->EnsureInitializedImageData(texImageTarget, level))
return;
}
}
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
existingEffectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
&driverType);
MakeContextCurrent();
gl->fTexSubImage3D(texImageTarget.get(), level,
xoffset, yoffset, zoffset,
width, height, depth,
driverFormat, driverType, data);
tex->TexSubImage3D(texImageTarget, level, xOffset, yOffset, zOffset, width, height,
depth, unpackFormat, unpackType, maybeView, &out_rv);
}
void
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, dom::ImageData* data,
ErrorResult& rv)
GLint xOffset, GLint yOffset, GLint zOffset,
GLenum unpackFormat, GLenum unpackType, dom::ImageData* imageData,
ErrorResult& out_rv)
{
MOZ_CRASH("Not Implemented.");
GenerateWarning("texSubImage3D: Not implemented.");
}
void
WebGL2Context::CopyTexSubImage3D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoff