зеркало из https://github.com/mozilla/pjs.git
b=571831; use the new CreateOffscreen API in WebGL; r=bjacob
This commit is contained in:
Родитель
2f984cc829
Коммит
95c827946f
|
@ -99,6 +99,106 @@ WebGLContext::WebGLContext()
|
|||
|
||||
WebGLContext::~WebGLContext()
|
||||
{
|
||||
DestroyResourcesAndContext();
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteTextureFunction(const PRUint32& aKey, WebGLTexture *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Texture is still in mMapTextures, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteTextures(1, &name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteBufferFunction(const PRUint32& aKey, WebGLBuffer *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Buffer is still in mMapBuffers, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteBuffers(1, &name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteFramebufferFunction(const PRUint32& aKey, WebGLFramebuffer *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Framebuffer is still in mMapFramebuffers, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteFramebuffers(1, &name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteRenderbufferFunction(const PRUint32& aKey, WebGLRenderbuffer *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Renderbuffer is still in mMapRenderbuffers, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteRenderbuffers(1, &name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteProgramFunction(const PRUint32& aKey, WebGLProgram *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Program is still in mMapPrograms, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteProgram(name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteShaderFunction(const PRUint32& aKey, WebGLShader *aValue, void *aData)
|
||||
{
|
||||
gl::GLContext *gl = (gl::GLContext *) aData;
|
||||
NS_ASSERTION(!aValue->Deleted(), "Shader is still in mMapShaders, but is deleted?");
|
||||
GLuint name = aValue->GLName();
|
||||
gl->fDeleteShader(name);
|
||||
aValue->Delete();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DestroyResourcesAndContext()
|
||||
{
|
||||
if (!gl)
|
||||
return;
|
||||
|
||||
gl->MakeCurrent();
|
||||
|
||||
mMapTextures.EnumerateRead(DeleteTextureFunction, gl);
|
||||
mMapTextures.Clear();
|
||||
|
||||
mMapBuffers.EnumerateRead(DeleteBufferFunction, gl);
|
||||
mMapBuffers.Clear();
|
||||
|
||||
mMapPrograms.EnumerateRead(DeleteProgramFunction, gl);
|
||||
mMapPrograms.Clear();
|
||||
|
||||
mMapShaders.EnumerateRead(DeleteShaderFunction, gl);
|
||||
mMapShaders.Clear();
|
||||
|
||||
mMapFramebuffers.EnumerateRead(DeleteFramebufferFunction, gl);
|
||||
mMapFramebuffers.Clear();
|
||||
|
||||
mMapRenderbuffers.EnumerateRead(DeleteRenderbufferFunction, gl);
|
||||
mMapRenderbuffers.Clear();
|
||||
|
||||
// We just got rid of everything, so the context had better
|
||||
// have been going away.
|
||||
printf_stderr("--- WebGL context destroyed: %p\n", gl.get());
|
||||
|
||||
gl = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -141,38 +241,42 @@ WebGLContext::SetCanvasElement(nsHTMLCanvasElement* aParentCanvas)
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
{
|
||||
if (mWidth == width && mHeight == height)
|
||||
return NS_OK;
|
||||
|
||||
// If we already have a gl context, then we just need to resize
|
||||
// FB0.
|
||||
if (gl &&
|
||||
gl->ResizeOffscreen(gfxIntSize(width, height)))
|
||||
{
|
||||
// everything's good, we're done here
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We're going to create an entirely new context. If our
|
||||
// generation is not 0 right now (that is, if this isn't the first
|
||||
// context we're creating), we may have to dispatch a context lost
|
||||
// event.
|
||||
|
||||
// If incrementing the generation would cause overflow,
|
||||
// don't allow it. Allowing this would allow us to use
|
||||
// resource handles created from older context generations.
|
||||
if (!(mGeneration+1).valid())
|
||||
return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
|
||||
|
||||
if (mWidth == width && mHeight == height)
|
||||
return NS_OK;
|
||||
|
||||
if (gl) {
|
||||
// hey we already have something
|
||||
if (gl->Resize(gfxIntSize(width, height))) {
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
gl->fViewport(0, 0, mWidth, mHeight);
|
||||
gl->fClearColor(0, 0, 0, 0);
|
||||
gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// great success!
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// We're going to recreate our context, so make sure we clean up
|
||||
// after ourselves.
|
||||
DestroyResourcesAndContext();
|
||||
|
||||
gl::ContextFormat format(gl::ContextFormat::BasicRGBA32);
|
||||
format.depth = 16;
|
||||
format.minDepth = 1;
|
||||
|
||||
gl = gl::GLContextProvider::CreatePBuffer(gfxIntSize(width, height),
|
||||
gl::GLContextProvider::GetGlobalContext(),
|
||||
format);
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
|
@ -186,17 +290,14 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
#endif
|
||||
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = gl::GLContextProviderOSMesa::CreatePBuffer(gfxIntSize(width, height),
|
||||
nsnull,
|
||||
format);
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (!InitAndValidateGL()) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
else {
|
||||
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
}
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
@ -205,12 +306,25 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
// increment the generation number
|
||||
++mGeneration;
|
||||
|
||||
#if 0
|
||||
if (mGeneration > 0) {
|
||||
// XXX dispatch context lost event
|
||||
}
|
||||
#endif
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
// Make sure that we clear this out, otherwise
|
||||
// we'll end up displaying random memory
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, gl->GetOffscreenFBO());
|
||||
gl->fViewport(0, 0, mWidth, mHeight);
|
||||
gl->fClearColor(0, 0, 0, 0);
|
||||
gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
#ifdef USE_GLES2
|
||||
gl->fClearDepthf(0.0f);
|
||||
#else
|
||||
gl->fClearDepth(0.0f);
|
||||
#endif
|
||||
gl->fClearStencil(0);
|
||||
gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -348,26 +462,19 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer,
|
|||
// data with the gl context directly, or may provide a surface to which it renders (this is the case
|
||||
// of OSMesa contexts), in which case we want to initialize data with that surface.
|
||||
|
||||
void* native_pbuffer = gl->GetNativeData(gl::GLContext::NativePBuffer);
|
||||
void* native_surface = gl->GetNativeData(gl::GLContext::NativeImageSurface);
|
||||
|
||||
if (native_pbuffer) {
|
||||
data.mGLContext = gl.get();
|
||||
}
|
||||
else if (native_surface) {
|
||||
if (native_surface) {
|
||||
data.mSurface = static_cast<gfxASurface*>(native_surface);
|
||||
}
|
||||
else {
|
||||
NS_WARNING("The GLContext has neither a native PBuffer nor a native surface!");
|
||||
return nsnull;
|
||||
} else {
|
||||
data.mGLContext = gl.get();
|
||||
}
|
||||
|
||||
data.mSize = nsIntSize(mWidth, mHeight);
|
||||
data.mGLBufferIsPremultiplied = PR_FALSE;
|
||||
|
||||
canvasLayer->Initialize(data);
|
||||
// once we support GL context attributes, we'll set the right thing here
|
||||
canvasLayer->SetIsOpaqueContent(PR_FALSE);
|
||||
canvasLayer->SetIsOpaqueContent(gl->CreationFormat().alpha == 0 ? PR_TRUE : PR_FALSE);
|
||||
canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight));
|
||||
|
||||
mInvalidated = PR_FALSE;
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "Layers.h"
|
||||
|
||||
#include "CheckedInt.h"
|
||||
|
@ -359,6 +359,7 @@ protected:
|
|||
PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
|
||||
|
||||
void Invalidate();
|
||||
void DestroyResourcesAndContext();
|
||||
|
||||
void MakeContextCurrent() { gl->MakeCurrent(); }
|
||||
|
||||
|
|
|
@ -227,7 +227,11 @@ WebGLContext::BindFramebuffer(WebGLenum target, nsIWebGLFramebuffer *fbobj)
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (isNull) {
|
||||
gl->fBindFramebuffer(target, gl->GetOffscreenFBO());
|
||||
} else {
|
||||
gl->fBindFramebuffer(target, framebuffername);
|
||||
}
|
||||
|
||||
mBoundFramebuffer = wfb;
|
||||
|
||||
|
@ -503,7 +507,9 @@ NS_IMETHODIMP
|
|||
WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval)
|
||||
{
|
||||
MakeContextCurrent();
|
||||
// XXX check target
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnum("CheckFramebufferStatus: target must be FRAMEBUFFER");
|
||||
|
||||
*retval = gl->fCheckFramebufferStatus(target);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1013,8 +1019,11 @@ WebGLContext::FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment, We
|
|||
if (rbtarget != LOCAL_GL_RENDERBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("FramebufferRenderbuffer: cannot modify framebuffer 0");
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (mBoundFramebuffer && attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
mBoundFramebuffer->setDimensions(wrb);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
@ -1055,8 +1064,11 @@ WebGLContext::FramebufferTexture2D(WebGLenum target,
|
|||
if (level != 0)
|
||||
return ErrorInvalidValue("FramebufferTexture2D: level must be 0");
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("FramebufferTexture2D: cannot modify framebuffer 0");
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (mBoundFramebuffer && attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
mBoundFramebuffer->setDimensions(wtex);
|
||||
|
||||
// XXXXX we need to store/reference this attachment!
|
||||
|
@ -1544,14 +1556,49 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta
|
|||
return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: attachment", attachment);
|
||||
}
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("GetFramebufferAttachmentParameter: cannot query framebuffer 0");
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
GLint atype = 0;
|
||||
gl->fGetFramebufferAttachmentParameteriv(target, attachment, LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atype);
|
||||
|
||||
if (atype == LOCAL_GL_RENDERBUFFER) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
||||
wrval->SetAsInt32(atype);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: {
|
||||
GLint i = 0;
|
||||
gl->fGetFramebufferAttachmentParameteriv(target, attachment, pname, &i);
|
||||
WebGLRenderbuffer *rb = mMapRenderbuffers.GetWeak(PRUint32(i));
|
||||
NS_ASSERTION(rb, "Expected to find renderbuffer in table, but it's not there?");
|
||||
wrval->SetAsISupports(rb);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnum("GetFramebufferAttachmentParameter: invalid parameter");
|
||||
}
|
||||
} else if (atype == LOCAL_GL_TEXTURE) {
|
||||
switch (pname) {
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
|
||||
wrval->SetAsInt32(atype);
|
||||
break;
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: {
|
||||
GLint i = 0;
|
||||
gl->fGetFramebufferAttachmentParameteriv(target, attachment, pname, &i);
|
||||
WebGLTexture *tex = mMapTextures.GetWeak(PRUint32(i));
|
||||
NS_ASSERTION(tex, "Expected to find texture in table, but it's not there?");
|
||||
wrval->SetAsISupports(tex);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
|
||||
{
|
||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: {
|
||||
GLint i = 0;
|
||||
gl->fGetFramebufferAttachmentParameteriv(target, attachment, pname, &i);
|
||||
wrval->SetAsInt32(i);
|
||||
|
@ -1559,7 +1606,11 @@ WebGLContext::GetFramebufferAttachmentParameter(WebGLenum target, WebGLenum atta
|
|||
break;
|
||||
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: parameter", pname);
|
||||
return ErrorInvalidEnum("GetFramebufferAttachmentParameter: invalid parameter");
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Unknown framebuffer attachment type?");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*retval = wrval.forget().get();
|
||||
|
|
|
@ -384,7 +384,7 @@ WebGLContext::InitAndValidateGL()
|
|||
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, (GLint*) &mGLMaxVertexAttribs);
|
||||
if (mGLMaxVertexAttribs < 8) {
|
||||
LogMessage("GL_MAX_VERTEX_ATTRIBS is < 8!");
|
||||
LogMessage("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ WebGLContext::InitAndValidateGL()
|
|||
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
|
||||
gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, (GLint*) &mGLMaxTextureUnits);
|
||||
if (mGLMaxTextureUnits < 8) {
|
||||
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is < 8!");
|
||||
LogMessage("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче