m-c -> m-i merge
authorJustin Wood <Callek@gmail.com>
Fri, 09 Sep 2011 22:04:09 -0400
changeset 76861 068a0c2a28b2a1a6cd9758d15134b3d087156118
parent 76860 d09ca67df777d1cbdbdd470bd64c467d4e55b70a (current diff)
parent 76830 e986b99d847b35cb2ed48f04542af64c3a538945 (diff)
child 76862 b35689d684f7dc3990b87655ebedc7d398fef138
child 76865 a911910372a6fde94de8378dc198181c71cd500d
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone9.0a1
m-c -> m-i merge
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -810,37 +810,41 @@ public:
     void SetByteLength(GLuint byteLength) { mByteLength = byteLength; }
     void SetTarget(GLenum target) { mTarget = target; }
 
     // element array buffers are the only buffers for which we need to keep a copy of the data.
     // this method assumes that the byte length has previously been set by calling SetByteLength.
     PRBool CopyDataIfElementArray(const void* data) {
         if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
             mData = realloc(mData, mByteLength);
-            if (!mData)
+            if (!mData) {
+                mByteLength = 0;
                 return PR_FALSE;
+            }
             memcpy(mData, data, mByteLength);
         }
         return PR_TRUE;
     }
 
     // same comments as for CopyElementArrayData
     PRBool ZeroDataIfElementArray() {
         if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
             mData = realloc(mData, mByteLength);
-            if (!mData)
+            if (!mData) {
+                mByteLength = 0;
                 return PR_FALSE;
+            }
             memset(mData, 0, mByteLength);
         }
         return PR_TRUE;
     }
 
     // same comments as for CopyElementArrayData
     void CopySubDataIfElementArray(GLuint byteOffset, GLuint byteLength, const void* data) {
-        if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER && mByteLength) {
             memcpy((void*) (size_t(mData)+byteOffset), data, byteLength);
         }
     }
 
     // this method too is only for element array buffers. It returns the maximum value in the part of
     // the buffer starting at given offset, consisting of given count of elements. The type T is the type
     // to interprete the array elements as, must be GLushort or GLubyte.
     template<typename T>
@@ -1042,20 +1046,16 @@ protected:
     }
 
     PRBool CheckFloatTextureFilterParams() const {
         // Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported
         return (mMagFilter == LOCAL_GL_NEAREST) &&
             (mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
     }
 
-    PRBool DoesMinFilterRequireMipmap() const {
-        return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
-    }
-
     PRBool AreBothWrapModesClampToEdge() const {
         return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
     }
 
     PRBool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(size_t face) const {
         if (mHaveGeneratedMipmap)
             return PR_TRUE;
 
@@ -1149,16 +1149,22 @@ public:
     void SetWrapS(WebGLenum aWrapS) {
         mWrapS = aWrapS;
         SetDontKnowIfNeedFakeBlack();
     }
     void SetWrapT(WebGLenum aWrapT) {
         mWrapT = aWrapT;
         SetDontKnowIfNeedFakeBlack();
     }
+    
+    WebGLenum MinFilter() const { return mMinFilter; }
+
+    PRBool DoesMinFilterRequireMipmap() const {
+        return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
+    }
 
     void SetGeneratedMipmap() {
         if (!mHaveGeneratedMipmap) {
             mHaveGeneratedMipmap = PR_TRUE;
             SetDontKnowIfNeedFakeBlack();
         }
     }
 
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1746,17 +1746,38 @@ WebGLContext::GenerateMipmap(WebGLenum t
 
     if (!tex->AreAllLevel0ImageInfosEqual()) {
         return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type.");
     }
 
     tex->SetGeneratedMipmap();
 
     MakeContextCurrent();
+
+#ifdef XP_MACOSX
+    // On Mac, glGenerateMipmap on a texture whose minification filter does NOT require a mipmap at the time of the call,
+    // will happily grab random video memory into certain mipmap levels. See bug 684882. Also, this is Apple bug 9129398.
+    // Thanks to Kenneth Russell / Google for figuring this out.
+    // So we temporarily spoof the minification filter, call glGenerateMipmap,
+    // and restore it. If that turned out to not be enough, we would have to avoid calling glGenerateMipmap altogether and
+    // emulate it.
+    if (tex->DoesMinFilterRequireMipmap()) {
+        gl->fGenerateMipmap(target);
+    } else {
+        // spoof the min filter as something that requires a mipmap. The particular choice of a filter doesn't matter as
+        // we're not rendering anything here. Since LINEAR_MIPMAP_LINEAR is by far the most common use case, and we're trying
+        // to work around a bug triggered by "unexpected" min filters, it seems to be the safest choice.
+        gl->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR_MIPMAP_LINEAR);
+        gl->fGenerateMipmap(target);
+        gl->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, tex->MinFilter());
+    }
+#else
     gl->fGenerateMipmap(target);
+#endif
+    
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetActiveUniform(nsIWebGLProgram *pobj, PRUint32 index, nsIWebGLActiveInfo **retval)
 {
     *retval = nsnull;
 
--- a/xpcom/io/nsLocalFileWin.h
+++ b/xpcom/io/nsLocalFileWin.h
@@ -58,20 +58,21 @@
 #include <objbase.h>
 DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
 #endif
 
 #include "shlobj.h"
 
 #include <sys/stat.h>
 
-typedef PIDLIST_ABSOLUTE (*ILCreateFromPathWPtr)(PCWSTR);
-typedef void (*ILFreePtr)(PIDLIST_RELATIVE);
-typedef HRESULT (*SHOpenFolderAndSelectItemsPtr)(PCIDLIST_ABSOLUTE, UINT, 
-                                                 PCUITEMID_CHILD_ARRAY, DWORD);
+typedef LPITEMIDLIST (WINAPI *ILCreateFromPathWPtr)(PCWSTR);
+typedef void (WINAPI *ILFreePtr)(LPITEMIDLIST);
+typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsPtr)(LPCITEMIDLIST, UINT, 
+                                                        PCUITEMID_CHILD_ARRAY,
+                                                        DWORD);
 
 class nsLocalFile : public nsILocalFileWin,
                     public nsIHashable
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
     
     nsLocalFile();