bool SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { // Calling glReadPixels when an IOSurface is bound to the current framebuffer // can cause corruption in following glReadPixel calls (even if they aren't // reading from an IOSurface). // We workaround this by copying to a temporary texture, and doing the readback // from that. MOZ_ASSERT(mGL->IsCurrent()); ScopedTexture destTex(mGL); { ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); ScopedBindTexture bindTex(mGL, destTex.Texture()); mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB, x, y, width, height, 0); } ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); ScopedBindFramebuffer bindFB(mGL, destFB.FB()); mGL->raw_fReadPixels(0, 0, width, height, format, type, pixels); return true; }
static inline void newTex(GLuint tex, int w, int h, GLint internalFormat, GLenum format) { const auto target = GL_TEXTURE_2D; bindTex(tex, target); glTexImage2D(target, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, nullptr); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); }
bool SharedSurface_IOSurface::CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { /* Bug 896693 - OpenGL framebuffers that are backed by IOSurface on OSX expose a bug * in glCopyTexImage2D --- internalformats GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA * return the wrong results. To work around, copy framebuffer to a temporary texture * using GL_RGBA (which works), attach as read framebuffer and glCopyTexImage2D * instead. */ // https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage2D.xml says that width or // height set to 0 results in a NULL texture. Lets not do any work and punt to // original glCopyTexImage2D, since the FBO below will fail when trying to attach a // texture of 0 width or height. if (width == 0 || height == 0) return false; switch (internalformat) { case LOCAL_GL_ALPHA: case LOCAL_GL_LUMINANCE: case LOCAL_GL_LUMINANCE_ALPHA: break; default: return false; } MOZ_ASSERT(mGL->IsCurrent()); ScopedTexture destTex(mGL); { ScopedBindTexture bindTex(mGL, destTex.Texture()); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, x, y, width, height, 0); } ScopedFramebufferForTexture tmpFB(mGL, destTex.Texture(), LOCAL_GL_TEXTURE_2D); ScopedBindFramebuffer bindFB(mGL, tmpFB.FB()); mGL->raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height, border); return true; }
static inline void activeTex(GLuint tex, int num, GLenum target = GL_TEXTURE_2D) { glActiveTexture(GL_TEXTURE0 + num); bindTex(tex, target); }
static inline void uploadTex(GLuint tex, int w, int h, GLenum format, const void *data) { const auto target = GL_TEXTURE_2D; bindTex(tex, target); glTexSubImage2D(target, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, data); }