michael@0: /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/Preferences.h" michael@0: michael@0: #include "SharedSurfaceGralloc.h" michael@0: michael@0: #include "GLContext.h" michael@0: #include "SharedSurfaceGL.h" michael@0: #include "SurfaceFactory.h" michael@0: #include "GLLibraryEGL.h" michael@0: #include "mozilla/layers/GrallocTextureClient.h" michael@0: #include "mozilla/layers/ShadowLayers.h" michael@0: michael@0: #include "ui/GraphicBuffer.h" michael@0: #include "../layers/ipc/ShadowLayers.h" michael@0: #include "ScopedGLHelpers.h" michael@0: michael@0: #include "gfxPlatform.h" michael@0: #include "gfx2DGlue.h" michael@0: #include "gfxPrefs.h" michael@0: michael@0: #define DEBUG_GRALLOC michael@0: #ifdef DEBUG_GRALLOC michael@0: #define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0) michael@0: #else michael@0: #define DEBUG_PRINT(...) do { } while (0) michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::gfx; michael@0: using namespace gl; michael@0: using namespace layers; michael@0: using namespace android; michael@0: michael@0: SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL, michael@0: const SurfaceCaps& caps, michael@0: layers::ISurfaceAllocator* allocator) michael@0: : SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps) michael@0: { michael@0: if (caps.surfaceAllocator) { michael@0: allocator = caps.surfaceAllocator; michael@0: } michael@0: michael@0: MOZ_ASSERT(allocator); michael@0: michael@0: mAllocator = allocator; michael@0: } michael@0: michael@0: SharedSurface_Gralloc* michael@0: SharedSurface_Gralloc::Create(GLContext* prodGL, michael@0: const GLFormats& formats, michael@0: const gfx::IntSize& size, michael@0: bool hasAlpha, michael@0: ISurfaceAllocator* allocator) michael@0: { michael@0: GLLibraryEGL* egl = &sEGLLibrary; michael@0: MOZ_ASSERT(egl); michael@0: michael@0: DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n"); michael@0: michael@0: if (!HasExtensions(egl, prodGL)) michael@0: return nullptr; michael@0: michael@0: gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA michael@0: : gfxContentType::COLOR; michael@0: michael@0: gfxImageFormat format michael@0: = gfxPlatform::GetPlatform()->OptimalFormatForContent(type); michael@0: michael@0: RefPtr grallocTC = michael@0: new GrallocTextureClientOGL( michael@0: allocator, michael@0: gfx::ImageFormatToSurfaceFormat(format), michael@0: gfx::BackendType::NONE, // we don't need to use it with a DrawTarget michael@0: TEXTURE_FLAGS_DEFAULT); michael@0: michael@0: if (!grallocTC->AllocateForGLRendering(size)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: sp buffer = grallocTC->GetGraphicBuffer(); michael@0: michael@0: EGLDisplay display = egl->Display(); michael@0: EGLClientBuffer clientBuffer = buffer->getNativeBuffer(); michael@0: EGLint attrs[] = { michael@0: LOCAL_EGL_NONE, LOCAL_EGL_NONE michael@0: }; michael@0: EGLImage image = egl->fCreateImage(display, michael@0: EGL_NO_CONTEXT, michael@0: LOCAL_EGL_NATIVE_BUFFER_ANDROID, michael@0: clientBuffer, attrs); michael@0: if (!image) { michael@0: return nullptr; michael@0: } michael@0: michael@0: prodGL->MakeCurrent(); michael@0: GLuint prodTex = 0; michael@0: prodGL->fGenTextures(1, &prodTex); michael@0: ScopedBindTexture autoTex(prodGL, prodTex); michael@0: michael@0: prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); michael@0: prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); michael@0: prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); michael@0: prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); michael@0: michael@0: prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image); michael@0: michael@0: egl->fDestroyImage(display, image); michael@0: michael@0: SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, grallocTC, prodTex); michael@0: michael@0: DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get()); michael@0: michael@0: return surf; michael@0: } michael@0: michael@0: michael@0: bool michael@0: SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl) michael@0: { michael@0: return egl->HasKHRImageBase() && michael@0: gl->IsExtensionSupported(GLContext::OES_EGL_image); michael@0: } michael@0: michael@0: SharedSurface_Gralloc::~SharedSurface_Gralloc() michael@0: { michael@0: michael@0: DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this); michael@0: michael@0: mGL->MakeCurrent(); michael@0: mGL->fDeleteTextures(1, &mProdTex); michael@0: } michael@0: michael@0: void michael@0: SharedSurface_Gralloc::Fence() michael@0: { michael@0: // We should be able to rely on genlock write locks/read locks. michael@0: // But they're broken on some configs, and even a glFinish doesn't michael@0: // work. glReadPixels seems to, though. michael@0: if (gfxPrefs::GrallocFenceWithReadPixels()) { michael@0: mGL->MakeCurrent(); michael@0: // read a 1x1 pixel michael@0: unsigned char pixels[4]; michael@0: mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &pixels[0]); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: SharedSurface_Gralloc::WaitSync() michael@0: { michael@0: return true; michael@0: }