mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
365
dom/canvas/WebGLObjectModel.h
Normal file
365
dom/canvas/WebGLObjectModel.h
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
/* -*- 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 WEBGLOBJECTMODEL_H_
|
||||
#define WEBGLOBJECTMODEL_H_
|
||||
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
|
||||
#include "WebGLTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename> class LinkedList;
|
||||
class WebGLContext;
|
||||
|
||||
////
|
||||
|
||||
// This class is a mixin for objects that are tied to a specific
|
||||
// context (which is to say, all of them). They provide initialization
|
||||
// as well as comparison with the current context.
|
||||
class WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
WebGLContext* const mContext;
|
||||
private:
|
||||
const uint32_t mContextGeneration;
|
||||
|
||||
public:
|
||||
explicit WebGLContextBoundObject(WebGLContext* webgl);
|
||||
|
||||
bool IsCompatibleWithContext(const WebGLContext* other) const;
|
||||
};
|
||||
|
||||
////
|
||||
|
||||
class WebGLDeletableObject : public WebGLContextBoundObject
|
||||
{
|
||||
template<typename> friend class WebGLRefCountedObject;
|
||||
|
||||
private:
|
||||
enum DeletionStatus { Default, DeleteRequested, Deleted };
|
||||
|
||||
DeletionStatus mDeletionStatus;
|
||||
|
||||
////
|
||||
|
||||
explicit WebGLDeletableObject(WebGLContext* webgl)
|
||||
: WebGLContextBoundObject(webgl)
|
||||
, mDeletionStatus(Default)
|
||||
{ }
|
||||
|
||||
~WebGLDeletableObject() {
|
||||
MOZ_ASSERT(mDeletionStatus == Deleted,
|
||||
"Derived class destructor must call DeleteOnce().");
|
||||
}
|
||||
|
||||
public:
|
||||
bool IsDeleted() const { return mDeletionStatus == Deleted; }
|
||||
bool IsDeleteRequested() const { return mDeletionStatus != Default; }
|
||||
};
|
||||
|
||||
/* Each WebGL object class WebGLFoo wants to:
|
||||
* - inherit WebGLRefCountedObject<WebGLFoo>
|
||||
* - implement a Delete() method
|
||||
* - have its destructor call DeleteOnce()
|
||||
*
|
||||
* This base class provides two features to WebGL object types:
|
||||
* 1. support for OpenGL object reference counting
|
||||
* 2. support for OpenGL deletion statuses
|
||||
*
|
||||
***** 1. OpenGL object reference counting *****
|
||||
*
|
||||
* WebGL objects such as WebGLTexture's really have two different refcounts:
|
||||
* the XPCOM refcount, that is directly exposed to JavaScript, and the OpenGL
|
||||
* refcount.
|
||||
*
|
||||
* For example, when in JavaScript one does: var newname = existingTexture;
|
||||
* that increments the XPCOM refcount, but doesn't affect the OpenGL refcount.
|
||||
* When one attaches the texture to a framebuffer object, that does increment
|
||||
* its OpenGL refcount (and also its XPCOM refcount, to prevent the regular
|
||||
* XPCOM refcounting mechanism from destroying objects prematurely).
|
||||
*
|
||||
* The actual OpenGL refcount is opaque to us (it's internal to the OpenGL
|
||||
* implementation) but is affects the WebGL semantics that we have to implement:
|
||||
* for example, a WebGLTexture that is attached to a WebGLFramebuffer must not
|
||||
* be actually deleted, even if deleteTexture has been called on it, and even
|
||||
* if JavaScript doesn't have references to it anymore. We can't just rely on
|
||||
* OpenGL to keep alive the underlying OpenGL texture for us, for a variety of
|
||||
* reasons, most importantly: we'd need to know when OpenGL objects are actually
|
||||
* deleted, and OpenGL doesn't notify us about that, so we would have to query
|
||||
* status very often with glIsXxx calls which isn't practical.
|
||||
*
|
||||
* This means that we have to keep track of the OpenGL refcount ourselves,
|
||||
* in addition to the XPCOM refcount.
|
||||
*
|
||||
* This class implements such a refcount, see the mWebGLRefCnt
|
||||
* member. In order to avoid name clashes (with regular XPCOM refcounting)
|
||||
* in the derived class, we prefix members with 'WebGL', whence the names
|
||||
* WebGLAddRef, WebGLRelease, etc.
|
||||
*
|
||||
* In practice, WebGLAddRef and WebGLRelease are only called from the
|
||||
* WebGLRefPtr class.
|
||||
*
|
||||
***** 2. OpenGL deletion statuses *****
|
||||
*
|
||||
* In OpenGL, an object can go through 3 different deletion statuses during its
|
||||
* lifetime, which correspond to the 3 enum values for DeletionStatus in this
|
||||
* class:
|
||||
* - the Default status, which it has from its creation to when the suitable
|
||||
* glDeleteXxx function is called on it;
|
||||
* - the DeleteRequested status, which is has from when the suitable
|
||||
* glDeleteXxx function is called on it to when it is no longer referenced by
|
||||
* other OpenGL objects. For example, a texture that is attached to a
|
||||
* non-current FBO will enter that status when glDeleteTexture is called on
|
||||
* it. For objects with that status, GL_DELETE_STATUS queries return true,
|
||||
* but glIsXxx functions still return true.
|
||||
* - the Deleted status, which is the status of objects on which the suitable
|
||||
* glDeleteXxx function has been called, and that are not referenced by other
|
||||
* OpenGL objects.
|
||||
*
|
||||
* This state is stored in the mDeletionStatus member of this class.
|
||||
*
|
||||
* When the GL refcount hits zero, if the status is DeleteRequested then we call
|
||||
* the Delete() method on the derived class and the status becomes Deleted. This
|
||||
* is what the MaybeDelete() function does.
|
||||
*
|
||||
* The DeleteOnce() function implemented here is a helper to ensure that we
|
||||
* don't call Delete() twice on the same object. Since the derived class's
|
||||
* destructor needs to call DeleteOnce() which calls Delete(), we can't allow
|
||||
* either to be virtual. Strictly speaking, we could let them be virtual if the
|
||||
* derived class were final, but that would be impossible to enforce and would
|
||||
* lead to strange bugs if it were subclassed.
|
||||
*
|
||||
* This WebGLRefCountedObject class takes the Derived type as template
|
||||
* parameter, as a means to allow DeleteOnce to call Delete() on the Derived
|
||||
* class, without either method being virtual. This is a common C++ pattern
|
||||
* known as the "curiously recursive template pattern (CRTP)".
|
||||
*/
|
||||
|
||||
template<typename Derived>
|
||||
class WebGLRefCountedObject : public WebGLDeletableObject
|
||||
{
|
||||
friend class WebGLContext;
|
||||
template<typename T> friend void ClearLinkedList(LinkedList<T>& list);
|
||||
|
||||
private:
|
||||
nsAutoRefCnt mWebGLRefCnt;
|
||||
|
||||
public:
|
||||
explicit WebGLRefCountedObject(WebGLContext* webgl)
|
||||
: WebGLDeletableObject(webgl)
|
||||
{ }
|
||||
|
||||
~WebGLRefCountedObject() {
|
||||
MOZ_ASSERT(mWebGLRefCnt == 0,
|
||||
"Destroying WebGL object still referenced by other WebGL"
|
||||
" objects.");
|
||||
}
|
||||
|
||||
// called by WebGLRefPtr
|
||||
void WebGLAddRef() {
|
||||
++mWebGLRefCnt;
|
||||
}
|
||||
|
||||
// called by WebGLRefPtr
|
||||
void WebGLRelease() {
|
||||
MOZ_ASSERT(mWebGLRefCnt > 0,
|
||||
"Releasing WebGL object with WebGL refcnt already zero");
|
||||
--mWebGLRefCnt;
|
||||
MaybeDelete();
|
||||
}
|
||||
|
||||
// this is the function that WebGL.deleteXxx() functions want to call
|
||||
void RequestDelete() {
|
||||
if (mDeletionStatus == Default)
|
||||
mDeletionStatus = DeleteRequested;
|
||||
MaybeDelete();
|
||||
}
|
||||
|
||||
protected:
|
||||
void DeleteOnce() {
|
||||
if (mDeletionStatus != Deleted) {
|
||||
static_cast<Derived*>(this)->Delete();
|
||||
mDeletionStatus = Deleted;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void MaybeDelete() {
|
||||
if (mWebGLRefCnt == 0 &&
|
||||
mDeletionStatus == DeleteRequested)
|
||||
{
|
||||
DeleteOnce();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* This WebGLRefPtr class is meant to be used for references between WebGL
|
||||
* objects. For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's
|
||||
* attached to it.
|
||||
*
|
||||
* Why the need for a separate refptr class? The only special thing that
|
||||
* WebGLRefPtr does is that it increments and decrements the WebGL refcount of
|
||||
* WebGLRefCountedObject's, in addition to incrementing and decrementing the
|
||||
* usual XPCOM refcount.
|
||||
*
|
||||
* This means that by using a WebGLRefPtr instead of a nsRefPtr, you ensure that
|
||||
* the WebGL refcount is incremented, which means that the object will be kept
|
||||
* alive by this reference even if the matching webgl.deleteXxx() function is
|
||||
* called on it.
|
||||
*/
|
||||
template<typename T>
|
||||
class WebGLRefPtr
|
||||
{
|
||||
public:
|
||||
WebGLRefPtr()
|
||||
: mRawPtr(0)
|
||||
{}
|
||||
|
||||
WebGLRefPtr(const WebGLRefPtr<T>& smartPtr)
|
||||
: mRawPtr(smartPtr.mRawPtr)
|
||||
{
|
||||
AddRefOnPtr(mRawPtr);
|
||||
}
|
||||
|
||||
explicit WebGLRefPtr(T* rawPtr)
|
||||
: mRawPtr(rawPtr)
|
||||
{
|
||||
AddRefOnPtr(mRawPtr);
|
||||
}
|
||||
|
||||
~WebGLRefPtr() {
|
||||
ReleasePtr(mRawPtr);
|
||||
}
|
||||
|
||||
WebGLRefPtr<T>&
|
||||
operator=(const WebGLRefPtr<T>& rhs)
|
||||
{
|
||||
assign_with_AddRef(rhs.mRawPtr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
WebGLRefPtr<T>&
|
||||
operator=(T* rhs)
|
||||
{
|
||||
assign_with_AddRef(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return static_cast<T*>(mRawPtr);
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
|
||||
MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator->()!");
|
||||
return get();
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator*()!");
|
||||
return *get();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void AddRefOnPtr(T* rawPtr) {
|
||||
if (rawPtr) {
|
||||
rawPtr->WebGLAddRef();
|
||||
rawPtr->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
static void ReleasePtr(T* rawPtr) {
|
||||
if (rawPtr) {
|
||||
rawPtr->WebGLRelease(); // must be done first before Release(), as Release() might actually destroy the object
|
||||
rawPtr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void assign_with_AddRef(T* rawPtr) {
|
||||
AddRefOnPtr(rawPtr);
|
||||
assign_assuming_AddRef(rawPtr);
|
||||
}
|
||||
|
||||
void assign_assuming_AddRef(T* newPtr) {
|
||||
T* oldPtr = mRawPtr;
|
||||
mRawPtr = newPtr;
|
||||
ReleasePtr(oldPtr);
|
||||
}
|
||||
|
||||
protected:
|
||||
T* mRawPtr;
|
||||
};
|
||||
|
||||
// this class is a mixin for GL objects that have dimensions
|
||||
// that we need to track.
|
||||
class WebGLRectangleObject
|
||||
{
|
||||
public:
|
||||
WebGLRectangleObject()
|
||||
: mWidth(0)
|
||||
, mHeight(0)
|
||||
{}
|
||||
|
||||
WebGLRectangleObject(GLsizei width, GLsizei height)
|
||||
: mWidth(width)
|
||||
, mHeight(height)
|
||||
{}
|
||||
|
||||
GLsizei Width() const { return mWidth; }
|
||||
void width(GLsizei value) { mWidth = value; }
|
||||
|
||||
GLsizei Height() const { return mHeight; }
|
||||
void height(GLsizei value) { mHeight = value; }
|
||||
|
||||
void setDimensions(GLsizei width, GLsizei height) {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
}
|
||||
|
||||
void setDimensions(WebGLRectangleObject* rect) {
|
||||
if (rect) {
|
||||
mWidth = rect->Width();
|
||||
mHeight = rect->Height();
|
||||
} else {
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasSameDimensionsAs(const WebGLRectangleObject& other) const {
|
||||
return Width() == other.Width() && Height() == other.Height();
|
||||
}
|
||||
|
||||
protected:
|
||||
GLsizei mWidth;
|
||||
GLsizei mHeight;
|
||||
};
|
||||
|
||||
}// namespace mozilla
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& field)
|
||||
{
|
||||
field = nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
|
||||
const mozilla::WebGLRefPtr<T>& field,
|
||||
const char* name,
|
||||
uint32_t flags = 0)
|
||||
{
|
||||
CycleCollectionNoteChild(callback, field.get(), name, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue