OSDN Git Service

Add external layer buffer cache management.
authorLin Johnson <johnson.lin@intel.com>
Tue, 28 Nov 2017 08:38:20 +0000 (16:38 +0800)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Sun, 10 Dec 2017 03:09:09 +0000 (19:09 -0800)
This is to avoid import and generate eglImage and
texture for every frame.

Jira: None
Tests: UI, Video, Camera work as before.
Signed-off-by: Lin Johnson <johnson.lin@intel.com>
26 files changed:
common/Android.mk
common/Makefile.sources
common/compositor/compositor.cpp
common/compositor/compositor.h
common/compositor/compositorthread.cpp
common/compositor/compositorthread.h
common/compositor/gl/glrenderer.cpp
common/compositor/gl/glrenderer.h
common/compositor/gl/glsurface.cpp
common/compositor/gl/nativeglresource.cpp
common/compositor/renderer.h
common/core/hwclayerbuffermanager.cpp [new file with mode: 0644]
common/core/hwclayerbuffermanager.h [new file with mode: 0644]
common/core/overlaylayer.cpp
common/core/overlaylayer.h
common/display/displayqueue.cpp
common/display/displayqueue.h
common/display/virtualdisplay.cpp
common/display/virtualdisplay.h
common/utils/hwctrace.h
os/android/platformdefines.h
os/linux/platformdefines.h
os/platformcommondefines.h
wsi/drm/drmbuffer.cpp
wsi/drm/drmbuffer.h
wsi/overlaybuffer.h

index accc682..38ccfb0 100644 (file)
@@ -72,6 +72,7 @@ LOCAL_SRC_FILES := \
        compositor/va/varenderer.cpp \
         core/gpudevice.cpp \
         core/hwclayer.cpp \
+        core/hwclayerbuffermanager.cpp \
        core/logicaldisplay.cpp \
        core/logicaldisplaymanager.cpp \
        core/mosaicdisplay.cpp \
index df8dfee..1670f67 100644 (file)
@@ -5,6 +5,7 @@ common_SOURCES =              \
     compositor/nativesurface.cpp \
     compositor/renderstate.cpp \
     core/hwclayer.cpp \
+    core/hwclayerbuffermanager.cpp \
     core/overlaylayer.cpp \
     core/gpudevice.cpp \
     core/logicaldisplay.cpp \
index fe7913a..ea7a889 100755 (executable)
@@ -37,11 +37,12 @@ Compositor::Compositor() {
 Compositor::~Compositor() {
 }
 
-void Compositor::Init(DisplayPlaneManager *plane_manager) {
+void Compositor::Init(DisplayPlaneManager *plane_manager,
+                      HwcLayerBufferManager *buffer_manager) {
   if (!thread_)
     thread_.reset(new CompositorThread());
 
-  thread_->Initialize(plane_manager);
+  thread_->Initialize(plane_manager, buffer_manager);
 }
 
 void Compositor::EnsureTasksAreDone() {
index bdd5443..4b36897 100644 (file)
@@ -32,6 +32,7 @@ namespace hwcomposer {
 
 class NativeBufferHandler;
 class DisplayPlaneManager;
+class HwcLayerBufferManager;
 struct OverlayLayer;
 
 class Compositor {
@@ -39,7 +40,8 @@ class Compositor {
   Compositor();
   ~Compositor();
 
-  void Init(DisplayPlaneManager *plane_manager);
+  void Init(DisplayPlaneManager *plane_manager,
+            HwcLayerBufferManager *buffer_manager);
   void Reset();
 
   Compositor(const Compositor &) = delete;
index 7316cba..7ec55f4 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "hwcutils.h"
 #include "hwctrace.h"
+#include "hwclayerbuffermanager.h"
 #include "nativegpuresource.h"
 #include "overlaylayer.h"
 #include "renderer.h"
@@ -36,12 +37,14 @@ CompositorThread::CompositorThread() : HWCThread(-8, "CompositorThread") {
 CompositorThread::~CompositorThread() {
 }
 
-void CompositorThread::Initialize(DisplayPlaneManager *plane_manager) {
+void CompositorThread::Initialize(DisplayPlaneManager *plane_manager,
+                                  HwcLayerBufferManager *buffer_manager) {
   tasks_lock_.lock();
   if (!gpu_resource_handler_)
     gpu_resource_handler_.reset(CreateNativeGpuResourceHandler());
 
   plane_manager_ = plane_manager;
+  buffer_manager_ = buffer_manager;
   tasks_lock_.unlock();
   if (!InitWorker()) {
     ETRACE("Failed to initalize CompositorThread. %s", PRINTERROR());
@@ -249,7 +252,7 @@ void CompositorThread::HandleMediaDrawRequest() {
 void CompositorThread::Ensure3DRenderer() {
   if (!gl_renderer_) {
     gl_renderer_.reset(Create3DRenderer());
-    if (!gl_renderer_->Init()) {
+    if (!gl_renderer_->Init(buffer_manager_)) {
       ETRACE("Failed to initialize OpenGL compositor %s", PRINTERROR());
       gl_renderer_.reset(nullptr);
     }
index e276db3..132edea 100644 (file)
@@ -34,13 +34,15 @@ namespace hwcomposer {
 
 class OverlayBuffer;
 class DisplayPlaneManager;
+class HwcLayerBufferManager;
 
 class CompositorThread : public HWCThread {
  public:
   CompositorThread();
   ~CompositorThread() override;
 
-  void Initialize(DisplayPlaneManager* plane_manager);
+  void Initialize(DisplayPlaneManager* plane_manager,
+                  HwcLayerBufferManager* buffer_manager);
 
   void Draw(std::vector<DrawState>& states,
             std::vector<DrawState>& media_states,
@@ -80,6 +82,7 @@ class CompositorThread : public HWCThread {
   bool disable_explicit_sync_;
   bool release_all_resources_;
   DisplayPlaneManager* plane_manager_ = NULL;
+  HwcLayerBufferManager* buffer_manager_ = NULL;
   uint32_t tasks_ = kNone;
   FDHandler fd_chandler_;
   HWCEvent cevent_;
index f002288..a2f2beb 100644 (file)
 #include "nativesurface.h"
 #include "renderstate.h"
 #include "shim.h"
+#include "hwclayerbuffermanager.h"
 
 namespace hwcomposer {
 
 GLRenderer::~GLRenderer() {
+  if (!context_.MakeCurrent()) {
+    ETRACE("Failed make current context.");
+    return;
+  }
+
+  if (buffer_manager_)
+    buffer_manager_->PurgeGraphicsResources();
   if (vertex_array_)
     glDeleteVertexArraysOES(1, &vertex_array_);
 }
 
-bool GLRenderer::Init() {
+bool GLRenderer::Init(HwcLayerBufferManager *buffer_manager) {
   // clang-format off
+  buffer_manager_ = buffer_manager;
   const GLfloat verts[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f,
                            0.0f, 2.0f, 2.0f, 0.0f, 2.0f, 0.0f};
   // clang-format on
index 400b48f..650d365 100644 (file)
@@ -32,7 +32,7 @@ class GLRenderer : public Renderer {
   GLRenderer() = default;
   ~GLRenderer();
 
-  bool Init() override;
+  bool Init(HwcLayerBufferManager *buffer_manager) override;
   bool Draw(const std::vector<RenderState> &commands, NativeSurface *surface,
             bool clear_surface) override;
 
@@ -44,6 +44,7 @@ class GLRenderer : public Renderer {
   GLProgram *GetProgram(unsigned texture_count);
 
   EGLOffScreenContext context_;
+  HwcLayerBufferManager *buffer_manager_;
 
   std::vector<std::unique_ptr<GLProgram>> programs_;
   GLuint vertex_array_ = 0;
index 81f445a..3944bba 100644 (file)
@@ -54,7 +54,6 @@ bool GLSurface::InitializeGPUResources() {
   glBindTexture(GL_TEXTURE_2D, 0);
 
   tex_ = texture;
-  eglDestroyImageKHR(egl_display, image);
 
   // Create Fb.
   GLuint gl_fb;
index 537a342..e72ea91 100644 (file)
@@ -36,17 +36,8 @@ bool NativeGLResource::PrepareResources(
       ETRACE("Failed to make import image.");
       return false;
     }
-
-    GLuint texture;
-    glGenTextures(1, &texture);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
-                                 (GLeglImageOES)egl_image);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+    GLuint texture = (GLuint)buffer->GetImageTexture();
     layer_textures_.emplace_back(texture);
-    eglDestroyImageKHR(egl_display, egl_image);
   }
 
   return true;
@@ -61,12 +52,6 @@ void NativeGLResource::ReleaseGPUResources() {
 }
 
 void NativeGLResource::Reset() {
-  GLuint texture_id = 0;
-  size_t size = layer_textures_.size();
-  for (size_t i = 0; i < size; i++) {
-    texture_id = layer_textures_.at(i);
-    glDeleteTextures(1, &texture_id);
-  }
 }
 
 GpuResourceHandle NativeGLResource::GetResourceHandle(
index c357b68..691af3a 100644 (file)
@@ -18,6 +18,7 @@
 #define COMMON_COMPOSITOR_RENDERER_H_
 
 #include <stdint.h>
+#include <stddef.h>
 
 #include <vector>
 
@@ -26,6 +27,7 @@ namespace hwcomposer {
 class NativeSurface;
 struct RenderState;
 struct MediaState;
+class HwcLayerBufferManager;
 
 class Renderer {
  public:
@@ -36,9 +38,10 @@ class Renderer {
   Renderer& operator=(const Renderer& rhs) = delete;
 
   // Needs to be implemented for 3D Renderer's only.
-  virtual bool Init() {
+  virtual bool Init(HwcLayerBufferManager* /*buffer_manager*/) {
     return false;
   }
+
   virtual bool Draw(const std::vector<RenderState>& /*commands*/,
                     NativeSurface* /*surface*/, bool /*clear_surface*/) {
     return false;
diff --git a/common/core/hwclayerbuffermanager.cpp b/common/core/hwclayerbuffermanager.cpp
new file mode 100644 (file)
index 0000000..7ad430e
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+// Copyright (c) 2016 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "hwclayerbuffermanager.h"
+
+namespace hwcomposer {
+
+HwcLayerBufferManager::HwcLayerBufferManager() {
+  for(size_t i = 0; i < BUFFER_CACHE_LENGTH; i++)
+    cached_buffers_.emplace_back();
+}
+
+HwcLayerBufferManager::~HwcLayerBufferManager() {
+    PurgeBuffer();
+}
+
+void HwcLayerBufferManager::PurgeBuffer() {
+  for(auto &map : cached_buffers_) {
+       map.clear();
+  }
+}
+
+void HwcLayerBufferManager::PurgeGraphicsResources() {
+  for (auto& map : cached_buffers_) {
+    for (auto& pair : map) {
+      pair.second->DeleteImage();
+      pair.second->DeleteTexture();
+    }
+  }
+}
+
+void HwcLayerBufferManager::Dump() {
+}
+
+std::shared_ptr<OverlayBuffer>& HwcLayerBufferManager::FindCachedBuffer(const HWCNativeBuffer& native_buffer) {
+
+  BUFFER_MAP&  first_map = cached_buffers_[0];
+  static std::shared_ptr<OverlayBuffer> pBufNull = nullptr;
+  for (auto& map : cached_buffers_) {
+    if (map.count(native_buffer)) {
+      std::shared_ptr<OverlayBuffer>& pBuf = map[native_buffer];
+      if (&map != &first_map) {
+        first_map.emplace(std::make_pair(native_buffer, pBuf));
+        map.erase(native_buffer);
+      }
+#ifdef CACHE_TRACING
+      hit_count_++;
+#endif
+      return pBuf;
+    }
+  }
+
+#ifdef CACHE_TRACING
+  miss_count_++;
+  if (miss_count_ % 100 == 0)
+    ICACHETRACE("cache miss count is %llu, while hit count is %llu",
+                miss_count_, hit_count_);
+#endif
+
+  return pBufNull;
+}
+
+void HwcLayerBufferManager::RegisterBuffer(const HWCNativeBuffer& native_buffer, std::shared_ptr<OverlayBuffer>& pBuffer) {
+
+  BUFFER_MAP&  first_map = cached_buffers_[0];
+  first_map.emplace(std::make_pair(native_buffer, pBuffer));
+}
+
+void HwcLayerBufferManager::RefreshBufferCache() {
+  auto begin = cached_buffers_.begin();
+  cached_buffers_.emplace(begin);
+  cached_buffers_.pop_back();
+}
+
+}  // namespace hwcomposer
diff --git a/common/core/hwclayerbuffermanager.h b/common/core/hwclayerbuffermanager.h
new file mode 100644 (file)
index 0000000..7156dc8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+/*
+Design of hwclayerbuffermanager:
+The purpose is to add cache magagement to external buffer owned by hwcLayer
+to avoid import buffer and glimage/texture generation overhead
+
+1: the hwclayerbuffermanager is owned per display, as each display has a
+separate
+GL context
+2: hwclayerbuffermanager stores a refernce of external buffers in a vector
+   cached_buffers, each vector member is hash map.
+   The vector stores history buffer in this way, vector[0] is for the current
+   frame buffers, vector[1] is for last frame (-1) buffers, vector[2] is -2
+   frames buffers etc. A constant (currently 4) frames of buffers is stored.
+   When a buffer refernce is stored in vector[3] and it is not used in the
+   current frame present, it will go out of scope and be released.
+   If a buffer is fetched from map, it will always re-registered in vector[0]
+map.
+3. By this way, drm_buffer now owns eglImage and gltexture and they
+   can be resued.
+*/
+
+#ifndef COMMON_CORE_HWCLAYERBUFFER_MANAGER_H_
+#define COMMON_CORE_HWCLAYERBUFFER_MANAGER_H_
+
+#include <hwcdefs.h>
+#include <platformdefines.h>
+#include <hwctrace.h>
+
+#include <memory>
+#include <unordered_map>
+
+#include "overlaybuffer.h"
+
+namespace hwcomposer {
+
+struct HwcLayer;
+class OverlayBuffer;
+class NativeBufferHandler;
+
+class HwcLayerBufferManager {
+
+public:
+  HwcLayerBufferManager();
+  ~HwcLayerBufferManager();
+  void Dump();
+  std::shared_ptr<OverlayBuffer>& FindCachedBuffer(const HWCNativeBuffer& native_buffer);
+  void RegisterBuffer(const HWCNativeBuffer& native_buffer, std::shared_ptr<OverlayBuffer>& pBuffer);
+  void RefreshBufferCache();
+  void PurgeGraphicsResources();
+
+private:
+  void PurgeBuffer();
+
+#define BUFFER_CACHE_LENGTH 4
+  typedef std::unordered_map<HWCNativeBuffer, std::shared_ptr<OverlayBuffer>,
+                            BufferHash, BufferEqual> BUFFER_MAP;
+  std::vector<BUFFER_MAP> cached_buffers_;
+};
+
+}  // namespace hwcomposer
+#endif  // COMMON_CORE_OVERLAYLAYER_H_
index 4997813..04dc36b 100644 (file)
@@ -24,6 +24,7 @@
 #include "hwcutils.h"
 
 #include <nativebufferhandler.h>
+#include "hwclayerbuffermanager.h"
 
 namespace hwcomposer {
 
@@ -33,10 +34,10 @@ OverlayLayer::ImportedBuffer::~ImportedBuffer() {
   }
 }
 
-OverlayLayer::ImportedBuffer::ImportedBuffer(OverlayBuffer* buffer,
-                                             int32_t acquire_fence)
+OverlayLayer::ImportedBuffer::ImportedBuffer(
+    std::shared_ptr<OverlayBuffer>& buffer, int32_t acquire_fence)
     : acquire_fence_(acquire_fence) {
-  buffer_.reset(buffer);
+  buffer_ = buffer;
 }
 
 void OverlayLayer::SetAcquireFence(int32_t acquire_fence) {
@@ -59,13 +60,27 @@ int32_t OverlayLayer::ReleaseAcquireFence() const {
 }
 
 OverlayBuffer* OverlayLayer::GetBuffer() const {
+  if (imported_buffer_->buffer_.get() == NULL)
+    ETRACE("hwc layer get NullBuffer");
   return imported_buffer_->buffer_.get();
 }
 
 void OverlayLayer::SetBuffer(NativeBufferHandler* buffer_handler,
-                             HWCNativeHandle handle, int32_t acquire_fence) {
-  OverlayBuffer* buffer = OverlayBuffer::CreateOverlayBuffer();
-  buffer->InitializeFromNativeHandle(handle, buffer_handler);
+                             HWCNativeHandle handle, int32_t acquire_fence,
+                             HwcLayerBufferManager* buffer_manager) {
+  std::shared_ptr<OverlayBuffer> buffer(NULL);
+
+  if (buffer_manager) {
+    buffer = buffer_manager->FindCachedBuffer(GETNATIVEBUFFER(handle));
+  }
+
+  if (buffer == NULL) {
+    buffer = OverlayBuffer::CreateOverlayBuffer();
+    buffer->InitializeFromNativeHandle(handle, buffer_handler);
+    if (buffer_manager) {
+      buffer_manager->RegisterBuffer(GETNATIVEBUFFER(handle), buffer);
+    }
+  }
   imported_buffer_.reset(new ImportedBuffer(buffer, acquire_fence));
 }
 
@@ -189,6 +204,7 @@ void OverlayLayer::UpdateSurfaceDamage(HwcLayer* /*layer*/) {
 
 void OverlayLayer::InitializeState(HwcLayer* layer,
                                    NativeBufferHandler* buffer_handler,
+                                   HwcLayerBufferManager* buffer_manager,
                                    OverlayLayer* previous_layer,
                                    uint32_t z_order, uint32_t layer_index,
                                    uint32_t max_height, HWCRotation rotation,
@@ -210,7 +226,8 @@ void OverlayLayer::InitializeState(HwcLayer* layer,
   source_crop_height_ = layer->GetSourceCropHeight();
   source_crop_ = layer->GetSourceCrop();
   blending_ = layer->GetBlending();
-  SetBuffer(buffer_handler, layer->GetNativeHandle(), layer->GetAcquireFence());
+  SetBuffer(buffer_handler, layer->GetNativeHandle(), layer->GetAcquireFence(),
+            buffer_manager);
   ValidateForOverlayUsage();
   if (previous_layer) {
     ValidatePreviousFrameState(previous_layer, layer);
@@ -306,23 +323,26 @@ void OverlayLayer::InitializeState(HwcLayer* layer,
 
 void OverlayLayer::InitializeFromHwcLayer(
     HwcLayer* layer, NativeBufferHandler* buffer_handler,
-    OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
-    uint32_t max_height, HWCRotation rotation, bool handle_constraints) {
+    HwcLayerBufferManager* buffer_manager, OverlayLayer* previous_layer,
+    uint32_t z_order, uint32_t layer_index, uint32_t max_height,
+    HWCRotation rotation, bool handle_constraints) {
   display_frame_width_ = layer->GetDisplayFrameWidth();
   display_frame_height_ = layer->GetDisplayFrameHeight();
   display_frame_ = layer->GetDisplayFrame();
-  InitializeState(layer, buffer_handler, previous_layer, z_order, layer_index,
-                  max_height, rotation, handle_constraints);
+  InitializeState(layer, buffer_handler, buffer_manager, previous_layer,
+                  z_order, layer_index, max_height, rotation,
+                  handle_constraints);
 }
 
 void OverlayLayer::InitializeFromScaledHwcLayer(
     HwcLayer* layer, NativeBufferHandler* buffer_handler,
-    OverlayLayer* previous_layer, uint32_t z_order, uint32_t layer_index,
-    const HwcRect<int>& display_frame, uint32_t max_height,
-    HWCRotation rotation, bool handle_constraints) {
+    HwcLayerBufferManager* buffer_manager, OverlayLayer* previous_layer,
+    uint32_t z_order, uint32_t layer_index, const HwcRect<int>& display_frame,
+    uint32_t max_height, HWCRotation rotation, bool handle_constraints) {
   SetDisplayFrame(display_frame);
-  InitializeState(layer, buffer_handler, previous_layer, z_order, layer_index,
-                  max_height, rotation, handle_constraints);
+  InitializeState(layer, buffer_handler, buffer_manager, previous_layer,
+                  z_order, layer_index, max_height, rotation,
+                  handle_constraints);
 }
 
 void OverlayLayer::ValidatePreviousFrameState(OverlayLayer* rhs,
@@ -390,7 +410,7 @@ void OverlayLayer::ValidatePreviousFrameState(OverlayLayer* rhs,
 }
 
 void OverlayLayer::ValidateForOverlayUsage() {
-  const std::unique_ptr<OverlayBuffer>& buffer = imported_buffer_->buffer_;
+  const std::shared_ptr<OverlayBuffer>& buffer = imported_buffer_->buffer_;
   if (buffer->GetUsage() & kLayerCursor) {
     type_ = kLayerCursor;
   } else if (buffer->IsVideoBuffer()) {
index be5f855..ca25e3c 100644 (file)
@@ -30,6 +30,7 @@ namespace hwcomposer {
 struct HwcLayer;
 class OverlayBuffer;
 class NativeBufferHandler;
+class HwcLayerBufferManager;
 
 struct OverlayLayer {
   OverlayLayer() = default;
@@ -42,17 +43,16 @@ struct OverlayLayer {
   // Initialize OverlayLayer from layer.
   void InitializeFromHwcLayer(HwcLayer* layer,
                               NativeBufferHandler* buffer_handler,
+                              HwcLayerBufferManager* buffer_manager,
                               OverlayLayer* previous_layer, uint32_t z_order,
                               uint32_t layer_index, uint32_t max_height,
                               HWCRotation rotation, bool handle_constraints);
 
-  void InitializeFromScaledHwcLayer(HwcLayer* layer,
-                                    NativeBufferHandler* buffer_handler,
-                                    OverlayLayer* previous_layer,
-                                    uint32_t z_order, uint32_t layer_index,
-                                    const HwcRect<int>& display_frame,
-                                    uint32_t max_height, HWCRotation rotation,
-                                    bool handle_constraints);
+  void InitializeFromScaledHwcLayer(
+      HwcLayer* layer, NativeBufferHandler* buffer_handler,
+      HwcLayerBufferManager* buffer_manager, OverlayLayer* previous_layer,
+      uint32_t z_order, uint32_t layer_index, const HwcRect<int>& display_frame,
+      uint32_t max_height, HWCRotation rotation, bool handle_constraints);
   // Get z order of this layer.
   uint32_t GetZorder() const {
     return z_order_;
@@ -89,7 +89,8 @@ struct OverlayLayer {
   OverlayBuffer* GetBuffer() const;
 
   void SetBuffer(NativeBufferHandler* buffer_handler, HWCNativeHandle handle,
-                 int32_t acquire_fence);
+                 int32_t acquire_fence,
+                 HwcLayerBufferManager* buffer_manager = NULL);
   void ResetBuffer();
 
   void SetSourceCrop(const HwcRect<float>& source_crop);
@@ -192,10 +193,11 @@ struct OverlayLayer {
 
   struct ImportedBuffer {
    public:
-    ImportedBuffer(OverlayBuffer* buffer, int32_t acquire_fence);
+    ImportedBuffer(std::shared_ptr<OverlayBuffer>& buffer,
+                   int32_t acquire_fence);
     ~ImportedBuffer();
 
-    std::unique_ptr<OverlayBuffer> buffer_;
+    std::shared_ptr<OverlayBuffer> buffer_;
     int32_t acquire_fence_ = -1;
   };
 
@@ -214,6 +216,7 @@ struct OverlayLayer {
   void UpdateSurfaceDamage(HwcLayer* layer);
 
   void InitializeState(HwcLayer* layer, NativeBufferHandler* buffer_handler,
+                       HwcLayerBufferManager* buffer_manager,
                        OverlayLayer* previous_layer, uint32_t z_order,
                        uint32_t layer_index, uint32_t max_height,
                        HWCRotation rotation, bool handle_constraints);
index b5f966b..f380b49 100644 (file)
@@ -89,6 +89,12 @@ bool DisplayQueue::Initialize(uint32_t pipe, uint32_t width, uint32_t height,
     return false;
   }
 
+  buffer_manager_.reset(new HwcLayerBufferManager());
+  if (!buffer_manager_) {
+    ETRACE("Failed to construct hwc layer buffer manager");
+    return false;
+  }
+
   vblank_handler_->SetPowerMode(kOff);
   vblank_handler_->Init(gpu_fd_, pipe);
   return true;
@@ -111,7 +117,7 @@ bool DisplayQueue::SetPowerMode(uint32_t power_mode) {
       vblank_handler_->SetPowerMode(kOn);
       power_mode_lock_.lock();
       state_ &= ~kIgnoreIdleRefresh;
-      compositor_.Init(display_plane_manager_.get());
+      compositor_.Init(display_plane_manager_.get(), buffer_manager_.get());
       power_mode_lock_.unlock();
       break;
     default:
@@ -300,6 +306,8 @@ bool DisplayQueue::QueueUpdate(std::vector<HwcLayer*>& source_layers,
     cursor_state_changed = true;
   }
 
+  buffer_manager_->RefreshBufferCache();
+
   for (size_t layer_index = 0; layer_index < size; layer_index++) {
     HwcLayer* layer = source_layers.at(layer_index);
     layer->SetReleaseFence(-1);
@@ -328,13 +336,14 @@ bool DisplayQueue::QueueUpdate(std::vector<HwcLayer*>& source_layers,
           (display_frame.bottom * scaling_tracker_.scaling_height);
 
       overlay_layer->InitializeFromScaledHwcLayer(
-          layer, buffer_handler_, previous_layer, z_order, layer_index,
-          display_frame, display_plane_manager_->GetHeight(), rotation_,
-          handle_constraints);
+          layer, buffer_handler_, buffer_manager_.get(), previous_layer,
+          z_order, layer_index, display_frame,
+          display_plane_manager_->GetHeight(), rotation_, handle_constraints);
     } else {
       overlay_layer->InitializeFromHwcLayer(
-          layer, buffer_handler_, previous_layer, z_order, layer_index,
-          display_plane_manager_->GetHeight(), rotation_, handle_constraints);
+          layer, buffer_handler_, buffer_manager_.get(), previous_layer,
+          z_order, layer_index, display_plane_manager_->GetHeight(), rotation_,
+          handle_constraints);
     }
 
     if (!overlay_layer->IsVisible()) {
index 317089e..59ba02e 100644 (file)
@@ -31,6 +31,7 @@
 #include "hwcthread.h"
 #include "vblankeventhandler.h"
 #include "platformdefines.h"
+#include "hwclayerbuffermanager.h"
 
 namespace hwcomposer {
 struct gamma_colors {
@@ -249,6 +250,7 @@ class DisplayQueue {
   struct gamma_colors gamma_;
   std::unique_ptr<VblankEventHandler> vblank_handler_;
   std::unique_ptr<DisplayPlaneManager> display_plane_manager_;
+  std::unique_ptr<HwcLayerBufferManager> buffer_manager_;
   std::vector<OverlayLayer> in_flight_layers_;
   DisplayPlaneStateList previous_plane_state_;
   NativeBufferHandler* buffer_handler_;
index 810a13f..2775efc 100644 (file)
@@ -39,6 +39,10 @@ VirtualDisplay::VirtualDisplay(uint32_t /*gpu_fd*/,
       buffer_handler_(buffer_handler),
       width_(0),
       height_(0) {
+  buffer_manager_.reset(new HwcLayerBufferManager());
+  if (!buffer_manager_) {
+    ETRACE("Failed to construct hwc layer buffer manager");
+  }
 }
 
 VirtualDisplay::~VirtualDisplay() {
@@ -54,7 +58,7 @@ VirtualDisplay::~VirtualDisplay() {
 }
 
 void VirtualDisplay::InitVirtualDisplay(uint32_t width, uint32_t height) {
-  compositor_.Init(nullptr);
+  compositor_.Init(nullptr, buffer_manager_.get());
   width_ = width;
   height_ = height;
 }
@@ -85,8 +89,9 @@ bool VirtualDisplay::Present(std::vector<HwcLayer *> &source_layers,
   *retire_fence = -1;
   uint32_t z_order = 0;
 
+  buffer_manager_->RefreshBufferCache();
   for (size_t layer_index = 0; layer_index < size; layer_index++) {
-    HwcLayerlayer = source_layers.at(layer_index);
+    HwcLayer *layer = source_layers.at(layer_index);
     layer->SetReleaseFence(-1);
     if (!layer->IsVisible())
       continue;
@@ -98,9 +103,9 @@ bool VirtualDisplay::Present(std::vector<HwcLayer *> &source_layers,
       previous_layer = &(in_flight_layers_.at(z_order));
     }
 
-    overlay_layer.InitializeFromHwcLayer(layer, buffer_handler_, previous_layer,
-                                         z_order, layer_index, width_,
-                                         kRotateNone, handle_constraints);
+    overlay_layer.InitializeFromHwcLayer(
+        layer, buffer_handler_, buffer_manager_.get(), previous_layer, z_order,
+        layer_index, width_, kRotateNone, handle_constraints);
     index.emplace_back(z_order);
     layers_rects.emplace_back(layer->GetDisplayFrame());
     z_order++;
index c5beb2d..664458a 100644 (file)
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include "compositor.h"
+#include "hwclayerbuffermanager.h"
 
 namespace hwcomposer {
 struct HwcLayer;
@@ -87,6 +88,7 @@ class VirtualDisplay : public NativeDisplay {
   uint32_t height_ = 1;
   std::vector<OverlayLayer> in_flight_layers_;
   HWCNativeHandle handle_ = 0;
+  std::unique_ptr<HwcLayerBufferManager> buffer_manager_;
 };
 
 }  // namespace hwcomposer
index 8634a5b..f6f3932 100644 (file)
@@ -112,6 +112,12 @@ class TraceFunc {
 #define ICOMPOSITORTRACE(fmt, ...) ((void)0)
 #endif
 
+#ifdef CACHE_TRACING
+#define ICACHETRACE ITRACE
+#else
+#define ICACHETRACE ((void)0)
+#endif
+
 // Errors
 #define PRINTERROR() strerror(-errno)
 
index 811decc..6e59ce2 100644 (file)
 #include <cutils/log.h>
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
-
 #include <ui/GraphicBuffer.h>
-
 #include "platformcommondefines.h"
-
+#include <cros_gralloc_handle.h>
 #define DRV_I915 1
 #include <i915_private_android_types.h>
 
@@ -51,6 +49,37 @@ struct gralloc_handle {
 };
 
 typedef struct gralloc_handle* HWCNativeHandle;
+typedef struct cros_gralloc_handle HWCNativeBuffer;
+#define GETNATIVEBUFFER(handle) (*(cros_gralloc_handle*)(handle->handle_))
+
+
+struct BufferHash {
+  size_t operator()(HWCNativeBuffer const& buffer) const {
+    const native_handle_t & p = buffer.base;
+    std::size_t seed = 0;
+    for (int i = 0; i < p.numFds + p.numInts; i++) {
+      hash_combine_hwc(seed, (const size_t)p.data[i]);
+    }
+    return seed;
+  }
+};
+
+struct BufferEqual {
+  bool operator()(const HWCNativeBuffer& buffer1, const HWCNativeBuffer& buffer2) const {
+    const native_handle_t &p1 = buffer1.base;
+    const native_handle_t &p2 = buffer2.base;
+    bool equal = (p1.numFds == p2.numFds) && (p1.numInts ==  p2.numInts);
+    if (equal) {
+      for (int i = 0; i < p1.numFds + p1.numInts; i++) {
+        equal = equal && (p1.data[i] == p2.data[i]);
+        if (!equal)
+          break;
+      }
+    }
+    return equal;
+  }
+};
+
 
 #define VTRACE(fmt, ...) ALOGV("%s: " fmt, __func__, ##__VA_ARGS__)
 #define DTRACE(fmt, ...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__)
index b4ee6f1..6e163ab 100644 (file)
@@ -44,6 +44,64 @@ struct gbm_handle {
 };
 
 typedef struct gbm_handle* HWCNativeHandle;
+#define GETNATIVEBUFFER(handle) (handle->import_data)
+
+#ifdef USE_MINIGBM
+typedef gbm_import_fd_planar_data HWCNativeBuffer;
+struct BufferHash {
+  size_t operator()(gbm_import_fd_planar_data const& p) const {
+    std::size_t seed = 0;
+    for (int i = 0; i < GBM_MAX_PLANES; i++) {
+      hash_combine_hwc(seed, (const size_t)p.fds[i]);
+    }
+    // avoid to consider next information?
+    hash_combine_hwc(seed, p.width);
+    hash_combine_hwc(seed, p.height);
+    hash_combine_hwc(seed, p.format);
+    return seed;
+  }
+};
+
+struct BufferEqual {
+  bool operator()(const gbm_import_fd_planar_data& p1,
+                  const gbm_import_fd_planar_data& p2) const {
+    bool equal = true;
+    for (int i = 0; i < GBM_MAX_PLANES; i++) {
+      equal = equal && (p1.fds[i] == p2.fds[i]);
+      if (!equal)
+        break;
+    }
+    if (equal)
+      equal = equal && (p1.width == p2.width) && (p1.height == p2.height) &&
+              (p1.format == p2.format);
+    return equal;
+  }
+};
+#else
+
+typedef gbm_import_fd_data HWCNativeBuffer;
+struct BufferHash {
+  size_t operator()(gbm_import_fd_data const& p) const {
+    std::size_t seed = 0;
+    hash_combine_hwc(seed, p.fd);
+    hash_combine_hwc(seed, p.width);
+    hash_combine_hwc(seed, p.height);
+    hash_combine_hwc(seed, p.stride);
+    hash_combine_hwc(seed, p.format);
+    return seed;
+  }
+};
+struct BufferEqual {
+  bool operator()(const gbm_import_fd_data& p1,
+                  const gbm_import_fd_data& p2) const {
+    bool equal = (p1.fd == p2.fd) && (p1.width == p2.width) &&
+                 (p1.height == p2.height) && (p1.stride == p2.stride) &&
+                 (p1.format == p2.format);
+    return equal;
+  }
+};
+
+#endif
 
 #ifdef _cplusplus
 extern "C" {
index 9619bdc..2bd52d6 100644 (file)
@@ -31,4 +31,8 @@ VkFormat NativeToVkFormat(int native_format);
 // minigbm specific DRM_FORMAT_YVU420_ANDROID enum
 #define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
 
+inline void hash_combine_hwc(size_t seed, size_t value) {
+  seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
 #endif  // OS_LINUX_PLATFORMCOMMONDEFINES_H_
index 8bcb00d..3c6f70e 100644 (file)
@@ -30,6 +30,16 @@ namespace hwcomposer {
 
 DrmBuffer::~DrmBuffer() {
   ReleaseFrameBuffer();
+#if USE_GL
+  if (image_)
+    eglDestroyImageKHR(display_, image_);
+  if (texture_) {
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+    glDeleteTextures(1, &texture_);
+  }
+#elif USE_VK
+
+#endif
 
   if (buffer_handler_ && handle_) {
     buffer_handler_->ReleaseBuffer(handle_);
@@ -103,6 +113,9 @@ void DrmBuffer::InitializeFromNativeHandle(
 }
 
 GpuImage DrmBuffer::ImportImage(GpuDisplay egl_display) {
+  if (image_)
+    return image_;
+
 #ifdef USE_GL
   EGLImageKHR image = EGL_NO_IMAGE_KHR;
   // Note: If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT
@@ -156,6 +169,8 @@ GpuImage DrmBuffer::ImportImage(GpuDisplay egl_display) {
                           static_cast<EGLClientBuffer>(nullptr), attr_list);
   }
 
+  image_ = image;
+  display_ = egl_display;
   return image;
 #elif USE_VK
   struct vk_import import;
@@ -192,18 +207,67 @@ GpuImage DrmBuffer::ImportImage(GpuDisplay egl_display) {
   import.res = vkCreateDmaBufImageINTEL(egl_display, &image_create, NULL,
                                         &import.memory, &import.image);
 
+  image_ = import;
+  display_ = egl_display;
   return import;
 #else
   return NULL;
 #endif
 }
 
+void DrmBuffer::DeleteImage() {
+#if USE_GL
+  if (image_)
+    eglDestroyImageKHR(display_, image_);
+  image_ = 0;
+#endif
+}
+
+void DrmBuffer::DeleteTexture() {
+#if USE_GL
+  if (texture_) {
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+    glDeleteTextures(1, &texture_);
+  }
+#endif
+}
+
+uint32_t DrmBuffer::GetImageTexture() {
+#ifdef USE_GL
+  if (texture_ != 0) {
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
+                                 (GLeglImageOES)image_);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+    return texture_;
+  }
+
+  GLuint texture;
+  glGenTextures(1, &texture);
+  glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
+  glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image_);
+  glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+  texture_ = texture;
+  return texture;
+#elif USE_VK
+  return 0;
+#else
+  return 0;
+#endif
+}
+
 void DrmBuffer::SetRecommendedFormat(uint32_t format) {
   frame_buffer_format_ = format;
 }
 
 bool DrmBuffer::CreateFrameBuffer(uint32_t gpu_fd) {
-  ReleaseFrameBuffer();
+  if (fb_id_) {
+    // Has been created before
+    return true;
+  }
+
   int ret = drmModeAddFB2(gpu_fd, width_, height_, frame_buffer_format_,
                           gem_handles_, pitches_, offsets_, &fb_id_, 0);
 
@@ -251,8 +315,8 @@ void DrmBuffer::Dump() {
   DUMPTRACE("DrmBuffer Information Ends. -------------");
 }
 
-OverlayBuffer* OverlayBuffer::CreateOverlayBuffer() {
-  return new DrmBuffer();
+std::shared_ptr<OverlayBuffer> OverlayBuffer::CreateOverlayBuffer() {
+  return std::make_shared<DrmBuffer>();
 }
 
 }  // namespace hwcomposer
index 9573b1d..61f57e7 100644 (file)
@@ -75,6 +75,10 @@ class DrmBuffer : public OverlayBuffer {
   }
 
   GpuImage ImportImage(GpuDisplay egl_display) override;
+  void DeleteImage() override;
+
+  uint32_t GetImageTexture() override;
+  void DeleteTexture() override;
 
   bool CreateFrameBuffer(uint32_t gpu_fd) override;
 
@@ -104,6 +108,9 @@ class DrmBuffer : public OverlayBuffer {
   bool is_yuv_ = false;
   HWCNativeHandle handle_ = 0;
   NativeBufferHandler* buffer_handler_ = 0;
+  GpuImage image_ = 0;
+  GpuDisplay display_ = 0;
+  uint32_t texture_ = 0;
 };
 
 }  // namespace hwcomposer
index 8892a84..6328054 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <platformdefines.h>
 
+#include <memory>
+
 #include "compositordefs.h"
 
 namespace hwcomposer {
@@ -26,7 +28,7 @@ class NativeBufferHandler;
 
 class OverlayBuffer {
  public:
-  static OverlayBuffer* CreateOverlayBuffer();
+  static std::shared_ptr<OverlayBuffer> CreateOverlayBuffer();
 
   OverlayBuffer(OverlayBuffer&& rhs) = default;
   OverlayBuffer& operator=(OverlayBuffer&& other) = default;
@@ -57,6 +59,10 @@ class OverlayBuffer {
   virtual const uint32_t* GetOffsets() const = 0;
 
   virtual GpuImage ImportImage(GpuDisplay egl_display) = 0;
+  virtual void DeleteImage() = 0;
+
+  virtual uint32_t GetImageTexture() = 0;
+  virtual void DeleteTexture() = 0;
 
   virtual bool CreateFrameBuffer(uint32_t gpu_fd) = 0;