mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge.
This commit is contained in:
commit
b8be454ea7
@ -212,7 +212,7 @@ nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *v
|
||||
|
||||
/*
|
||||
* ReadPixels takes:
|
||||
* TexImage2D(int, int, int, int, uint, uint, ArrayBufferView)
|
||||
* ReadPixels(int, int, int, int, uint, uint, ArrayBufferView)
|
||||
*/
|
||||
static JSBool
|
||||
nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
@ -230,8 +230,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
||||
return JS_FALSE;
|
||||
|
||||
// XXX we currently allow passing only 6 args to support the API. Eventually drop that.
|
||||
if (argc < 6)
|
||||
if (argc < 7)
|
||||
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
@ -244,40 +243,8 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
GET_UINT32_ARG(argv4, 4);
|
||||
GET_UINT32_ARG(argv5, 5);
|
||||
|
||||
if (argc == 6) {
|
||||
/*** BEGIN old API deprecated code. Eventually drop that. ***/
|
||||
// the code here is ugly, but temporary. It comes from the old ReadPixels implementation.
|
||||
// Remove it as soon as it's OK to drop the old API.
|
||||
|
||||
PRInt32 byteLength;
|
||||
rv = self->ReadPixels_byteLength_old_API_deprecated(argv2, argv3, argv4, argv5, &byteLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JSObject *abufObject = js_CreateArrayBuffer(cx, byteLength);
|
||||
if (!abufObject) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(abufObject);
|
||||
|
||||
rv = self->ReadPixels_buf(
|
||||
argv0, argv1, argv2, argv3, argv4, argv5, abuf);
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc_qsThrow(cx, NS_ERROR_FAILURE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
JSObject *retval = js_CreateTypedArrayWithBuffer(cx, js::TypedArray::TYPE_UINT8,
|
||||
abufObject, 0, byteLength);
|
||||
|
||||
*vp = OBJECT_TO_JSVAL(retval);
|
||||
return JS_TRUE; // return here to be unaffected by the *vp = JSVAL_VOID; below
|
||||
|
||||
/*** END old API deprecated code ***/
|
||||
} else if (argc == 7 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[6]))
|
||||
if (argc == 7 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[6]))
|
||||
{
|
||||
JSObject *argv6 = JSVAL_TO_OBJECT(argv[6]);
|
||||
if (js_IsArrayBuffer(argv6)) {
|
||||
@ -306,7 +273,7 @@ nsICanvasRenderingContextWebGL_ReadPixels(JSContext *cx, uintN argc, jsval *vp)
|
||||
|
||||
/*
|
||||
* TexImage2D takes:
|
||||
* TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)\
|
||||
* TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)
|
||||
* TexImage2D(uint, int, uint, uint, uint, nsIDOMElement)
|
||||
* TexImage2D(uint, int, uint, uint, uint, ImageData)
|
||||
*/
|
||||
@ -326,9 +293,7 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
|
||||
return JS_FALSE;
|
||||
|
||||
// XXX we currently allow passing only 3 args to support the API. Eventually drop that.
|
||||
// if (argc < 6 || argc == 7 || argc == 8)
|
||||
if (argc < 3)
|
||||
if (argc < 6 || argc == 7 || argc == 8)
|
||||
return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
@ -337,22 +302,9 @@ nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
|
||||
GET_UINT32_ARG(argv0, 0);
|
||||
GET_INT32_ARG(argv1, 1);
|
||||
|
||||
if (argc > 2 && JSVAL_IS_OBJECT(argv[2])) {
|
||||
// the old API. Eventually drop that.
|
||||
|
||||
nsIDOMElement *elt;
|
||||
xpc_qsSelfRef eltRef;
|
||||
rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[2], &elt, &eltRef.ptr, &argv[2]);
|
||||
if (NS_FAILED(rv)) return JS_FALSE;
|
||||
|
||||
GET_OPTIONAL_UINT32_ARG(argv3, 3);
|
||||
GET_OPTIONAL_UINT32_ARG(argv4, 4);
|
||||
|
||||
rv = self->TexImage2D_dom_old_API_deprecated(argv0, argv1, elt, argv3, argv4);
|
||||
} else if (argc > 5 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[5]))
|
||||
if (argc > 5 &&
|
||||
!JSVAL_IS_PRIMITIVE(argv[5]))
|
||||
{
|
||||
|
||||
// implement the variants taking a DOMElement as argv[5]
|
||||
GET_UINT32_ARG(argv2, 2);
|
||||
GET_UINT32_ARG(argv3, 3);
|
||||
|
@ -56,6 +56,8 @@
|
||||
|
||||
#include "GLContextProvider.h"
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
@ -275,29 +277,77 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
||||
format.depth = 16;
|
||||
format.minDepth = 1;
|
||||
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// On Windows, we may have a choice of backends, including straight
|
||||
// OpenGL, D3D through ANGLE via EGL, or straight EGL/GLES2.
|
||||
// We don't differentiate the latter two yet, but we allow for
|
||||
// a env var to try EGL first, instead of last.
|
||||
bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL") != nsnull;
|
||||
|
||||
// if we want EGL, try it first
|
||||
if (!gl && preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if it failed, then try the default provider, whatever that is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
// if that failed, and we weren't already preferring EGL, try it now.
|
||||
if (!gl && !preferEGL) {
|
||||
gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// other platforms just use whatever the default is
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl && !InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// last chance, try OSMesa
|
||||
if (!gl) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (gl) {
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = nsnull;
|
||||
} else {
|
||||
// make sure we notify always in this case, because it's likely going to be
|
||||
// painfully slow
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gl) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
printf_stderr ("--- WebGL context created: %p\n", gl.get());
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
#else
|
||||
// Check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
if (gl->IsGLES2()) {
|
||||
// On native GLES2, no need to validate, the compiler will do it
|
||||
mShaderValidation = PR_FALSE;
|
||||
} else {
|
||||
// Otherwise, check the shader validator pref
|
||||
nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(prefService != nsnull, NS_ERROR_FAILURE);
|
||||
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
#endif
|
||||
|
||||
if (!InitAndValidateGL()) {
|
||||
gl = gl::GLContextProviderOSMesa::CreateOffscreen(gfxIntSize(width, height), format);
|
||||
if (!InitAndValidateGL()) {
|
||||
LogMessage("WebGL: Can't get a usable OpenGL context.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LogMessage("WebGL: Using software rendering via OSMesa");
|
||||
prefService->GetBoolPref("webgl.shader_validator", &mShaderValidation);
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
|
@ -2409,58 +2409,6 @@ WebGLContext::ReadPixels_buf(WebGLint x, WebGLint y, WebGLsizei width, WebGLsize
|
||||
pixels ? pixels->byteLength : 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::ReadPixels_byteLength_old_API_deprecated(WebGLsizei width, WebGLsizei height,
|
||||
WebGLenum format, WebGLenum type, WebGLsizei *retval)
|
||||
{
|
||||
*retval = 0;
|
||||
if (width < 0 || height < 0)
|
||||
return ErrorInvalidValue("ReadPixels: negative size passed");
|
||||
|
||||
PRUint32 size = 0;
|
||||
switch (format) {
|
||||
case LOCAL_GL_ALPHA:
|
||||
size = 1;
|
||||
break;
|
||||
case LOCAL_GL_RGB:
|
||||
size = 3;
|
||||
break;
|
||||
case LOCAL_GL_RGBA:
|
||||
size = 4;
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("ReadPixels: format", format);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
// case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||
case LOCAL_GL_UNSIGNED_BYTE:
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("ReadPixels: type", type);
|
||||
}
|
||||
PRUint32 packAlignment;
|
||||
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*) &packAlignment);
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
|
||||
|
||||
// alignedRowSize = row size rounded up to next multiple of
|
||||
// packAlignment which is a power of 2
|
||||
CheckedUint32 checked_alignedRowSize
|
||||
= ((checked_plainRowSize + packAlignment-1) / packAlignment) * packAlignment;
|
||||
|
||||
CheckedUint32 checked_neededByteLength = (height-1)*checked_alignedRowSize + checked_plainRowSize;
|
||||
|
||||
if (!checked_neededByteLength.valid())
|
||||
return ErrorInvalidOperation("ReadPixels: integer overflow computing the needed buffer size");
|
||||
|
||||
*retval = checked_neededByteLength.value();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height)
|
||||
{
|
||||
@ -3229,27 +3177,6 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna
|
||||
isurf->Data(), byteLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::TexImage2D_dom_old_API_deprecated(WebGLenum target, WebGLint level, nsIDOMElement *elt,
|
||||
PRBool flipY, PRBool premultiplyAlpha)
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> isurf;
|
||||
|
||||
nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf),
|
||||
flipY, premultiplyAlpha);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ASSERTION(isurf->Stride() == isurf->Width() * 4, "Bad stride!");
|
||||
|
||||
PRUint32 byteLength = isurf->Stride() * isurf->Height();
|
||||
|
||||
return TexImage2D_base(target, level, LOCAL_GL_RGBA,
|
||||
isurf->Width(), isurf->Height(), 0,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data(), byteLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::TexSubImage2D(PRInt32 dummy)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ interface nsIWebGLUniformLocation : nsISupports
|
||||
};
|
||||
|
||||
|
||||
[scriptable, uuid(f02c85e0-8305-11de-abe2-000c29206271)]
|
||||
[scriptable, uuid(2f21ca21-9720-4eee-ad94-27eefe4f72dc)]
|
||||
interface nsICanvasRenderingContextWebGL : nsISupports
|
||||
{
|
||||
//
|
||||
@ -725,8 +725,6 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
||||
in WebGLenum format, in WebGLenum type, in WebGLArrayPtr pixels);
|
||||
[noscript] void readPixels_buf(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
|
||||
in WebGLenum format, in WebGLenum type, in WebGLArrayBufferPtr pixels);
|
||||
[noscript] WebGLsizei readPixels_byteLength_old_API_deprecated(
|
||||
in WebGLsizei width, in WebGLsizei height, in WebGLenum format, in WebGLenum type);
|
||||
|
||||
//void glReleaseShaderCompiler();
|
||||
|
||||
@ -754,9 +752,6 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
||||
// HTMLImageElement, HTMLCanvasElement, HTMLVideoElement
|
||||
[noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
|
||||
in WebGLenum format, in WebGLenum type, in nsIDOMElement element);
|
||||
// XXX the old API. Eventually drop that.
|
||||
[noscript] void TexImage2D_dom_old_API_deprecated(in WebGLenum target, in WebGLint level,
|
||||
in nsIDOMElement element, in PRBool flipY, in PRBool premultiplyAlpha);
|
||||
|
||||
void texSubImage2D([optional] in long dummy);
|
||||
[noscript] void texSubImage2D_buf(in WebGLenum target, in WebGLint level,
|
||||
|
@ -172,6 +172,13 @@ public:
|
||||
*/
|
||||
virtual gfxIntSize GetCurrentSize() = 0;
|
||||
|
||||
/**
|
||||
* Set a new layer manager for this image container. It must be
|
||||
* either of the same type as the container's current layer manager,
|
||||
* or null. TRUE is returned on success.
|
||||
*/
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager) = 0;
|
||||
|
||||
protected:
|
||||
LayerManager* mManager;
|
||||
|
||||
|
@ -142,12 +142,21 @@ public:
|
||||
LAYERS_D3D9
|
||||
};
|
||||
|
||||
LayerManager() : mUserData(nsnull)
|
||||
LayerManager() : mUserData(nsnull), mDestroyed(PR_FALSE)
|
||||
{
|
||||
InitLog();
|
||||
}
|
||||
virtual ~LayerManager() {}
|
||||
|
||||
/**
|
||||
* Release layers and resources held by this layer manager, and mark
|
||||
* it as destroyed. Should do any cleanup necessary in preparation
|
||||
* for its widget going away. After this call, only user data calls
|
||||
* are valid on the layer manager.
|
||||
*/
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
PRBool IsDestroyed() { return mDestroyed; }
|
||||
|
||||
/**
|
||||
* Start a new transaction. Nested transactions are not allowed so
|
||||
* there must be no transaction currently in progress.
|
||||
@ -297,6 +306,7 @@ public:
|
||||
protected:
|
||||
nsRefPtr<Layer> mRoot;
|
||||
void* mUserData;
|
||||
PRPackedBool mDestroyed;
|
||||
|
||||
// Print interesting information about this into aTo. Internally
|
||||
// used to implement Dump*() and Log*().
|
||||
@ -328,7 +338,9 @@ public:
|
||||
virtual ~Layer() {}
|
||||
|
||||
/**
|
||||
* Returns the LayoutManager this Layer belongs to. Cannot be null.
|
||||
* Returns the LayerManager this Layer belongs to. Note that the layer
|
||||
* manager might be in a destroyed state, at which point it's only
|
||||
* valid to set/get user data from it.
|
||||
*/
|
||||
LayerManager* Manager() { return mManager; }
|
||||
|
||||
@ -387,6 +399,7 @@ public:
|
||||
}
|
||||
Mutated();
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set a clip rect which will be applied to this layer as it is
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -226,6 +226,7 @@ public:
|
||||
virtual already_AddRefed<Image> GetCurrentImage();
|
||||
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
protected:
|
||||
Monitor mMonitor;
|
||||
@ -302,6 +303,20 @@ BasicImageContainer::GetCurrentSize()
|
||||
return !mImage ? gfxIntSize(0,0) : ToImageData(mImage)->GetSize();
|
||||
}
|
||||
|
||||
PRBool
|
||||
BasicImageContainer::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
if (aManager &&
|
||||
aManager->GetBackendType() != LayerManager::LAYERS_BASIC)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// for basic layers, we can just swap; no magic needed.
|
||||
mManager = aManager;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
already_AddRefed<ImageContainer>
|
||||
BasicLayerManager::CreateImageContainer()
|
||||
{
|
||||
|
@ -701,15 +701,9 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use mUpdatedRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
if (mGLContext->IsGLES2()) {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
} else {
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
isurf->Data());
|
||||
}
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
isurf);
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
@ -111,9 +111,15 @@ CanvasLayerD3D9::Updated(const nsIntRect& aRect)
|
||||
// For simplicity, we read the entire framebuffer for now -- in
|
||||
// the future we should use aRect, though with WebGL we don't
|
||||
// have an easy way to generate one.
|
||||
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
|
||||
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
destination);
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface(destination,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
tmpSurface);
|
||||
tmpSurface = nsnull;
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -130,6 +130,13 @@ ImageContainerD3D9::GetCurrentSize()
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ImageContainerD3D9::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
// we can't do anything here for now
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerD3D9::GetLayer()
|
||||
{
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
|
@ -54,12 +54,17 @@ using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
CanvasLayerOGL::~CanvasLayerOGL()
|
||||
void
|
||||
CanvasLayerOGL::Destroy()
|
||||
{
|
||||
mOGLManager->MakeCurrent();
|
||||
if (!mDestroyed) {
|
||||
if (mTexture) {
|
||||
GLContext *cx = mOGLManager->glForResources();
|
||||
cx->MakeCurrent();
|
||||
cx->fDeleteTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
if (mTexture) {
|
||||
gl()->fDeleteTextures(1, &mTexture);
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +121,10 @@ CanvasLayerOGL::MakeTexture()
|
||||
void
|
||||
CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mUpdatedRect.IsEmpty(),
|
||||
"CanvasLayer::Updated called more than once during a transaction!");
|
||||
|
||||
@ -123,13 +132,15 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
|
||||
mUpdatedRect.UnionRect(mUpdatedRect, aRect);
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
if (mCanvasGLContext &&
|
||||
mCanvasGLContext->GetContextType() == gl()->GetContextType())
|
||||
{
|
||||
if (gl()->BindOffscreenNeedsTexture(mCanvasGLContext) &&
|
||||
mTexture == 0)
|
||||
{
|
||||
MakeTexture();
|
||||
}
|
||||
} else if (mCanvasSurface) {
|
||||
} else {
|
||||
PRBool newTexture = mTexture == 0;
|
||||
if (newTexture) {
|
||||
MakeTexture();
|
||||
@ -140,40 +151,50 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect)
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> updatedAreaImageSurface;
|
||||
nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
|
||||
if (mCanvasSurface) {
|
||||
nsRefPtr<gfxASurface> sourceSurface = mCanvasSurface;
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
|
||||
if (!sourceSurface)
|
||||
sourceSurface = mCanvasSurface;
|
||||
}
|
||||
if (sourceSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
|
||||
sourceSurface = static_cast<gfxWindowsSurface*>(sourceSurface.get())->GetImageSurface();
|
||||
if (!sourceSurface)
|
||||
sourceSurface = mCanvasSurface;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// XXX don't copy, blah.
|
||||
// but need to deal with stride on the gl side; do this later.
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mCanvasSurface.get());
|
||||
if (s->Format() == gfxASurface::ImageFormatARGB32 ||
|
||||
s->Format() == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
updatedAreaImageSurface = ...;
|
||||
} else {
|
||||
NS_WARNING("surface with format that we can't handle");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
// XXX don't copy, blah.
|
||||
// but need to deal with stride on the gl side; do this later.
|
||||
if (mCanvasSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *s = static_cast<gfxImageSurface*>(mCanvasSurface.get());
|
||||
if (s->Format() == gfxASurface::ImageFormatARGB32 ||
|
||||
s->Format() == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
updatedAreaImageSurface = ...;
|
||||
} else {
|
||||
NS_WARNING("surface with format that we can't handle");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
{
|
||||
updatedAreaImageSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(updatedAreaImageSurface);
|
||||
ctx->Translate(gfxPoint(-mUpdatedRect.x, -mUpdatedRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(sourceSurface);
|
||||
ctx->Paint();
|
||||
}
|
||||
} else if (mCanvasGLContext) {
|
||||
updatedAreaImageSurface =
|
||||
new gfxImageSurface(gfxIntSize(mUpdatedRect.width, mUpdatedRect.height),
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(updatedAreaImageSurface);
|
||||
ctx->Translate(gfxPoint(-mUpdatedRect.x, -mUpdatedRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(sourceSurface);
|
||||
ctx->Paint();
|
||||
mCanvasGLContext->ReadPixelsIntoImageSurface(mUpdatedRect.x, mUpdatedRect.y,
|
||||
mUpdatedRect.width,
|
||||
mUpdatedRect.height,
|
||||
updatedAreaImageSurface);
|
||||
}
|
||||
|
||||
if (newTexture) {
|
||||
@ -222,12 +243,12 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
bool useGLContext = mCanvasGLContext &&
|
||||
mCanvasGLContext->GetContextType() == gl()->GetContextType();
|
||||
|
||||
if (useGLContext) {
|
||||
gl()->BindTex2DOffscreen(mCanvasGLContext);
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
program = mOGLManager->GetRGBALayerProgram();
|
||||
} else {
|
||||
program = mOGLManager->GetBGRALayerProgram();
|
||||
@ -244,7 +265,7 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination,
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
if (mCanvasGLContext) {
|
||||
if (useGLContext) {
|
||||
gl()->UnbindTex2DOffscreen(mCanvasGLContext);
|
||||
}
|
||||
|
||||
|
@ -56,14 +56,14 @@ public:
|
||||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
|
||||
~CanvasLayerOGL();
|
||||
~CanvasLayerOGL() { Destroy(); }
|
||||
|
||||
// CanvasLayer implementation
|
||||
virtual void Initialize(const Data& aData);
|
||||
virtual void Updated(const nsIntRect& aRect);
|
||||
|
||||
// LayerOGL implementation
|
||||
virtual void Destroy();
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
@ -53,10 +53,13 @@ public:
|
||||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
~ColorLayerOGL() { Destroy(); }
|
||||
|
||||
// LayerOGL Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
};
|
||||
|
@ -49,8 +49,18 @@ ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager)
|
||||
|
||||
ContainerLayerOGL::~ContainerLayerOGL()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
RemoveChild(mFirstChild);
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
while (mFirstChild) {
|
||||
GetFirstChildOGL()->Destroy();
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -60,6 +60,8 @@ public:
|
||||
/** LayerOGL implementation */
|
||||
Layer* GetLayer();
|
||||
|
||||
void Destroy();
|
||||
|
||||
LayerOGL* GetFirstChildOGL();
|
||||
|
||||
PRBool IsEmpty();
|
||||
|
@ -57,11 +57,13 @@ public:
|
||||
GLuint aTexture)
|
||||
: mContext(aContext), mTexture(aTexture)
|
||||
{
|
||||
NS_ASSERTION(aTexture, "TextureDeleter instantiated with nothing to do");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mTexture) {
|
||||
mContext->DestroyTexture(mTexture);
|
||||
}
|
||||
mContext->MakeCurrent();
|
||||
mContext->fDeleteTextures(1, &mTexture);
|
||||
|
||||
// Ensure context is released on the main thread
|
||||
mContext = nsnull;
|
||||
return NS_OK;
|
||||
@ -74,12 +76,15 @@ public:
|
||||
void
|
||||
GLTexture::Allocate(GLContext *aContext)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Can only allocate texture on main thread");
|
||||
NS_ASSERTION(aContext->IsGlobalSharedContext() ||
|
||||
NS_IsMainThread(), "Can only allocate texture on main thread or with cx sharing");
|
||||
|
||||
Release();
|
||||
|
||||
mContext = aContext;
|
||||
mTexture = mContext->CreateTexture();
|
||||
|
||||
mContext->MakeCurrent();
|
||||
mContext->fGenTextures(1, &mTexture);
|
||||
}
|
||||
|
||||
void
|
||||
@ -100,19 +105,20 @@ GLTexture::Release()
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
if (mTexture) {
|
||||
mContext->DestroyTexture(mTexture);
|
||||
mTexture = 0;
|
||||
if (mTexture) {
|
||||
if (NS_IsMainThread() || mContext->IsGlobalSharedContext()) {
|
||||
mContext->MakeCurrent();
|
||||
mContext->fDeleteTextures(1, &mTexture);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new TextureDeleter(mContext.forget(), mTexture);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
mContext = nsnull;
|
||||
return;
|
||||
|
||||
mTexture = 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new TextureDeleter(mContext.forget(), mTexture);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
mTexture = 0;
|
||||
mContext = nsnull;
|
||||
}
|
||||
|
||||
RecycleBin::RecycleBin()
|
||||
@ -133,7 +139,7 @@ RecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
|
||||
}
|
||||
|
||||
PRUint8*
|
||||
RecycleBin::TakeBuffer(PRUint32 aSize)
|
||||
RecycleBin::GetBuffer(PRUint32 aSize)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
@ -163,8 +169,8 @@ RecycleBin::RecycleTexture(GLTexture *aTexture, TextureType aType,
|
||||
}
|
||||
|
||||
void
|
||||
RecycleBin::TakeTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture)
|
||||
RecycleBin::GetTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
@ -184,6 +190,15 @@ ImageContainerOGL::ImageContainerOGL(LayerManagerOGL *aManager)
|
||||
{
|
||||
}
|
||||
|
||||
ImageContainerOGL::~ImageContainerOGL()
|
||||
{
|
||||
if (mManager) {
|
||||
NS_ASSERTION(mManager->GetBackendType() == LayerManager::LAYERS_OPENGL, "Wrong layer manager got assigned to ImageContainerOGL!");
|
||||
|
||||
static_cast<LayerManagerOGL*>(mManager)->ForgetImageContainer(this);
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainerOGL::CreateImage(const Image::Format *aFormats,
|
||||
PRUint32 aNumFormats)
|
||||
@ -193,7 +208,8 @@ ImageContainerOGL::CreateImage(const Image::Format *aFormats,
|
||||
}
|
||||
nsRefPtr<Image> img;
|
||||
if (aFormats[0] == Image::PLANAR_YCBCR) {
|
||||
img = new PlanarYCbCrImageOGL(mRecycleBin);
|
||||
img = new PlanarYCbCrImageOGL(static_cast<LayerManagerOGL*>(mManager),
|
||||
mRecycleBin);
|
||||
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
|
||||
img = new CairoImageOGL(static_cast<LayerManagerOGL*>(mManager));
|
||||
}
|
||||
@ -228,7 +244,47 @@ ImageContainerOGL::GetCurrentImage()
|
||||
already_AddRefed<gfxASurface>
|
||||
ImageContainerOGL::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
{
|
||||
return nsnull;
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
|
||||
if (!mActiveImage) {
|
||||
*aSize = gfxIntSize(0,0);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
GLContext *gl = nsnull;
|
||||
// tex1 will be RGBA or Y, tex2 will Cb, tex3 will be Cr
|
||||
GLuint tex1 = 0, tex2 = 0, tex3 = 0;
|
||||
gfxIntSize size;
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
|
||||
if (!yuvImage->HasData() || !yuvImage->HasTextures()) {
|
||||
*aSize = gfxIntSize(0, 0);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
size = yuvImage->mSize;
|
||||
gl = yuvImage->mTextures[0].GetGLContext();
|
||||
tex1 = yuvImage->mTextures[0].GetTextureID();
|
||||
tex2 = yuvImage->mTextures[1].GetTextureID();
|
||||
tex3 = yuvImage->mTextures[2].GetTextureID();
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(mActiveImage.get());
|
||||
size = cairoImage->mSize;
|
||||
gl = cairoImage->mTexture.GetGLContext();
|
||||
tex1 = cairoImage->mTexture.GetTextureID();
|
||||
}
|
||||
|
||||
// XXX TODO: read all textures in YCbCr case and convert to RGB
|
||||
// XXX Or maybe add a ReadYCbCrTextureImage that will take 3 textures
|
||||
// and return RGB, since we can render YCbCr to the temporary framebuffer.
|
||||
nsRefPtr<gfxImageSurface> s = gl->ReadTextureImage(tex1, size, LOCAL_GL_RGBA);
|
||||
*aSize = size;
|
||||
return s.forget();
|
||||
}
|
||||
|
||||
gfxIntSize
|
||||
@ -238,6 +294,7 @@ ImageContainerOGL::GetCurrentSize()
|
||||
if (!mActiveImage) {
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
|
||||
@ -246,7 +303,9 @@ ImageContainerOGL::GetCurrentSize()
|
||||
}
|
||||
return yuvImage->mSize;
|
||||
|
||||
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageOGL *cairoImage =
|
||||
static_cast<CairoImageOGL*>(mActiveImage.get());
|
||||
return cairoImage->mSize;
|
||||
@ -255,6 +314,38 @@ ImageContainerOGL::GetCurrentSize()
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ImageContainerOGL::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
if (!aManager) {
|
||||
// the layer manager just entirely went away
|
||||
|
||||
// XXX if we don't have context sharing, we should tell our images
|
||||
// that their textures are no longer valid.
|
||||
mManager = nsnull;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (aManager->GetBackendType() != LayerManager::LAYERS_OPENGL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
LayerManagerOGL* lmOld = static_cast<LayerManagerOGL*>(mManager);
|
||||
LayerManagerOGL* lmNew = static_cast<LayerManagerOGL*>(aManager);
|
||||
|
||||
if (lmOld) {
|
||||
NS_ASSERTION(lmNew->glForResources() == lmOld->glForResources(),
|
||||
"We require GL context sharing here!");
|
||||
lmOld->ForgetImageContainer(this);
|
||||
}
|
||||
|
||||
mManager = aManager;
|
||||
|
||||
lmNew->RememberImageContainer(this);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerOGL::GetLayer()
|
||||
{
|
||||
@ -276,11 +367,15 @@ ImageLayerOGL::RenderLayer(int,
|
||||
PlanarYCbCrImageOGL *yuvImage =
|
||||
static_cast<PlanarYCbCrImageOGL*>(image.get());
|
||||
|
||||
if (!yuvImage->HasData())
|
||||
if (!yuvImage->HasData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!yuvImage->HasTextures()) {
|
||||
yuvImage->AllocateTextures(gl());
|
||||
}
|
||||
|
||||
if (!yuvImage->HasTextures())
|
||||
yuvImage->AllocateTextures(mOGLManager);
|
||||
yuvImage->UpdateTextures(gl());
|
||||
|
||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, yuvImage->mTextures[0].GetTextureID());
|
||||
@ -335,9 +430,39 @@ ImageLayerOGL::RenderLayer(int,
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(RecycleBin *aRecycleBin)
|
||||
static void
|
||||
InitTexture(GLContext* aGL, GLuint aTexture, GLenum aFormat, const gfxIntSize& aSize)
|
||||
{
|
||||
aGL->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
aFormat,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
aFormat,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
|
||||
RecycleBin *aRecycleBin)
|
||||
: PlanarYCbCrImage(nsnull), mRecycleBin(aRecycleBin), mHasData(PR_FALSE)
|
||||
{
|
||||
#if 0
|
||||
// We really want to allocate this on the decode thread -- but to do that,
|
||||
// we need to create a per-thread shared GL context, and it will only work
|
||||
// if we have context sharing. For now, create the textures on the main
|
||||
// thread the first time we render.
|
||||
if (aManager) {
|
||||
AllocateTextures(aManager->glForResources());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
|
||||
@ -346,9 +471,11 @@ PlanarYCbCrImageOGL::~PlanarYCbCrImageOGL()
|
||||
mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
|
||||
}
|
||||
|
||||
mRecycleBin->RecycleTexture(&mTextures[0], RecycleBin::TEXTURE_Y, mData.mYSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
if (HasTextures()) {
|
||||
mRecycleBin->RecycleTexture(&mTextures[0], RecycleBin::TEXTURE_Y, mData.mYSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -384,7 +511,7 @@ PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
|
||||
|
||||
mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
|
||||
mData.mYStride * mData.mYSize.height;
|
||||
mBuffer = mRecycleBin->TakeBuffer(mBufferSize);
|
||||
mBuffer = mRecycleBin->GetBuffer(mBufferSize);
|
||||
if (!mBuffer)
|
||||
return;
|
||||
|
||||
@ -417,54 +544,24 @@ PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
|
||||
mHasData = PR_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
SetupPlaneTexture(GLContext* aGL, const gfxIntSize& aSize, PRUint8* aData, PRBool aIsNew)
|
||||
void
|
||||
PlanarYCbCrImageOGL::AllocateTextures(mozilla::gl::GLContext *gl)
|
||||
{
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->MakeCurrent();
|
||||
|
||||
if (aIsNew) {
|
||||
aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
0,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
aData);
|
||||
} else {
|
||||
aGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
0, 0,
|
||||
aSize.width,
|
||||
aSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
aData);
|
||||
}
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_Y, mData.mYSize, gl, &mTextures[0]);
|
||||
InitTexture(gl, mTextures[0].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mYSize);
|
||||
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[1]);
|
||||
InitTexture(gl, mTextures[1].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
|
||||
|
||||
mRecycleBin->GetTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[2]);
|
||||
InitTexture(gl, mTextures[2].GetTextureID(), LOCAL_GL_LUMINANCE, mData.mCbCrSize);
|
||||
}
|
||||
|
||||
void
|
||||
PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
||||
PlanarYCbCrImageOGL::UpdateTextures(GLContext *gl)
|
||||
{
|
||||
aManager->MakeCurrent();
|
||||
|
||||
mozilla::gl::GLContext *gl = aManager->gl();
|
||||
|
||||
PRPackedBool isNewTexture[3];
|
||||
for (PRUint32 i = 0; i < 3; ++i) {
|
||||
isNewTexture[i] = !mTextures[i].IsAllocated();
|
||||
}
|
||||
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_Y, mData.mYSize, gl, &mTextures[0]);
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[1]);
|
||||
mRecycleBin->TakeTexture(RecycleBin::TEXTURE_C, mData.mCbCrSize, gl, &mTextures[2]);
|
||||
if (!HasTextures())
|
||||
return;
|
||||
|
||||
GLint alignment;
|
||||
|
||||
if (!((ptrdiff_t)mData.mYStride & 0x7) && !((ptrdiff_t)mData.mYChannel & 0x7)) {
|
||||
@ -481,12 +578,16 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[0].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mYSize, mData.mYChannel, isNewTexture[0]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mYSize.width, mData.mYSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mYChannel);
|
||||
|
||||
if (!((ptrdiff_t)mData.mCbCrStride & 0x7) &&
|
||||
!((ptrdiff_t)mData.mCbChannel & 0x7) &&
|
||||
!((ptrdiff_t)mData.mCrChannel & 0x7)) {
|
||||
!((ptrdiff_t)mData.mCrChannel & 0x7))
|
||||
{
|
||||
alignment = 8;
|
||||
} else if (!((ptrdiff_t)mData.mCbCrStride & 0x3)) {
|
||||
alignment = 4;
|
||||
@ -500,12 +601,18 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[1].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mCbCrSize, mData.mCbChannel, isNewTexture[1]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mCbChannel);
|
||||
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextures[2].GetTextureID());
|
||||
|
||||
SetupPlaneTexture(gl, mData.mCbCrSize, mData.mCrChannel, isNewTexture[2]);
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mData.mCbCrSize.width, mData.mCbCrSize.height,
|
||||
LOCAL_GL_LUMINANCE,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
mData.mCrChannel);
|
||||
|
||||
// Reset alignment to default
|
||||
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
|
||||
@ -516,12 +623,15 @@ PlanarYCbCrImageOGL::AllocateTextures(LayerManagerOGL *aManager)
|
||||
}
|
||||
}
|
||||
|
||||
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager) : CairoImage(nsnull)
|
||||
CairoImageOGL::CairoImageOGL(LayerManagerOGL *aManager)
|
||||
: CairoImage(nsnull)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread to create a cairo image");
|
||||
|
||||
// Allocate texture now to grab a reference to the GLContext
|
||||
mTexture.Allocate(aManager->gl());
|
||||
if (aManager) {
|
||||
// Allocate texture now to grab a reference to the GLContext
|
||||
mTexture.Allocate(aManager->glForResources());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -533,20 +643,20 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
||||
mozilla::gl::GLContext *gl = mTexture.GetGLContext();
|
||||
gl->MakeCurrent();
|
||||
|
||||
mSize = aData.mSize;
|
||||
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
if (mSize != aData.mSize) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
InitTexture(gl, mTexture.GetTextureID(), LOCAL_GL_RGBA, aData.mSize);
|
||||
mSize = aData.mSize;
|
||||
} else {
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture.GetTextureID());
|
||||
}
|
||||
|
||||
if (!mASurfaceAsGLContext) {
|
||||
mASurfaceAsGLContext = GLContextProvider::CreateForNativePixmapSurface(aData.mSurface);
|
||||
if (mASurfaceAsGLContext)
|
||||
mASurfaceAsGLContext->BindTexImage();
|
||||
}
|
||||
|
||||
if (mASurfaceAsGLContext)
|
||||
return;
|
||||
|
||||
@ -561,15 +671,11 @@ CairoImageOGL::SetData(const CairoImage::Data &aData)
|
||||
context->SetSource(aData.mSurface);
|
||||
context->Paint();
|
||||
|
||||
gl->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
mSize.width,
|
||||
mSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
|
||||
0, 0, mSize.width, mSize.height,
|
||||
LOCAL_GL_RGBA,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -102,7 +102,7 @@ public:
|
||||
|
||||
void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
|
||||
// Returns a recycled buffer of the right size, or allocates a new buffer.
|
||||
PRUint8* TakeBuffer(PRUint32 aSize);
|
||||
PRUint8* GetBuffer(PRUint32 aSize);
|
||||
|
||||
enum TextureType {
|
||||
TEXTURE_Y,
|
||||
@ -111,8 +111,8 @@ public:
|
||||
|
||||
void RecycleTexture(GLTexture *aTexture, TextureType aType,
|
||||
const gfxIntSize& aSize);
|
||||
void TakeTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture);
|
||||
void GetTexture(TextureType aType, const gfxIntSize& aSize,
|
||||
GLContext *aContext, GLTexture *aOutTexture);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
@ -135,7 +135,7 @@ class THEBES_API ImageContainerOGL : public ImageContainer
|
||||
{
|
||||
public:
|
||||
ImageContainerOGL(LayerManagerOGL *aManager);
|
||||
virtual ~ImageContainerOGL() {}
|
||||
virtual ~ImageContainerOGL();
|
||||
|
||||
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
|
||||
PRUint32 aNumFormats);
|
||||
@ -148,6 +148,8 @@ public:
|
||||
|
||||
virtual gfxIntSize GetCurrentSize();
|
||||
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
@ -169,8 +171,10 @@ public:
|
||||
{
|
||||
mImplData = static_cast<LayerOGL*>(this);
|
||||
}
|
||||
~ImageLayerOGL() { Destroy(); }
|
||||
|
||||
// LayerOGL Implementation
|
||||
virtual void Destroy() { mDestroyed = PR_TRUE; }
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
@ -182,7 +186,8 @@ class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
public:
|
||||
PlanarYCbCrImageOGL(RecycleBin *aRecycleBin);
|
||||
PlanarYCbCrImageOGL(LayerManagerOGL *aManager,
|
||||
RecycleBin *aRecycleBin);
|
||||
~PlanarYCbCrImageOGL();
|
||||
|
||||
virtual void SetData(const Data &aData);
|
||||
@ -191,7 +196,9 @@ public:
|
||||
* Upload the data from out mData into our textures. For now we use this to
|
||||
* make sure the textures are created and filled on the main thread.
|
||||
*/
|
||||
void AllocateTextures(LayerManagerOGL *aManager);
|
||||
void AllocateTextures(GLContext *gl);
|
||||
void UpdateTextures(GLContext *gl);
|
||||
|
||||
PRBool HasData() { return mHasData; }
|
||||
PRBool HasTextures()
|
||||
{
|
||||
|
@ -76,8 +76,30 @@ LayerManagerOGL::LayerManagerOGL(nsIWidget *aWidget)
|
||||
|
||||
LayerManagerOGL::~LayerManagerOGL()
|
||||
{
|
||||
mRoot = nsnull;
|
||||
CleanupResources();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
if (mRoot) {
|
||||
RootLayer()->Destroy();
|
||||
}
|
||||
mRoot = nsnull;
|
||||
|
||||
// Make a copy, since SetLayerManager will cause mImageContainers
|
||||
// to get mutated.
|
||||
nsTArray<ImageContainer*> imageContainers(mImageContainers);
|
||||
for (PRUint32 i = 0; i < imageContainers.Length(); ++i) {
|
||||
ImageContainer *c = imageContainers[i];
|
||||
c->SetLayerManager(nsnull);
|
||||
}
|
||||
|
||||
CleanupResources();
|
||||
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -90,7 +112,7 @@ LayerManagerOGL::CleanupResources()
|
||||
if (!ctx) {
|
||||
ctx = mGLContext;
|
||||
}
|
||||
|
||||
|
||||
ctx->MakeCurrent();
|
||||
|
||||
for (unsigned int i = 0; i < mPrograms.Length(); ++i)
|
||||
@ -125,6 +147,7 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
||||
} else {
|
||||
if (mGLContext)
|
||||
CleanupResources();
|
||||
|
||||
mGLContext = gl::GLContextProvider::CreateForWindow(mWidget);
|
||||
|
||||
if (!mGLContext) {
|
||||
@ -137,10 +160,9 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
||||
|
||||
DEBUG_GL_ERROR_CHECK(mGLContext);
|
||||
|
||||
const char *extensionStr =
|
||||
(const char*) mGLContext->fGetString(LOCAL_GL_EXTENSIONS);
|
||||
|
||||
mHasBGRA = (strstr(extensionStr, "EXT_bgra") != nsnull);
|
||||
mHasBGRA =
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_texture_format_BGRA8888) ||
|
||||
mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra);
|
||||
|
||||
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
@ -259,7 +281,7 @@ LayerManagerOGL::Initialize(GLContext *aExistingContext)
|
||||
* texture rectangle access inside GLSL (sampler2DRect,
|
||||
* texture2DRect).
|
||||
*/
|
||||
if (strstr(extensionStr, "ARB_texture_rectangle") == NULL)
|
||||
if (!mGLContext->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -327,6 +349,11 @@ LayerManagerOGL::BeginTransaction()
|
||||
void
|
||||
LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
@ -334,6 +361,11 @@ void
|
||||
LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mThebesLayerCallback = aCallback;
|
||||
mThebesLayerCallbackData = aCallbackData;
|
||||
|
||||
@ -348,6 +380,11 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
already_AddRefed<ThebesLayer>
|
||||
LayerManagerOGL::CreateThebesLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ThebesLayer> layer = new ThebesLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
@ -355,6 +392,11 @@ LayerManagerOGL::CreateThebesLayer()
|
||||
already_AddRefed<ContainerLayer>
|
||||
LayerManagerOGL::CreateContainerLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ContainerLayer> layer = new ContainerLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
@ -362,13 +404,24 @@ LayerManagerOGL::CreateContainerLayer()
|
||||
already_AddRefed<ImageContainer>
|
||||
LayerManagerOGL::CreateImageContainer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageContainer> container = new ImageContainerOGL(this);
|
||||
RememberImageContainer(container);
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageLayer>
|
||||
LayerManagerOGL::CreateImageLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageLayer> layer = new ImageLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
@ -376,6 +429,11 @@ LayerManagerOGL::CreateImageLayer()
|
||||
already_AddRefed<ColorLayer>
|
||||
LayerManagerOGL::CreateColorLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<ColorLayer> layer = new ColorLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
@ -383,25 +441,65 @@ LayerManagerOGL::CreateColorLayer()
|
||||
already_AddRefed<CanvasLayer>
|
||||
LayerManagerOGL::CreateCanvasLayer()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<CanvasLayer> layer = new CanvasLayerOGL(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::ForgetImageContainer(ImageContainer *aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->Manager() == this,
|
||||
"ForgetImageContainer called on non-owned container!");
|
||||
|
||||
if (!mImageContainers.RemoveElement(aContainer)) {
|
||||
NS_WARNING("ForgetImageContainer couldn't find container it was supposed to forget!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::RememberImageContainer(ImageContainer *aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->Manager() == this,
|
||||
"RememberImageContainer called on non-owned container!");
|
||||
mImageContainers.AppendElement(aContainer);
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::MakeCurrent()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
mGLContext->MakeCurrent();
|
||||
}
|
||||
|
||||
LayerOGL*
|
||||
LayerManagerOGL::RootLayer() const
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return static_cast<LayerOGL*>(mRoot->ImplData());
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerOGL::Render()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
NS_WARNING("Call on destroyed layer manager");
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetBounds(rect);
|
||||
GLint width = rect.width;
|
||||
@ -645,12 +743,22 @@ LayerManagerOGL::CopyToTarget()
|
||||
NS_ASSERTION(imageSurface->Stride() == width * 4,
|
||||
"Image Surfaces being created with weird stride!");
|
||||
|
||||
PRUint32 currentPackAlignment = 0;
|
||||
mGLContext->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)¤tPackAlignment);
|
||||
if (currentPackAlignment != 4) {
|
||||
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
mGLContext->fReadPixels(0, 0,
|
||||
width, height,
|
||||
format,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
imageSurface->Data());
|
||||
|
||||
if (currentPackAlignment != 4) {
|
||||
mGLContext->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
if (!mHasBGRA) {
|
||||
// need to swap B and R bytes
|
||||
for (int j = 0; j < height; ++j) {
|
||||
@ -739,6 +847,5 @@ LayerManagerOGL::CreateFBOWithTexture(int aWidth, int aHeight,
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
}
|
||||
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
@ -83,6 +83,8 @@ public:
|
||||
|
||||
void CleanupResources();
|
||||
|
||||
void Destroy();
|
||||
|
||||
/**
|
||||
* Initializes the layer manager, this is when the layer manager will
|
||||
* actually access the device and attempt to create the swap chain used
|
||||
@ -135,6 +137,16 @@ public:
|
||||
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_OPENGL; }
|
||||
|
||||
/**
|
||||
* Image Container management.
|
||||
*/
|
||||
|
||||
/* Forget this image container. Should be called by ImageContainerOGL
|
||||
* on its current layer manager before switching to a new one.
|
||||
*/
|
||||
void ForgetImageContainer(ImageContainer* aContainer);
|
||||
void RememberImageContainer(ImageContainer* aContainer);
|
||||
|
||||
/**
|
||||
* Helper methods.
|
||||
*/
|
||||
@ -182,6 +194,16 @@ public:
|
||||
void* GetThebesLayerCallbackData() const
|
||||
{ return mThebesLayerCallbackData; }
|
||||
|
||||
// This is a GLContext that can be used for resource
|
||||
// management (creation, destruction). It is guaranteed
|
||||
// to be either the same as the gl() context, or a context
|
||||
// that is in the same share pool.
|
||||
GLContext *glForResources() const {
|
||||
if (mGLContext->GetSharedContext())
|
||||
return mGLContext->GetSharedContext();
|
||||
return mGLContext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions for our layers
|
||||
*/
|
||||
@ -281,6 +303,11 @@ private:
|
||||
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
// The image containers that this layer manager has created.
|
||||
// The destructor will tell the layer manager to remove
|
||||
// it from the list.
|
||||
nsTArray<ImageContainer*> mImageContainers;
|
||||
|
||||
enum ProgramType {
|
||||
RGBALayerProgramType,
|
||||
BGRALayerProgramType,
|
||||
@ -364,13 +391,20 @@ class LayerOGL
|
||||
{
|
||||
public:
|
||||
LayerOGL(LayerManagerOGL *aManager)
|
||||
: mOGLManager(aManager)
|
||||
: mOGLManager(aManager), mDestroyed(PR_FALSE)
|
||||
{ }
|
||||
|
||||
virtual ~LayerOGL() { }
|
||||
|
||||
virtual LayerOGL *GetFirstChildOGL() {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* Do NOT call this from the generic LayerOGL destructor. Only from the
|
||||
* concrete class destructor
|
||||
*/
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
@ -381,6 +415,7 @@ public:
|
||||
GLContext *gl() const { return mOGLManager->gl(); }
|
||||
protected:
|
||||
LayerManagerOGL *mOGLManager;
|
||||
PRPackedBool mDestroyed;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
@ -300,19 +300,17 @@ protected:
|
||||
}
|
||||
fprintf (stderr, "=== Log:\n%s\n", nsPromiseFlatCString(log).get());
|
||||
fprintf (stderr, "============\n");
|
||||
}
|
||||
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
// We can mark the shaders for deletion; they're attached to the program
|
||||
// and will remain attached.
|
||||
mGL->fDeleteShader(vertexShader);
|
||||
mGL->fDeleteShader(fragmentShader);
|
||||
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
|
||||
mProgram = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!success) {
|
||||
mGL->fDeleteProgram(mProgram);
|
||||
mProgram = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now query uniforms, so that we can initialize mUniformValues
|
||||
|
@ -331,8 +331,18 @@ ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL *aManager)
|
||||
|
||||
ThebesLayerOGL::~ThebesLayerOGL()
|
||||
{
|
||||
mBuffer = nsnull;
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerOGL::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
mBuffer = nsnull;
|
||||
DEBUG_GL_ERROR_CHECK(gl());
|
||||
|
||||
mDestroyed = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -50,7 +50,7 @@ namespace layers {
|
||||
class ThebesLayerBufferOGL;
|
||||
|
||||
class ThebesLayerOGL : public ThebesLayer,
|
||||
public LayerOGL
|
||||
public LayerOGL
|
||||
{
|
||||
typedef ThebesLayerBufferOGL Buffer;
|
||||
|
||||
@ -65,6 +65,7 @@ public:
|
||||
void InvalidateRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/** LayerOGL implementation */
|
||||
void Destroy();
|
||||
Layer* GetLayer();
|
||||
virtual PRBool IsEmpty();
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
|
@ -309,9 +309,64 @@ GLContext::InitWithPrefix(const char *prefix, PRBool trygl)
|
||||
};
|
||||
|
||||
mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
|
||||
|
||||
if (mInitialized) {
|
||||
InitExtensions();
|
||||
}
|
||||
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
// should match the order of GLExtensions
|
||||
static const char *sExtensionNames[] = {
|
||||
"GL_EXT_framebuffer_object",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_ARB_texture_rectangle",
|
||||
"GL_EXT_bgra",
|
||||
"GL_EXT_texture_format_BGRA8888",
|
||||
"GL_OES_depth24",
|
||||
"GL_OES_depth32",
|
||||
"GL_OES_stencil8",
|
||||
"GL_OES_texture_npot",
|
||||
"GL_OES_depth_texture",
|
||||
"GL_OES_packed_depth_stencil",
|
||||
"GL_IMG_read_format",
|
||||
"GL_EXT_read_format_bgra",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
GLContext::InitExtensions()
|
||||
{
|
||||
MakeCurrent();
|
||||
const GLubyte *extensions = fGetString(LOCAL_GL_EXTENSIONS);
|
||||
char *exts = strdup((char *)extensions);
|
||||
|
||||
printf_stderr("GL extensions: %s\n", exts);
|
||||
|
||||
char *s = exts;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
char *space = strchr(s, ' ');
|
||||
if (space) {
|
||||
*space = '\0';
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
|
||||
for (int i = 0; sExtensionNames[i]; ++i) {
|
||||
if (strcmp(s, sExtensionNames[i]) == 0) {
|
||||
printf_stderr("Found extension %s\n", s);
|
||||
mAvailableExtensions[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
s = space+1;
|
||||
}
|
||||
|
||||
free(exts);
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContext::IsExtensionSupported(const char *extension)
|
||||
{
|
||||
@ -479,6 +534,9 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
|
||||
GLint viewport[4];
|
||||
|
||||
bool useDepthStencil =
|
||||
!mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil);
|
||||
|
||||
// save a few things for later restoring
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*) &curBoundFramebuffer);
|
||||
@ -496,7 +554,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
fGenFramebuffers(1, &mOffscreenFBO);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fGenRenderbuffers(1, &mOffscreenDepthRB);
|
||||
} else {
|
||||
if (depth) {
|
||||
@ -529,18 +587,35 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
aSize.width, aSize.height,
|
||||
0,
|
||||
LOCAL_GL_RGB,
|
||||
#ifdef XP_WIN
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5
|
||||
: LOCAL_GL_UNSIGNED_BYTE,
|
||||
#endif
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
LOCAL_GL_DEPTH24_STENCIL8,
|
||||
aSize.width, aSize.height);
|
||||
} else {
|
||||
if (depth) {
|
||||
GLenum depthType;
|
||||
if (mIsGLES2) {
|
||||
if (IsExtensionSupported(OES_depth32)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT32;
|
||||
} else if (IsExtensionSupported(OES_depth24)) {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
} else {
|
||||
depthType = LOCAL_GL_DEPTH_COMPONENT24;
|
||||
}
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER,
|
||||
mIsGLES2 ? LOCAL_GL_DEPTH_COMPONENT16
|
||||
@ -565,7 +640,7 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
mOffscreenTexture,
|
||||
0);
|
||||
|
||||
if (depth && stencil && !mIsGLES2) {
|
||||
if (depth && stencil && useDepthStencil) {
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_DEPTH_ATTACHMENT,
|
||||
LOCAL_GL_RENDERBUFFER,
|
||||
@ -603,6 +678,10 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
|
||||
if (firstTime) {
|
||||
UpdateActualFormat();
|
||||
|
||||
printf_stderr("Created offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d\n",
|
||||
mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha,
|
||||
mActualFormat.depth, mActualFormat.stencil);
|
||||
}
|
||||
|
||||
// We're good, and the framebuffer is already attached, so let's
|
||||
@ -665,7 +744,216 @@ GLContext::ClearSafely()
|
||||
void
|
||||
GLContext::UpdateActualFormat()
|
||||
{
|
||||
// TODO
|
||||
ContextFormat nf;
|
||||
|
||||
fGetIntegerv(LOCAL_GL_RED_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_GREEN_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_BLUE_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_ALPHA_BITS, (GLint*) &nf.alpha);
|
||||
fGetIntegerv(LOCAL_GL_DEPTH_BITS, (GLint*) &nf.depth);
|
||||
fGetIntegerv(LOCAL_GL_STENCIL_BITS, (GLint*) &nf.depth);
|
||||
|
||||
mActualFormat = nf;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::MarkDestroyed()
|
||||
{
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
memset(&mFunctionListStartSentinel, 0, &mFunctionListEndSentinel - &mFunctionListStartSentinel);
|
||||
}
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
GLContext::ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
nsRefPtr<gfxImageSurface> isurf;
|
||||
|
||||
GLint oldrb, oldfb, oldprog, oldvp[4], oldPackAlignment;
|
||||
GLint success;
|
||||
|
||||
GLuint rb = 0, fb = 0;
|
||||
GLuint vs = 0, fs = 0, prog = 0;
|
||||
|
||||
const char *vShader =
|
||||
"attribute vec4 aVertex;\n"
|
||||
"attribute vec2 aTexCoord;\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"void main() { gl_Position = aVertex; vTexCoord = aTexCoord; }";
|
||||
const char *fShader =
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"varying vec2 vTexCoord;\n"
|
||||
"uniform sampler2D uTexture;\n"
|
||||
"void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
|
||||
|
||||
float verts[4*4] = {
|
||||
-1.0f, -1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
float texcoords[2*4] = {
|
||||
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
|
||||
fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
|
||||
fGetIntegerv(LOCAL_GL_VIEWPORT, oldvp);
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &oldPackAlignment);
|
||||
|
||||
fGenRenderbuffers(1, &rb);
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
|
||||
fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA,
|
||||
aSize.width, aSize.height);
|
||||
|
||||
fGenFramebuffers(1, &fb);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
|
||||
fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_RENDERBUFFER, rb);
|
||||
|
||||
if (fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) !=
|
||||
LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vs = fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
fs = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
fShaderSource(vs, 1, (const GLchar**) &vShader, NULL);
|
||||
fShaderSource(fs, 1, (const GLchar**) &fShader, NULL);
|
||||
prog = fCreateProgram();
|
||||
fAttachShader(prog, vs);
|
||||
fAttachShader(prog, fs);
|
||||
fBindAttribLocation(prog, 0, "aVertex");
|
||||
fBindAttribLocation(prog, 1, "aTexCoord");
|
||||
fLinkProgram(prog);
|
||||
|
||||
fGetProgramiv(prog, LOCAL_GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
fUseProgram(prog);
|
||||
|
||||
fEnableVertexAttribArray(0);
|
||||
fEnableVertexAttribArray(1);
|
||||
|
||||
fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, verts);
|
||||
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, texcoords);
|
||||
|
||||
fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
|
||||
|
||||
fUniform1i(fGetUniformLocation(prog, "uTexture"), 0);
|
||||
|
||||
fViewport(0, 0, aSize.width, aSize.height);
|
||||
|
||||
fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
fDisableVertexAttribArray(1);
|
||||
fDisableVertexAttribArray(0);
|
||||
|
||||
isurf = new gfxImageSurface(aSize, gfxASurface::ImageFormatARGB32);
|
||||
if (!isurf || isurf->CairoStatus()) {
|
||||
isurf = nsnull;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (oldPackAlignment != 4)
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
fReadPixels(0, 0, aSize.width, aSize.height,
|
||||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
isurf->Data());
|
||||
|
||||
if (oldPackAlignment != 4)
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, oldPackAlignment);
|
||||
|
||||
cleanup:
|
||||
// note that deleting 0 has no effect in any of these calls
|
||||
fDeleteRenderbuffers(1, &rb);
|
||||
fDeleteFramebuffers(1, &fb);
|
||||
fDeleteShader(vs);
|
||||
fDeleteShader(fs);
|
||||
fDeleteProgram(prog);
|
||||
|
||||
fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
|
||||
fUseProgram(oldprog);
|
||||
fViewport(oldvp[0], oldvp[1], oldvp[2], oldvp[3]);
|
||||
|
||||
return isurf.forget();
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ReadPixelsIntoImageSurface(GLint aX, GLint aY,
|
||||
GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest)
|
||||
{
|
||||
MakeCurrent();
|
||||
|
||||
if (aDest->Format() != gfxASurface::ImageFormatARGB32 &&
|
||||
aDest->Format() != gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with invalid image format");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDest->Width() != aWidth ||
|
||||
aDest->Height() != aHeight ||
|
||||
aDest->Stride() != aWidth * 4)
|
||||
{
|
||||
NS_WARNING("ReadPixelsIntoImageSurface called with wrong size or stride surface");
|
||||
return;
|
||||
}
|
||||
|
||||
GLint currentPackAlignment = 0;
|
||||
fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment);
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
// defaults for desktop
|
||||
GLenum format = LOCAL_GL_BGRA;
|
||||
GLenum datatype = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bool swap = false;
|
||||
|
||||
if (IsGLES2()) {
|
||||
datatype = LOCAL_GL_UNSIGNED_BYTE;
|
||||
|
||||
if (IsExtensionSupported(gl::GLContext::EXT_read_format_bgra) ||
|
||||
IsExtensionSupported(gl::GLContext::IMG_read_format) ||
|
||||
IsExtensionSupported(gl::GLContext::EXT_bgra))
|
||||
{
|
||||
format = LOCAL_GL_BGRA;
|
||||
} else {
|
||||
format = LOCAL_GL_RGBA;
|
||||
swap = true;
|
||||
}
|
||||
}
|
||||
|
||||
fReadPixels(0, 0, aWidth, aHeight,
|
||||
format, datatype,
|
||||
aDest->Data());
|
||||
|
||||
if (swap) {
|
||||
// swap B and R bytes
|
||||
for (int j = 0; j < aHeight; ++j) {
|
||||
PRUint32 *row = (PRUint32*) (aDest->Data() + aDest->Stride() * j);
|
||||
for (int i = 0; i < aWidth; ++i) {
|
||||
*row = (*row & 0xff00ff00) | ((*row & 0xff) << 16) | ((*row & 0xff0000) >> 16);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -385,6 +385,10 @@ public:
|
||||
mUserData.Put(aKey, aValue);
|
||||
}
|
||||
|
||||
// Mark this context as destroyed. This will NULL out all
|
||||
// the GL function pointers!
|
||||
void MarkDestroyed();
|
||||
|
||||
enum NativeDataType {
|
||||
NativeGLContext,
|
||||
NativeImageSurface,
|
||||
@ -395,6 +399,9 @@ public:
|
||||
virtual void *GetNativeData(NativeDataType aType) { return NULL; }
|
||||
GLContext *GetSharedContext() { return mSharedContext; }
|
||||
|
||||
PRBool IsGlobalSharedContext() { return mIsGlobalSharedContext; }
|
||||
void SetIsGlobalSharedContext(PRBool aIsOne) { mIsGlobalSharedContext = aIsOne; }
|
||||
|
||||
const ContextFormat& CreationFormat() { return mCreationFormat; }
|
||||
const ContextFormat& ActualFormat() { return mActualFormat; }
|
||||
|
||||
@ -428,20 +435,6 @@ public:
|
||||
*/
|
||||
virtual PRBool ReleaseTexImage() { return PR_FALSE; }
|
||||
|
||||
virtual GLuint CreateTexture()
|
||||
{
|
||||
GLuint tex;
|
||||
MakeCurrent();
|
||||
fGenTextures(1, &tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
virtual void DestroyTexture(GLuint tex)
|
||||
{
|
||||
MakeCurrent();
|
||||
fDeleteTextures(1, &tex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Offscreen support API
|
||||
*/
|
||||
@ -554,10 +547,61 @@ public:
|
||||
GLint aWrapMode,
|
||||
PRBool aUseNearestFilter=PR_FALSE);
|
||||
|
||||
/**
|
||||
* Read the image data contained in aTexture, and return it as an ImageSurface.
|
||||
* If GL_RGBA is given as the format, a ImageFormatARGB32 surface is returned.
|
||||
* Not implemented yet:
|
||||
* If GL_RGB is given as the format, a ImageFormatRGB24 surface is returned.
|
||||
* If GL_LUMINANCE is given as the format, a ImageFormatA8 surface is returned.
|
||||
*
|
||||
* THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
|
||||
* if you absolutely positively must, and never in any performance
|
||||
* critical path.
|
||||
*/
|
||||
already_AddRefed<gfxImageSurface> ReadTextureImage(GLuint aTexture,
|
||||
const gfxIntSize& aSize,
|
||||
GLenum aTextureFormat);
|
||||
|
||||
/**
|
||||
* Call ReadPixels into an existing gfxImageSurface for the given bounds.
|
||||
* The image surface must be using image format RGBA32 or RGB24.
|
||||
*/
|
||||
void ReadPixelsIntoImageSurface(GLint aX, GLint aY, GLsizei aWidth, GLsizei aHeight,
|
||||
gfxImageSurface *aDest);
|
||||
|
||||
/**
|
||||
* Known GL extensions that can be queried by
|
||||
* IsExtensionSupported. The results of this are cached, and as
|
||||
* such it's safe to use this even in performance critical code.
|
||||
* If you add to this array, remember to add to the string names
|
||||
* in GLContext.cpp.
|
||||
*/
|
||||
enum GLExtensions {
|
||||
EXT_framebuffer_object,
|
||||
ARB_framebuffer_object,
|
||||
ARB_texture_rectangle,
|
||||
EXT_bgra,
|
||||
EXT_texture_format_BGRA8888,
|
||||
OES_depth24,
|
||||
OES_depth32,
|
||||
OES_stencil8,
|
||||
OES_texture_npot,
|
||||
OES_depth_texture,
|
||||
OES_packed_depth_stencil,
|
||||
IMG_read_format,
|
||||
EXT_read_format_bgra,
|
||||
Extensions_Max
|
||||
};
|
||||
|
||||
PRBool IsExtensionSupported(GLExtensions aKnownExtension) {
|
||||
return mAvailableExtensions[aKnownExtension];
|
||||
}
|
||||
|
||||
protected:
|
||||
PRPackedBool mInitialized;
|
||||
PRPackedBool mIsOffscreen;
|
||||
PRPackedBool mIsGLES2;
|
||||
PRPackedBool mIsGlobalSharedContext;
|
||||
ContextFormat mCreationFormat;
|
||||
nsRefPtr<GLContext> mSharedContext;
|
||||
|
||||
@ -576,6 +620,25 @@ protected:
|
||||
GLuint mOffscreenDepthRB;
|
||||
GLuint mOffscreenStencilRB;
|
||||
|
||||
// this should just be a std::bitset, but that ended up breaking
|
||||
// MacOS X builds; see bug 584919. We can replace this with one
|
||||
// later on.
|
||||
template<size_t setlen>
|
||||
struct ExtensionBitset {
|
||||
ExtensionBitset() {
|
||||
for (int i = 0; i < setlen; ++i)
|
||||
values[i] = false;
|
||||
}
|
||||
|
||||
bool& operator[](const int index) {
|
||||
NS_ASSERTION(index >= 0 && index < setlen, "out of range");
|
||||
return values[index];
|
||||
}
|
||||
|
||||
bool values[setlen];
|
||||
};
|
||||
ExtensionBitset<Extensions_Max> mAvailableExtensions;
|
||||
|
||||
// Clear to transparent black, with 0 depth and stencil,
|
||||
// while preserving current ClearColor etc. values.
|
||||
// Useful for resizing offscreen buffers.
|
||||
@ -590,6 +653,7 @@ protected:
|
||||
|
||||
PRBool InitWithPrefix(const char *prefix, PRBool trygl);
|
||||
|
||||
void InitExtensions();
|
||||
PRBool IsExtensionSupported(const char *extension);
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
@ -607,6 +671,9 @@ public:
|
||||
* perl-or-python-or-js script somewhere and would be
|
||||
* autogenerated; one would be wrong.
|
||||
*/
|
||||
// Keep this at the start of the function pointers
|
||||
void *mFunctionListStartSentinel;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
PFNGLACTIVETEXTUREPROC fActiveTexture;
|
||||
typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
@ -851,6 +918,9 @@ public:
|
||||
typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
||||
PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage;
|
||||
|
||||
// keep this at the end of the function pointers
|
||||
void *mFunctionListEndSentinel;
|
||||
|
||||
void fDepthRange(GLclampf a, GLclampf b) {
|
||||
if (mIsGLES2) {
|
||||
priv_fDepthRangef(a, b);
|
||||
@ -963,127 +1033,73 @@ public:
|
||||
priv_fDeleteRenderbuffers(n, names);
|
||||
}
|
||||
#else
|
||||
GLContext *TrackingContext() {
|
||||
GLContext *tip = this;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
return tip;
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateProgram() {
|
||||
GLuint ret = priv_fCreateProgram();
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedProgram(this, ret);
|
||||
}
|
||||
TrackingContext()->CreatedProgram(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY fCreateShader(GLenum t) {
|
||||
GLuint ret = priv_fCreateShader(t);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedShader(this, ret);
|
||||
}
|
||||
TrackingContext()->CreatedShader(this, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenBuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedBuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedBuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenTextures(GLsizei n, GLuint* names) {
|
||||
priv_fGenTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedTextures(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedTextures(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenFramebuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedFramebuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fGenRenderbuffers(GLsizei n, GLuint* names) {
|
||||
priv_fGenRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->CreatedRenderbuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->CreatedRenderbuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteProgram(GLuint program) {
|
||||
priv_fDeleteProgram(program);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedProgram(this, program);
|
||||
}
|
||||
TrackingContext()->DeletedProgram(this, program);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteShader(GLuint shader) {
|
||||
priv_fDeleteShader(shader);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedShader(this, shader);
|
||||
}
|
||||
TrackingContext()->DeletedShader(this, shader);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteBuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteBuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedBuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedBuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteTextures(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteTextures(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedTextures(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedTextures(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteFramebuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteFramebuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
TrackingContext()->DeletedFramebuffers(this, n, names);
|
||||
}
|
||||
|
||||
void GLAPIENTRY fDeleteRenderbuffers(GLsizei n, GLuint *names) {
|
||||
priv_fDeleteRenderbuffers(n, names);
|
||||
if (mSharedContext) {
|
||||
GLContext *tip = mSharedContext;
|
||||
while (tip->mSharedContext)
|
||||
tip = tip->mSharedContext;
|
||||
tip->DeletedRenderbuffers(this, n, names);
|
||||
}
|
||||
TrackingContext()->DeletedRenderbuffers(this, n, names);
|
||||
}
|
||||
|
||||
void THEBES_API CreatedProgram(GLContext *aOrigin, GLuint aName);
|
||||
|
@ -74,12 +74,15 @@ namespace gl {
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
|
||||
#if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO) || defined(XP_WIN)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
|
||||
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// X11, but only if we didn't use EGL above
|
||||
#if defined(MOZ_X11) && !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
|
@ -520,6 +520,8 @@ GLContextProviderCGL::GetGlobalContext()
|
||||
gGlobalContext = nsnull;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
@ -76,6 +76,62 @@ typedef void *EGLNativeWindowType;
|
||||
#define EGL_LIB "/system/lib/libEGL.so"
|
||||
#define GLES2_LIB "/system/lib/libGLESv2.so"
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
|
||||
#include <nsServiceManagerUtils.h>
|
||||
#include <nsIPrefBranch.h>
|
||||
#include <nsILocalFile.h>
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
|
||||
#define EGL_LIB "libEGL.dll"
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
|
||||
// a little helper
|
||||
class AutoDestroyHWND {
|
||||
public:
|
||||
AutoDestroyHWND(HWND aWnd = NULL)
|
||||
: mWnd(aWnd)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoDestroyHWND() {
|
||||
if (mWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
}
|
||||
|
||||
operator HWND() {
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND forget() {
|
||||
HWND w = mWnd;
|
||||
mWnd = NULL;
|
||||
return w;
|
||||
}
|
||||
|
||||
HWND operator=(HWND aWnd) {
|
||||
if (mWnd && mWnd != aWnd) {
|
||||
::DestroyWindow(mWnd);
|
||||
}
|
||||
mWnd = aWnd;
|
||||
return mWnd;
|
||||
}
|
||||
|
||||
HWND mWnd;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#error "Platform not recognized"
|
||||
@ -147,58 +203,58 @@ public:
|
||||
mHave_EGL_KHR_gl_texture_2D_image = PR_FALSE;
|
||||
}
|
||||
|
||||
typedef EGLDisplay (*pfnGetDisplay)(void *display_id);
|
||||
typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
|
||||
pfnGetDisplay fGetDisplay;
|
||||
typedef EGLContext (*pfnGetCurrentContext)(void);
|
||||
typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void);
|
||||
pfnGetCurrentContext fGetCurrentContext;
|
||||
typedef EGLBoolean (*pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||
pfnMakeCurrent fMakeCurrent;
|
||||
typedef EGLBoolean (*pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
|
||||
pfnDestroyContext fDestroyContext;
|
||||
typedef EGLContext (*pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
|
||||
pfnCreateContext fCreateContext;
|
||||
typedef EGLBoolean (*pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnDestroySurface fDestroySurface;
|
||||
typedef EGLSurface (*pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
|
||||
pfnCreateWindowSurface fCreateWindowSurface;
|
||||
typedef EGLSurface (*pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
pfnCreatePbufferSurface fCreatePbufferSurface;
|
||||
typedef EGLSurface (*pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
|
||||
pfnCreatePixmapSurface fCreatePixmapSurface;
|
||||
typedef EGLBoolean (*pfnBindAPI)(EGLenum api);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api);
|
||||
pfnBindAPI fBindAPI;
|
||||
typedef EGLBoolean (*pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
pfnInitialize fInitialize;
|
||||
typedef EGLBoolean (*pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnChooseConfig fChooseConfig;
|
||||
typedef EGLint (*pfnGetError)(void);
|
||||
typedef EGLint (GLAPIENTRY * pfnGetError)(void);
|
||||
pfnGetError fGetError;
|
||||
typedef EGLBoolean (*pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||
pfnGetConfigAttrib fGetConfigAttrib;
|
||||
typedef EGLBoolean (*pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
pfnGetConfigs fGetConfigs;
|
||||
typedef EGLBoolean (*pfnWaitNative)(EGLint engine);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine);
|
||||
pfnWaitNative fWaitNative;
|
||||
typedef EGLCastToRelevantPtr (*pfnGetProcAddress)(const char *procname);
|
||||
typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char *procname);
|
||||
pfnGetProcAddress fGetProcAddress;
|
||||
typedef EGLBoolean (*pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
|
||||
pfnSwapBuffers fSwapBuffers;
|
||||
typedef EGLBoolean (*pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
pfnCopyBuffers fCopyBuffers;
|
||||
typedef const GLubyte* (*pfnQueryString)(EGLDisplay, EGLint name);
|
||||
typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name);
|
||||
pfnQueryString fQueryString;
|
||||
typedef EGLBoolean (*pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnBindTexImage fBindTexImage;
|
||||
typedef EGLBoolean (*pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
|
||||
pfnReleaseTexImage fReleaseTexImage;
|
||||
typedef EGLImageKHR (*pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLImageKHR (GLAPIENTRY * pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
pfnCreateImageKHR fCreateImageKHR;
|
||||
typedef EGLBoolean (*pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
typedef EGLBoolean (GLAPIENTRY * pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
|
||||
pfnDestroyImageKHR fDestroyImageKHR;
|
||||
// This is EGL specific GL ext symbol "glEGLImageTargetTexture2DOES"
|
||||
// Lets keep it here for now.
|
||||
typedef void (*pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
typedef void (GLAPIENTRY * pfnImageTargetTexture2DOES)(GLenum target, GLeglImageOES image);
|
||||
pfnImageTargetTexture2DOES fImageTargetTexture2DOES;
|
||||
|
||||
PRBool EnsureInitialized()
|
||||
@ -207,6 +263,43 @@ public:
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// ANGLE is an addon currently, so we have to do a bit of work
|
||||
// to find the directory; the addon sets this on startup/shutdown.
|
||||
do {
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService("@mozilla.org/preferences-service;1");
|
||||
nsCOMPtr<nsILocalFile> angleFile, glesv2File;
|
||||
if (!prefs)
|
||||
break;
|
||||
|
||||
nsresult rv = prefs->GetComplexValue("gfx.angle.egl.path",
|
||||
NS_GET_IID(nsILocalFile),
|
||||
getter_AddRefs(angleFile));
|
||||
if (NS_FAILED(rv) || !angleFile)
|
||||
break;
|
||||
|
||||
nsCAutoString s;
|
||||
|
||||
// note that we have to load the libs in this order, because libEGL.dll
|
||||
// depends on libGLESv2.dll, but is not in our search path.
|
||||
nsCOMPtr<nsIFile> f;
|
||||
angleFile->Clone(getter_AddRefs(f));
|
||||
glesv2File = do_QueryInterface(f);
|
||||
if (!glesv2File)
|
||||
break;
|
||||
|
||||
glesv2File->Append(NS_LITERAL_STRING("libGLESv2.dll"));
|
||||
|
||||
PRLibrary *glesv2lib = nsnull; // this will be leaked on purpose
|
||||
glesv2File->Load(&glesv2lib);
|
||||
if (!glesv2lib)
|
||||
break;
|
||||
|
||||
angleFile->Append(NS_LITERAL_STRING("libEGL.dll"));
|
||||
angleFile->Load(&mEGLLibrary);
|
||||
} while (false);
|
||||
#endif
|
||||
|
||||
if (!mEGLLibrary) {
|
||||
mEGLLibrary = PR_LoadLibrary(EGL_LIB);
|
||||
if (!mEGLLibrary) {
|
||||
@ -253,6 +346,11 @@ public:
|
||||
return PR_FALSE;
|
||||
|
||||
const char *extensions = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
|
||||
if (!extensions)
|
||||
extensions = "";
|
||||
|
||||
printf_stderr("Extensions: %s 0x%02x\n", extensions, extensions[0]);
|
||||
printf_stderr("Extensions length: %d\n", strlen(extensions));
|
||||
|
||||
// note the extra space -- this ugliness tries to match
|
||||
// EGL_KHR_image in the middle of the string, or right at the
|
||||
@ -406,10 +504,21 @@ public:
|
||||
, mThebesSurface(nsnull)
|
||||
, mBound(PR_FALSE)
|
||||
, mIsPBuffer(PR_FALSE)
|
||||
{}
|
||||
#ifdef XP_WIN
|
||||
, mWnd(0)
|
||||
#endif
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetIsGLES2(PR_TRUE);
|
||||
}
|
||||
|
||||
~GLContextEGL()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
// If mGLWidget is non-null, then we've been given it by the GL context provider,
|
||||
// and it's managed by the widget implementation. In this case, We can't destroy
|
||||
// our contexts.
|
||||
@ -559,6 +668,15 @@ public:
|
||||
CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
#ifdef XP_WIN
|
||||
static already_AddRefed<GLContextEGL>
|
||||
CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat);
|
||||
|
||||
void HoldWin32Window(HWND aWnd) { mWnd = aWnd; }
|
||||
HWND GetWin32Window() { return mWnd; }
|
||||
#endif
|
||||
|
||||
void SetOffscreenSize(const gfxIntSize &aRequestedSize,
|
||||
const gfxIntSize &aActualSize)
|
||||
{
|
||||
@ -577,6 +695,10 @@ protected:
|
||||
PRBool mBound;
|
||||
|
||||
PRPackedBool mIsPBuffer;
|
||||
|
||||
#ifdef XP_WIN
|
||||
AutoDestroyHWND mWnd;
|
||||
#endif
|
||||
};
|
||||
|
||||
PRBool
|
||||
@ -1167,6 +1289,95 @@ GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& aSize,
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
already_AddRefed<GLContextEGL>
|
||||
GLContextEGL::CreateEGLWin32OffscreenContext(const gfxIntSize& aSize,
|
||||
const ContextFormat& aFormat)
|
||||
{
|
||||
if (!sEGLLibrary.EnsureInitialized()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
WNDCLASSW wc;
|
||||
if (!GetClassInfoW(GetModuleHandle(NULL), L"ANGLEContextClass", &wc)) {
|
||||
ZeroMemory(&wc, sizeof(WNDCLASSW));
|
||||
wc.style = CS_OWNDC;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = L"ANGLEContextClass";
|
||||
if (!RegisterClassW(&wc)) {
|
||||
NS_WARNING("Failed to register ANGLEContextClass?!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AutoDestroyHWND wnd = CreateWindowW(L"ANGLEContextClass", L"ANGLEContext", 0,
|
||||
0, 0, 16, 16,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
NS_ENSURE_TRUE(HWND(wnd), NULL);
|
||||
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
// We don't really care, we're going to use a FBO anyway
|
||||
EGLint attribs[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
|
||||
EGLint ncfg = 1;
|
||||
if (!sEGLLibrary.fChooseConfig(sEGLLibrary.Display(), attribs, &config, ncfg, &ncfg) ||
|
||||
ncfg < 1)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
surface = sEGLLibrary.fCreateWindowSurface(sEGLLibrary.Display(),
|
||||
config,
|
||||
HWND(wnd),
|
||||
0);
|
||||
if (!surface) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API)) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
EGLint cxattribs[] = {
|
||||
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
context = sEGLLibrary.fCreateContext(sEGLLibrary.Display(),
|
||||
config,
|
||||
EGL_NO_CONTEXT,
|
||||
cxattribs);
|
||||
if (!context) {
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContextEGL> glContext = new GLContextEGL(aFormat, nsnull,
|
||||
config, surface, context,
|
||||
PR_TRUE);
|
||||
|
||||
// hold this even before we initialize, because we need to make
|
||||
// sure it gets destroyed after the surface etc. in case of error.
|
||||
glContext->HoldWin32Window(wnd.forget());
|
||||
|
||||
if (!glContext->Init() ||
|
||||
!glContext->ResizeOffscreenFBO(aSize))
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return glContext.forget();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Under EGL, if we're under X11, then we have to create a Pixmap
|
||||
// because Maemo's EGL implementation doesn't support pbuffers at all
|
||||
// for some reason. On Android, pbuffers are supported fine, though
|
||||
@ -1183,6 +1394,8 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize,
|
||||
return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat);
|
||||
#elif defined(MOZ_X11)
|
||||
return GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat);
|
||||
#elif defined(XP_WIN)
|
||||
return GLContextEGL::CreateEGLWin32OffscreenContext(aSize, aFormat);
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
@ -1291,6 +1504,8 @@ GLContextProviderEGL::GetGlobalContext()
|
||||
if (!triedToCreateContext && !gGlobalContext) {
|
||||
triedToCreateContext = true;
|
||||
gGlobalContext = CreateOffscreen(gfxIntSize(16, 16));
|
||||
if (gGlobalContext)
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
@ -225,6 +225,11 @@ TRY_AGAIN_NO_SHARING:
|
||||
|
||||
~GLContextGLX()
|
||||
{
|
||||
if (mOffscreenFBO) {
|
||||
MakeCurrent();
|
||||
DeleteOffscreenFBO();
|
||||
}
|
||||
|
||||
sGLXLibrary.xDeleteContext(mDisplay, mContext);
|
||||
|
||||
if (mDeleteDrawable) {
|
||||
@ -287,34 +292,6 @@ TRY_AGAIN_NO_SHARING:
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void WindowDestroyed()
|
||||
{
|
||||
for (unsigned int i=0; i<textures.Length(); i++) {
|
||||
GLContext::DestroyTexture(textures.ElementAt(i));
|
||||
}
|
||||
textures.Clear();
|
||||
}
|
||||
|
||||
// NB: we could set a flag upon WindowDestroyed() to dictate an
|
||||
// early-return from CreateTexture(), but then we would need the
|
||||
// same check before all GL calls, and that heads down a rabbit
|
||||
// hole.
|
||||
virtual GLuint CreateTexture()
|
||||
{
|
||||
GLuint tex = GLContext::CreateTexture();
|
||||
NS_ASSERTION(!textures.Contains(tex), "");
|
||||
textures.AppendElement(tex);
|
||||
return tex;
|
||||
}
|
||||
|
||||
virtual void DestroyTexture(GLuint texture)
|
||||
{
|
||||
if (textures.Contains(texture)) {
|
||||
textures.RemoveElement(texture);
|
||||
GLContext::DestroyTexture(texture);
|
||||
}
|
||||
}
|
||||
|
||||
virtual already_AddRefed<TextureImage>
|
||||
CreateBasicTextureImage(GLuint aTexture,
|
||||
const nsIntSize& aSize,
|
||||
@ -347,7 +324,6 @@ private:
|
||||
PRPackedBool mDeleteDrawable;
|
||||
PRPackedBool mDoubleBuffered;
|
||||
|
||||
nsTArray<GLuint> textures;
|
||||
nsRefPtr<gfxXlibSurface> mPixmap;
|
||||
};
|
||||
|
||||
@ -740,6 +716,8 @@ GLContextProviderGLX::GetGlobalContext()
|
||||
gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
|
||||
ContextFormat(ContextFormat::BasicRGB24),
|
||||
PR_FALSE);
|
||||
if (gGlobalContext)
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return gGlobalContext;
|
||||
|
@ -87,6 +87,10 @@ CreateDummyWindow(HDC *aWindowDC = nsnull)
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cAlphaBits = 8;
|
||||
pfd.cDepthBits = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
@ -688,6 +692,8 @@ GLContextProviderWGL::GetGlobalContext()
|
||||
gGlobalContext = nsnull;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
|
||||
}
|
||||
|
||||
return static_cast<GLContext*>(gGlobalContext);
|
||||
|
@ -116,6 +116,15 @@ public:
|
||||
GLXContext,
|
||||
Bool);
|
||||
PFNGLXCREATECONTEXT xCreateContext;
|
||||
typedef int (GLAPIENTRY * PFNGLXGETCONFIG) (Display *,
|
||||
XVisualInfo *,
|
||||
int,
|
||||
int *);
|
||||
PFNGLXGETCONFIG xGetConfig;
|
||||
typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEGLXPIXMAP) (Display *,
|
||||
XVisualInfo *,
|
||||
Pixmap);
|
||||
PFNGLXCREATEGLXPIXMAP xCreateGLXPixmap;
|
||||
|
||||
PRBool EnsureInitialized();
|
||||
|
||||
|
@ -414,6 +414,11 @@ else
|
||||
CPPSRCS += GLContextProvider$(GL_PROVIDER).cpp
|
||||
endif
|
||||
|
||||
# Win32 is a special snowflake, for ANGLE
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
CPPSRCS += GLContextProviderEGL.cpp
|
||||
endif
|
||||
|
||||
DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -187,6 +187,14 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
return nsnull;
|
||||
|
||||
nsRefPtr<ImageContainer> container = element->GetImageContainer();
|
||||
// If we have a container with a different layer manager, try to hand
|
||||
// off the container to the new one.
|
||||
if (container && container->Manager() != aManager) {
|
||||
// we don't care about the return type here -- if the set didn't take, it'll
|
||||
// be handled when we next check the manager
|
||||
container->SetLayerManager(aManager);
|
||||
}
|
||||
|
||||
// If we have a container with the right layer manager already, we don't
|
||||
// need to do anything here. Otherwise we need to set up a temporary
|
||||
// ImageContainer, capture the video data and store it in the temp
|
||||
@ -203,6 +211,10 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
// Get video from the existing container. It was created for a
|
||||
// different layer manager, so we do fallback through cairo.
|
||||
imageSurface = container->GetCurrentAsSurface(&cairoData.mSize);
|
||||
if (!imageSurface) {
|
||||
// we couldn't do fallback, so we've got nothing to do here
|
||||
return nsnull;
|
||||
}
|
||||
cairoData.mSurface = imageSurface;
|
||||
} else {
|
||||
// We're probably printing.
|
||||
|
@ -3128,7 +3128,7 @@ pref("image.mem.min_discard_timeout_ms", 10000);
|
||||
|
||||
// WebGL prefs
|
||||
pref("webgl.enabled_for_all_sites", false);
|
||||
pref("webgl.shader_validator", false);
|
||||
pref("webgl.shader_validator", true);
|
||||
pref("webgl.software_render", false);
|
||||
pref("webgl.osmesalib", "");
|
||||
|
||||
|
@ -40,10 +40,6 @@
|
||||
#include <windows.h>
|
||||
#include "nsToolkit.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_LIBXUL
|
||||
#include "../xre/nsWindowsDllBlocklist.cpp"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// If DllMain gets name mangled, it won't be seen.
|
||||
extern "C" {
|
||||
@ -60,9 +56,6 @@ BOOL APIENTRY DllMain(
|
||||
{
|
||||
switch( reason ) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
#ifdef MOZ_ENABLE_LIBXUL
|
||||
SetupDllBlocklist();
|
||||
#endif
|
||||
nsToolkit::Startup((HINSTANCE)hModule);
|
||||
break;
|
||||
|
||||
|
@ -1218,8 +1218,8 @@ var gSearchView = {
|
||||
return score;
|
||||
|
||||
aStr = aStr.trim().toLocaleLowerCase();
|
||||
var haystack = aStr.split(/\W+/);
|
||||
var needles = aQuery.split(/\W+/);
|
||||
var haystack = aStr.split(/\s+/);
|
||||
var needles = aQuery.split(/\s+/);
|
||||
|
||||
for (let n = 0; n < needles.length; n++) {
|
||||
for (let h = 0; h < haystack.length; h++) {
|
||||
|
@ -47,6 +47,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
head.js \
|
||||
browser_bug557943.js \
|
||||
browser_bug562890.js \
|
||||
browser_bug562899.js \
|
||||
browser_bug562992.js \
|
||||
|
77
toolkit/mozapps/extensions/test/browser/browser_bug557943.js
Normal file
77
toolkit/mozapps/extensions/test/browser/browser_bug557943.js
Normal file
@ -0,0 +1,77 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Bug 557943 - Searching for addons can result in wrong results
|
||||
|
||||
var gManagerWindow;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
gProvider.createAddons([{
|
||||
id: "addon1@tests.mozilla.org",
|
||||
name: "Microsoft .NET Framework Assistant",
|
||||
description: "",
|
||||
version: "6.66"
|
||||
}, {
|
||||
id: "addon2@tests.mozilla.org",
|
||||
name: "AwesomeNet Addon",
|
||||
description: ""
|
||||
}, {
|
||||
id: "addon3@tests.mozilla.org",
|
||||
name: "Dictionnaire MySpell en Francais (réforme 1990)",
|
||||
description: ""
|
||||
}]);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
close_manager(gManagerWindow, function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function perform_search(aQuery, aCallback) {
|
||||
var searchBox = gManagerWindow.document.getElementById("header-search");
|
||||
searchBox.value = aQuery;
|
||||
|
||||
EventUtils.synthesizeMouse(searchBox, 2, 2, { }, gManagerWindow);
|
||||
EventUtils.synthesizeKey("VK_RETURN", { }, gManagerWindow);
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
var list = gManagerWindow.document.getElementById("search-list");
|
||||
var rows = list.getElementsByTagName("richlistitem");
|
||||
aCallback(rows);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
add_test(function() {
|
||||
perform_search(".net", function(aRows) {
|
||||
is(aRows.length, 1, "Should only get one result");
|
||||
is(aRows[0].mAddon.id, "addon1@tests.mozilla.org", "Should get expected addon as only result");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function() {
|
||||
perform_search("réf", function(aRows) {
|
||||
is(aRows.length, 1, "Should only get one result");
|
||||
is(aRows[0].mAddon.id, "addon3@tests.mozilla.org", "Should get expected addon as only result");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function() {
|
||||
perform_search("javascript:void()", function(aRows) {
|
||||
is(aRows.length, 0, "Should not get any results");
|
||||
run_next_test();
|
||||
});
|
||||
});
|
@ -20,6 +20,9 @@ var gServer;
|
||||
var gAddonInstalled = false;
|
||||
|
||||
function test() {
|
||||
// Turn on searching for this test
|
||||
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
@ -41,9 +41,6 @@ function test() {
|
||||
operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
|
||||
}]);
|
||||
|
||||
// Turn off searching
|
||||
Services.prefs.setIntPref("extensions.getAddons.maxResults", 0);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
gDocument = gManagerWindow.document;
|
||||
|
@ -15,14 +15,22 @@ const CHROMEROOT = "chrome://mochikit/content/" + RELATIVE_DIR;
|
||||
const MANAGER_URI = "about:addons";
|
||||
const INSTALL_URI = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
|
||||
const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
|
||||
const PREF_SEARCH_MAXRESULTS = "extensions.getAddons.maxResults";
|
||||
|
||||
var gPendingTests = [];
|
||||
var gTestsRun = 0;
|
||||
|
||||
// Turn logging on for all tests
|
||||
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
|
||||
// Turn off remote results in searches
|
||||
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 0);
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
|
||||
try {
|
||||
Services.prefs.clearUserPref(PREF_SEARCH_MAXRESULTS);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
});
|
||||
|
||||
function add_test(test) {
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <winternl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
@ -58,31 +57,6 @@
|
||||
// define this for very verbose dll load debug spew
|
||||
#undef DEBUG_very_verbose
|
||||
|
||||
// This class takes care of setting and restoring the current directory
|
||||
// to make sure that the process current directory is not searched when
|
||||
// loading DLLs.
|
||||
class CurrentDirectoryGuard {
|
||||
public:
|
||||
CurrentDirectoryGuard() {
|
||||
::GetCurrentDirectoryW(MAX_PATH, mCwd);
|
||||
|
||||
WCHAR appPath[MAX_PATH] = {L'\0'};
|
||||
::GetModuleFileNameW(NULL, appPath, MAX_PATH);
|
||||
LPWSTR lastBackslash = wcsrchr(appPath, L'\\');
|
||||
if (lastBackslash) {
|
||||
*lastBackslash = L'\0';
|
||||
}
|
||||
::SetCurrentDirectoryW(appPath);
|
||||
}
|
||||
|
||||
~CurrentDirectoryGuard() {
|
||||
::SetCurrentDirectoryW(mCwd);
|
||||
}
|
||||
|
||||
private:
|
||||
WCHAR mCwd[MAX_PATH];
|
||||
};
|
||||
|
||||
// The signature for LdrLoadDll changed at some point, with the second arg
|
||||
// becoming a PULONG instead of a ULONG. This should only matter on 64-bit
|
||||
// systems, for which there was no support earlier -- on 32-bit systems,
|
||||
@ -235,14 +209,6 @@ continue_loading:
|
||||
|
||||
NS_SetHasLoadedNewDLLs();
|
||||
|
||||
// We need to make sure that the OS implementation of LdrLoadDll does not attempt
|
||||
// to load any DLLs from the current working directory. That's almost never what
|
||||
// we want, and it can cause us load unexpected DLLs. This guard protects against
|
||||
// that by setting the current directory to the application's directory before
|
||||
// LdrLoadDll is called, and restoring it to the original value when that call
|
||||
// returns.
|
||||
CurrentDirectoryGuard cwdGuard;
|
||||
|
||||
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
#include "nsUTF8Utils.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_IX86) && defined(XRE_WANT_DLL_BLOCKLIST) \
|
||||
!defined(MOZ_ENABLE_LIBXUL)
|
||||
#if defined(_MSC_VER) && defined(_M_IX86) && defined(XRE_WANT_DLL_BLOCKLIST)
|
||||
#include "nsWindowsDllBlocklist.cpp"
|
||||
#else
|
||||
#undef XRE_WANT_DLL_BLOCKLIST
|
||||
|
@ -704,15 +704,21 @@ nsWindow::Destroy(void)
|
||||
mIsDestroyed = PR_TRUE;
|
||||
mCreated = PR_FALSE;
|
||||
|
||||
nsRefPtr<GLContext> gl;
|
||||
if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL)
|
||||
{
|
||||
LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(GetLayerManager());
|
||||
gl = manager->gl();
|
||||
}
|
||||
|
||||
/** Need to clean our LayerManager up while still alive */
|
||||
mLayerManager = NULL;
|
||||
if (mLayerManager) {
|
||||
nsRefPtr<GLContext> gl = nsnull;
|
||||
if (mLayerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
|
||||
LayerManagerOGL *ogllm = static_cast<LayerManagerOGL*>(mLayerManager.get());
|
||||
gl = ogllm->gl();
|
||||
}
|
||||
|
||||
mLayerManager->Destroy();
|
||||
|
||||
if (gl) {
|
||||
gl->MarkDestroyed();
|
||||
}
|
||||
}
|
||||
mLayerManager = nsnull;
|
||||
|
||||
g_signal_handlers_disconnect_by_func(gtk_settings_get_default(),
|
||||
FuncToGpointer(theme_changed_cb),
|
||||
@ -789,9 +795,6 @@ nsWindow::Destroy(void)
|
||||
|
||||
gdk_window_set_user_data(mGdkWindow, NULL);
|
||||
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
|
||||
if (gl) {
|
||||
gl->WindowDestroyed();
|
||||
}
|
||||
gdk_window_destroy(mGdkWindow);
|
||||
mGdkWindow = nsnull;
|
||||
}
|
||||
|
@ -665,7 +665,10 @@ NS_METHOD nsWindow::Destroy()
|
||||
* On windows the LayerManagerOGL destructor wants the widget to be around for
|
||||
* cleanup. It also would like to have the HWND intact, so we NULL it here.
|
||||
*/
|
||||
mLayerManager = NULL;
|
||||
if (mLayerManager) {
|
||||
mLayerManager->Destroy();
|
||||
}
|
||||
mLayerManager = nsnull;
|
||||
|
||||
// The DestroyWindow function destroys the specified window. The function sends WM_DESTROY
|
||||
// and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus
|
||||
|
Loading…
Reference in New Issue
Block a user