hwc2: set layer buffer
am: 6436e3ee3e

Change-Id: I667f1eb84e497b19a26548f14b9bf04953c16baf
diff --git a/hwc2/Android.mk b/hwc2/Android.mk
index 58ae91e..8697126 100644
--- a/hwc2/Android.mk
+++ b/hwc2/Android.mk
@@ -45,7 +45,8 @@
 	hwc2_config.cpp \
 	hwc2_callback.cpp \
 	hwc2_layer.cpp \
-	hwc2_buffer.cpp
+	hwc2_buffer.cpp \
+	hwc2_gralloc.cpp
 
 LOCAL_MODLE_TAGS := optional
 
diff --git a/hwc2/hwc2.cpp b/hwc2/hwc2.cpp
index 7c51a5a..9da3561 100644
--- a/hwc2/hwc2.cpp
+++ b/hwc2/hwc2.cpp
@@ -251,11 +251,11 @@
     return dev->set_cursor_position(display, layer, x, y);
 }
 
-hwc2_error_t set_layer_buffer(hwc2_device_t* /*device*/,
-        hwc2_display_t /*display*/, hwc2_layer_t /*layer*/,
-        buffer_handle_t /*buffer*/, int32_t /*acquire_fence*/)
+hwc2_error_t set_layer_buffer(hwc2_device_t *device, hwc2_display_t display,
+        hwc2_layer_t layer, buffer_handle_t buffer, int32_t acquire_fence)
 {
-    return HWC2_ERROR_NONE;
+    hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
+    return dev->set_layer_buffer(display, layer, buffer, acquire_fence);
 }
 
 hwc2_error_t set_layer_surface_damage(hwc2_device_t *device,
diff --git a/hwc2/hwc2.h b/hwc2/hwc2.h
index 91f7414..fc4ed06 100644
--- a/hwc2/hwc2.h
+++ b/hwc2/hwc2.h
@@ -27,11 +27,34 @@
 #include <adf/adf.h>
 #include <adfhwc/adfhwc.h>
 
+class hwc2_gralloc {
+public:
+    /* hwc2_gralloc follows the singleton design pattern */
+    static const hwc2_gralloc &get_instance();
+
+    bool is_valid(buffer_handle_t handle) const;
+
+private:
+    hwc2_gralloc();
+    ~hwc2_gralloc();
+
+    /* The address of the nvgr_is_valid symbol. This NVIDIA function checks if a
+     * buffer is valid */
+    bool (*nvgr_is_valid)(buffer_handle_t handle);
+
+    /* A symbol table handle to the NVIDIA gralloc .so file. */
+    void *nvgr;
+};
+
 class hwc2_buffer {
 public:
     hwc2_buffer();
+    ~hwc2_buffer();
+
+    void close_acquire_fence();
 
     /* Set properties */
+    hwc2_error_t set_buffer(buffer_handle_t handle, int32_t acquire_fence);
     hwc2_error_t set_dataspace(android_dataspace_t dataspace);
     hwc2_error_t set_display_frame(const hwc_rect_t &display_frame);
     hwc2_error_t set_source_crop(const hwc_frect_t &source_crop);
@@ -42,6 +65,14 @@
     hwc2_error_t set_transform(hwc_transform_t transform);
 
 private:
+    /* A handle to the buffer */
+    buffer_handle_t handle;
+
+    /* A sync fence object which will be signaled when it is safe to read
+     * from the buffer. If the acquire_fence is -1, it is already safe to
+     * read from the buffer */
+    int32_t acquire_fence;
+
     /* Provides more info on how to interpret the buffer contents such as
      * the encoding standard and color transformation */
     android_dataspace_t dataspace;
@@ -130,6 +161,7 @@
 
     /* Set properties */
     hwc2_error_t set_comp_type(hwc2_composition_t comp_type);
+    hwc2_error_t set_buffer(buffer_handle_t handle, int32_t acquire_fence);
     hwc2_error_t set_dataspace(android_dataspace_t dataspace);
     hwc2_error_t set_display_frame(const hwc_rect_t &display_frame);
     hwc2_error_t set_source_crop(const hwc_frect_t &source_crop);
@@ -194,6 +226,8 @@
 
     hwc2_error_t set_layer_composition_type(hwc2_layer_t lyr_id,
                     hwc2_composition_t comp_type);
+    hwc2_error_t set_layer_buffer(hwc2_layer_t lyr_id, buffer_handle_t handle,
+                    int32_t acquire_fence);
     hwc2_error_t set_layer_dataspace(hwc2_layer_t lyr_id,
                     android_dataspace_t dataspace);
     hwc2_error_t set_layer_display_frame(hwc2_layer_t lyr_id,
@@ -286,6 +320,8 @@
 
     hwc2_error_t set_layer_composition_type(hwc2_display_t dpy_id,
                     hwc2_layer_t lyr_id, hwc2_composition_t comp_type);
+    hwc2_error_t set_layer_buffer(hwc2_display_t dpy_id, hwc2_layer_t lyr_id,
+                    buffer_handle_t handle, int32_t acquire_fence);
     hwc2_error_t set_layer_dataspace(hwc2_display_t dpy_id, hwc2_layer_t lyr_id,
                     android_dataspace_t dataspace);
     hwc2_error_t set_layer_display_frame(hwc2_display_t dpy_id,
diff --git a/hwc2/hwc2_buffer.cpp b/hwc2/hwc2_buffer.cpp
index 632307d..7bd2361 100644
--- a/hwc2/hwc2_buffer.cpp
+++ b/hwc2/hwc2_buffer.cpp
@@ -19,7 +19,9 @@
 #include "hwc2.h"
 
 hwc2_buffer::hwc2_buffer()
-    : dataspace(),
+    : handle(),
+      acquire_fence(-1),
+      dataspace(),
       display_frame(),
       source_crop(),
       z_order(0),
@@ -28,6 +30,38 @@
       plane_alpha(1.0),
       transform() { }
 
+hwc2_buffer::~hwc2_buffer()
+{
+    close_acquire_fence();
+}
+
+void hwc2_buffer::close_acquire_fence()
+{
+    if (acquire_fence >= 0) {
+        close(acquire_fence);
+        acquire_fence = -1;
+    }
+}
+
+hwc2_error_t hwc2_buffer::set_buffer(buffer_handle_t handle,
+        int32_t acquire_fence)
+{
+    /* Only check if non-null buffers are valid. Layer buffers are determined to
+     * be non-null in hwc2_layer. Client target buffers can be null and should
+     * not produce an error. */
+    if (handle && !hwc2_gralloc::get_instance().is_valid(handle)) {
+        ALOGE("invalid buffer handle");
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    close_acquire_fence();
+
+    this->handle = handle;
+    this->acquire_fence = acquire_fence;
+
+    return HWC2_ERROR_NONE;
+}
+
 hwc2_error_t hwc2_buffer::set_dataspace(android_dataspace_t dataspace)
 {
     this->dataspace = dataspace;
diff --git a/hwc2/hwc2_dev.cpp b/hwc2/hwc2_dev.cpp
index 8bb2a8b..294272b 100644
--- a/hwc2/hwc2_dev.cpp
+++ b/hwc2/hwc2_dev.cpp
@@ -187,6 +187,13 @@
             comp_type);
 }
 
+hwc2_error_t hwc2_dev::set_layer_buffer(hwc2_display_t dpy_id,
+        hwc2_layer_t lyr_id, buffer_handle_t handle, int32_t acquire_fence)
+{
+    return displays.find(dpy_id)->second.set_layer_buffer(lyr_id, handle,
+            acquire_fence);
+}
+
 hwc2_error_t hwc2_dev::set_layer_dataspace(hwc2_display_t dpy_id,
         hwc2_layer_t lyr_id, android_dataspace_t dataspace)
 {
diff --git a/hwc2/hwc2_display.cpp b/hwc2/hwc2_display.cpp
index e8f1ed2..c84d36b 100644
--- a/hwc2/hwc2_display.cpp
+++ b/hwc2/hwc2_display.cpp
@@ -276,6 +276,18 @@
     return it->second.set_comp_type(comp_type);
 }
 
+hwc2_error_t hwc2_display::set_layer_buffer(hwc2_layer_t lyr_id,
+        buffer_handle_t handle, int32_t acquire_fence)
+{
+    auto it = layers.find(lyr_id);
+    if (it == layers.end()) {
+        ALOGE("dpy %" PRIu64 ": lyr %" PRIu64 ": bad layer handle", id, lyr_id);
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    return it->second.set_buffer(handle, acquire_fence);
+}
+
 hwc2_error_t hwc2_display::set_layer_dataspace(hwc2_layer_t lyr_id,
         android_dataspace_t dataspace)
 {
diff --git a/hwc2/hwc2_gralloc.cpp b/hwc2/hwc2_gralloc.cpp
new file mode 100644
index 0000000..9301b3d
--- /dev/null
+++ b/hwc2/hwc2_gralloc.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 <cutils/log.h>
+#include <dlfcn.h>
+
+#include "hwc2.h"
+
+hwc2_gralloc::hwc2_gralloc()
+{
+    nvgr = dlopen("gralloc.tegra132.so", RTLD_LOCAL | RTLD_LAZY);
+    LOG_ALWAYS_FATAL_IF(!nvgr, "failed to find module");
+
+    *(void **)(&nvgr_is_valid) = dlsym(nvgr, "nvgr_is_valid");
+    LOG_ALWAYS_FATAL_IF(!nvgr_is_valid, "failed to find nvgr_is_valid symbol");
+
+}
+
+hwc2_gralloc::~hwc2_gralloc()
+{
+    dlclose(nvgr);
+}
+
+const hwc2_gralloc &hwc2_gralloc::get_instance()
+{
+    static hwc2_gralloc instance;
+    return instance;
+}
+
+bool hwc2_gralloc::is_valid(buffer_handle_t handle) const
+{
+    return nvgr_is_valid(handle);
+}
diff --git a/hwc2/hwc2_layer.cpp b/hwc2/hwc2_layer.cpp
index a536709..65e9b84 100644
--- a/hwc2/hwc2_layer.cpp
+++ b/hwc2/hwc2_layer.cpp
@@ -51,6 +51,22 @@
     return ret;
 }
 
+hwc2_error_t hwc2_layer::set_buffer(buffer_handle_t handle, int32_t acquire_fence)
+{
+    if (comp_type == HWC2_COMPOSITION_SOLID_COLOR
+            || comp_type == HWC2_COMPOSITION_SIDEBAND
+            || comp_type == HWC2_COMPOSITION_CLIENT) {
+        return HWC2_ERROR_NONE;
+    }
+
+    if (!handle) {
+        ALOGE("lyr %" PRIu64 ": layer buffers cannot be null", id);
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return buffer.set_buffer(handle, acquire_fence);
+}
+
 hwc2_error_t hwc2_layer::set_dataspace(android_dataspace_t dataspace)
 {
     return buffer.set_dataspace(dataspace);