drm_hwcomposer: Wrap the importers in a class
This will allow us to move the importer functionality into the
drmcompositor.
Change-Id: I4274ebd1776c4d7879342c54a2b7c4095ebc50f4
Signed-off-by: Sean Paul <seanpaul@chromium.org>
diff --git a/Android.mk b/Android.mk
index 81e7e48..30dfb5f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,6 +26,7 @@
libutils \
LOCAL_C_INCLUDES := \
+ external/drm_gralloc \
external/libdrm \
external/libdrm/include/drm \
system/core/include/utils \
@@ -38,19 +39,18 @@
drmconnector.cpp \
drmcrtc.cpp \
drmencoder.cpp \
+ drmgenericimporter.cpp \
drmmode.cpp \
drmplane.cpp \
drmproperty.cpp \
hwcomposer.cpp \
+ nvimporter.cpp \
worker.cpp
-ifeq ($(strip $(BOARD_DRM_HWCOMPOSER_BUFFER_IMPORTER)),drm-gralloc)
-LOCAL_C_INCLUDES += external/drm_gralloc
-LOCAL_SRC_FILES += hwcomposer_import_drm_gralloc.cpp
-endif
ifeq ($(strip $(BOARD_DRM_HWCOMPOSER_BUFFER_IMPORTER)),nvidia-gralloc)
-LOCAL_C_INCLUDES += external/drm_gralloc
-LOCAL_SRC_FILES += hwcomposer_import_nv_gralloc.cpp
+LOCAL_CPPFLAGS += -DUSE_NVIDIA_IMPORTER
+else
+LOCAL_CPPFLAGS += -DUSE_DRM_GENERIC_IMPORTER
endif
LOCAL_MODULE := hwcomposer.drm
diff --git a/drmgenericimporter.cpp b/drmgenericimporter.cpp
new file mode 100644
index 0000000..8c90f5f
--- /dev/null
+++ b/drmgenericimporter.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "hwc-drm-generic-importer"
+
+#include "importer.h"
+#include "drmresources.h"
+#include "drmgenericimporter.h"
+
+#include <drm/drm_fourcc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cutils/log.h>
+#include <gralloc_drm.h>
+#include <gralloc_drm_priv.h>
+#include <gralloc_drm_handle.h>
+#include <hardware/gralloc.h>
+
+namespace android {
+
+#ifdef USE_DRM_GENERIC_IMPORTER
+// static
+Importer *Importer::CreateInstance(DrmResources *drm) {
+ DrmGenericImporter *importer = new DrmGenericImporter(drm);
+ if (!importer)
+ return NULL;
+
+ int ret = importer->Init();
+ if (ret) {
+ ALOGE("Failed to initialize the nv importer %d", ret);
+ delete importer;
+ return NULL;
+ }
+ return importer;
+}
+#endif
+
+DrmGenericImporter::DrmGenericImporter(DrmResources *drm) : drm_(drm) {
+}
+
+DrmGenericImporter::~DrmGenericImporter() {
+}
+
+int DrmGenericImporter::Init() {
+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&gralloc_);
+ if (ret) {
+ ALOGE("Failed to open gralloc module");
+ return ret;
+ }
+ return 0;
+}
+
+uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) {
+ switch (hal_format) {
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return DRM_FORMAT_BGR888;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return DRM_FORMAT_ARGB8888;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return DRM_FORMAT_XBGR8888;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return DRM_FORMAT_ABGR8888;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return DRM_FORMAT_BGR565;
+ case HAL_PIXEL_FORMAT_YV12:
+ return DRM_FORMAT_YVU420;
+ default:
+ ALOGE("Cannot convert hal format to drm format %u", hal_format);
+ return -EINVAL;
+ }
+}
+
+int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+ gralloc_drm_handle_t *gr_handle = gralloc_drm_handle(handle);
+ if (!gr_handle)
+ return -EINVAL;
+
+ struct gralloc_drm_bo_t *gralloc_bo = gr_handle->data;
+ if (!gralloc_bo) {
+ ALOGE("Could not get drm bo from handle");
+ return -EINVAL;
+ }
+
+ uint32_t gem_handle;
+ int ret = drmPrimeFDToHandle(drm_->fd(), gr_handle->prime_fd, &gem_handle);
+ if (ret) {
+ ALOGE("failed to import prime fd %d ret=%d", gr_handle->prime_fd, ret);
+ return ret;
+ }
+
+ memset(bo, 0, sizeof(hwc_drm_bo_t));
+ bo->width = gr_handle->width;
+ bo->height = gr_handle->height;
+ bo->format = ConvertHalFormatToDrm(gr_handle->format);
+ bo->pitches[0] = gr_handle->stride;
+ bo->gem_handles[0] = gem_handle;
+ bo->offsets[0] = 0;
+
+ ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
+ bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
+ if (ret) {
+ ALOGE("could not create drm fb %d", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
+ if (bo->fb_id)
+ if (drmModeRmFB(drm_->fd(), bo->fb_id))
+ ALOGE("Failed to rm fb");
+
+ struct drm_gem_close gem_close;
+ memset(&gem_close, 0, sizeof(gem_close));
+ int num_gem_handles = sizeof(bo->gem_handles) / sizeof(bo->gem_handles[0]);
+ for (int i = 0; i < num_gem_handles; i++) {
+ if (!bo->gem_handles[i])
+ continue;
+
+ gem_close.handle = bo->gem_handles[i];
+ int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret)
+ ALOGE("Failed to close gem handle %d %d", i, ret);
+ else
+ bo->gem_handles[i] = 0;
+ }
+ return 0;
+}
+}
diff --git a/drmgenericimporter.h b/drmgenericimporter.h
new file mode 100644
index 0000000..d509ed8
--- /dev/null
+++ b/drmgenericimporter.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_DRM_GENERIC_IMPORTER_H_
+#define ANDROID_DRM_GENERIC_IMPORTER_H_
+
+#include "drmresources.h"
+#include "importer.h"
+
+#include <hardware/gralloc.h>
+
+namespace android {
+
+class DrmGenericImporter : public Importer {
+ public:
+ DrmGenericImporter(DrmResources *drm);
+ virtual ~DrmGenericImporter();
+
+ int Init();
+
+ virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo);
+ virtual int ReleaseBuffer(hwc_drm_bo_t *bo);
+
+ private:
+ uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
+
+ DrmResources *drm_;
+
+ const gralloc_module_t *gralloc_;
+};
+}
+
+#endif
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index c9452b6..06c0931 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -18,6 +18,7 @@
#include "drm_hwcomposer.h"
#include "drmresources.h"
+#include "importer.h"
#include <errno.h>
#include <fcntl.h>
@@ -75,14 +76,21 @@
typedef std::map<int, hwc_drm_display_t> DisplayMap;
typedef DisplayMap::iterator DisplayMapIter;
+ hwc_context_t() : procs(NULL), importer(NULL) {
+ }
+
+ ~hwc_context_t() {
+ delete importer;
+ }
+
hwc_composer_device_1_t device;
hwc_procs_t const *procs;
- struct hwc_import_context *import_ctx;
struct hwc_worker event_worker;
DisplayMap displays;
DrmResources drm;
+ Importer *importer;
};
static int hwc_prepare_layer(hwc_layer_1_t *layer) {
@@ -318,8 +326,7 @@
return ret;
}
- if (hwc_import_bo_release(hd->ctx->drm.fd(), hd->ctx->import_ctx,
- &hd->front)) {
+ if (!hd->ctx->importer->ReleaseBuffer(buf)) {
struct drm_gem_close args;
memset(&args, 0, sizeof(args));
for (int i = 0; i < ARRAY_SIZE(hd->front.gem_handles); ++i) {
@@ -469,9 +476,7 @@
}
struct hwc_drm_bo buf;
- memset(&buf, 0, sizeof(buf));
- ret =
- hwc_import_bo_create(ctx->drm.fd(), ctx->import_ctx, layer->handle, &buf);
+ ret = ctx->importer->ImportBuffer(layer->handle, &buf);
if (ret) {
ALOGE("Failed to import handle to drm bo %d", ret);
hwc_close_fences(display_contents);
@@ -754,12 +759,7 @@
if (hwc_destroy_worker(&ctx->event_worker))
ALOGE("Destroy event worker failed");
- int ret = hwc_import_destroy(ctx->import_ctx);
- if (ret)
- ALOGE("Could not destroy import %d", ret);
-
delete ctx;
-
return 0;
}
@@ -912,9 +912,9 @@
return ret;
}
- ret = hwc_import_init(&ctx->import_ctx);
- if (ret) {
- ALOGE("Failed to initialize import context");
+ ctx->importer = Importer::CreateInstance(&ctx->drm);
+ if (!ctx->importer) {
+ ALOGE("Failed to create importer instance");
delete ctx;
return ret;
}
diff --git a/hwcomposer_import_drm_gralloc.cpp b/hwcomposer_import_drm_gralloc.cpp
deleted file mode 100644
index 5958f57..0000000
--- a/hwcomposer_import_drm_gralloc.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2015 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 <stdlib.h>
-
-#include <cutils/log.h>
-
-#include <drm/drm_fourcc.h>
-
-#include <gralloc_drm.h>
-#include <gralloc_drm_priv.h>
-#include <gralloc_drm_handle.h>
-
-#include "drm_hwcomposer.h"
-
-struct hwc_import_context {
- struct drm_module_t *gralloc_module;
-};
-
-int hwc_import_init(struct hwc_import_context **ctx) {
- struct hwc_import_context *import_ctx;
-
- import_ctx = (struct hwc_import_context *)calloc(1, sizeof(*import_ctx));
- if (!ctx) {
- ALOGE("Failed to allocate gralloc import context");
- return -ENOMEM;
- }
-
- int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
- (const hw_module_t **)&import_ctx->gralloc_module);
- if (ret) {
- ALOGE("Failed to open gralloc module");
- free(import_ctx);
- return ret;
- }
-
- *ctx = import_ctx;
-
- return 0;
-}
-
-int hwc_import_destroy(struct hwc_import_context *ctx) {
- free(ctx);
- return 0;
-}
-
-static uint32_t hwc_convert_hal_format_to_drm_format(uint32_t hal_format) {
- switch (hal_format) {
- case HAL_PIXEL_FORMAT_RGB_888:
- return DRM_FORMAT_BGR888;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return DRM_FORMAT_ARGB8888;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return DRM_FORMAT_XBGR8888;
- case HAL_PIXEL_FORMAT_RGBA_8888:
- return DRM_FORMAT_ABGR8888;
- case HAL_PIXEL_FORMAT_RGB_565:
- return DRM_FORMAT_BGR565;
- case HAL_PIXEL_FORMAT_YV12:
- return DRM_FORMAT_YVU420;
- default:
- ALOGE("Cannot convert hal format to drm format %u", hal_format);
- return -EINVAL;
- }
-}
-
-int hwc_import_bo_create(int fd, hwc_import_context *ctx,
- buffer_handle_t handle, struct hwc_drm_bo *bo) {
- gralloc_drm_handle_t *gr_handle = gralloc_drm_handle(handle);
- if (!gr_handle)
- return -EINVAL;
-
- struct gralloc_drm_bo_t *gralloc_bo = gr_handle->data;
- if (!gralloc_bo) {
- ALOGE("Could not get drm bo from handle");
- return -EINVAL;
- }
-
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(fd, gr_handle->prime_fd, &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", gr_handle->prime_fd, ret);
- return ret;
- }
-
- bo->width = gr_handle->width;
- bo->height = gr_handle->height;
- bo->format = hwc_convert_hal_format_to_drm_format(gr_handle->format);
- bo->pitches[0] = gr_handle->stride;
- bo->gem_handles[0] = gem_handle;
- bo->offsets[0] = 0;
-
- ret = drmModeAddFB2(fd, bo->width, bo->height, bo->format, bo->gem_handles,
- bo->pitches, bo->offsets, &bo->fb_id, 0);
- if (ret) {
- ALOGE("could not create drm fb %d", ret);
- return ret;
- }
-
- return ret;
-}
-
-bool hwc_import_bo_release(int fd, hwc_import_context */* ctx */,
- struct hwc_drm_bo *bo) {
- if (bo->fb_id)
- if (drmModeRmFB(fd, bo->fb_id))
- ALOGE("Failed to rm fb");
-
- /* hwc may close the gem handles now. */
- return true;
-}
diff --git a/hwcomposer_import_nv_gralloc.cpp b/hwcomposer_import_nv_gralloc.cpp
deleted file mode 100644
index ef6bdb2..0000000
--- a/hwcomposer_import_nv_gralloc.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * Copyright (C) 2015 NVIDIA 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 <cutils/log.h>
-#include <hardware/gralloc.h>
-
-#include <stdlib.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-#include "drm_hwcomposer.h"
-
-#define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
-
-struct hwc_import_context {
- const gralloc_module_t *gralloc_module;
-};
-
-int hwc_import_init(struct hwc_import_context **ctx) {
- struct hwc_import_context *import_ctx = (struct hwc_import_context *)calloc(1, sizeof(*import_ctx));
- if (!ctx) {
- ALOGE("Failed to allocate gralloc import context");
- return -ENOMEM;
- }
-
- int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
- (const hw_module_t **)&import_ctx->gralloc_module);
- if (ret) {
- ALOGE("Failed to open gralloc module");
- free(import_ctx);
- return ret;
- }
-
- if (!strcasecmp(import_ctx->gralloc_module->common.author, "NVIDIA"))
- ALOGW("Using non-NVIDIA gralloc module: %s\n",
- import_ctx->gralloc_module->common.name);
-
- *ctx = import_ctx;
-
- return 0;
-}
-
-int hwc_import_destroy(struct hwc_import_context *ctx) {
- free(ctx);
- return 0;
-}
-
-struct importer_priv {
- int drm_fd;
- struct hwc_drm_bo bo;
-};
-
-static void free_priv(void *p) {
- struct importer_priv *priv = (struct importer_priv *)p;
- if (priv->bo.fb_id) {
- int ret = drmModeRmFB(priv->drm_fd, priv->bo.fb_id);
- if (ret)
- ALOGE("Failed to rm fb %d", ret);
- }
-
- struct drm_gem_close gem_close;
- memset(&gem_close, 0, sizeof(gem_close));
- for (int i = 0; i < ARRAY_SIZE(priv->bo.gem_handles); i++) {
- if (!priv->bo.gem_handles[i])
- continue;
- gem_close.handle = priv->bo.gem_handles[i];
- int ret = drmIoctl(priv->drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
- if (ret)
- ALOGE("Failed to close gem handle %d", ret);
- }
-
- free(priv);
-}
-
-static int hwc_import_set_priv(hwc_import_context *ctx, buffer_handle_t handle,
- struct importer_priv *priv) {
- const gralloc_module_t *g = ctx->gralloc_module;
- return g->perform(g, GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle,
- free_priv, priv);
-}
-
-static struct importer_priv *hwc_import_get_priv(hwc_import_context *ctx,
- buffer_handle_t handle) {
- const gralloc_module_t *g = ctx->gralloc_module;
- void *priv = NULL;
- int ret = g->perform(g, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE, handle,
- free_priv, &priv);
- return ret ? NULL : (struct importer_priv *)priv;
-}
-
-int hwc_import_bo_create(int fd, hwc_import_context *ctx,
- buffer_handle_t handle, struct hwc_drm_bo *bo) {
- /* Get imported bo that is cached in gralloc buffer, or create a new one. */
- struct importer_priv *priv = hwc_import_get_priv(ctx, handle);
- if (priv) {
- *bo = priv->bo;
- return 0;
- }
-
- priv = (struct importer_priv *)calloc(1, sizeof(*priv));
- if (!priv)
- return -ENOMEM;
- priv->drm_fd = fd;
-
- const gralloc_module_t *g = ctx->gralloc_module;
- int ret =
- g->perform(g, GRALLOC_MODULE_PERFORM_DRM_IMPORT, fd, handle, &priv->bo);
- if (ret) {
- ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
- free_priv(priv);
- return ret;
- }
-
- ret = drmModeAddFB2(fd, priv->bo.width, priv->bo.height, priv->bo.format,
- priv->bo.gem_handles, priv->bo.pitches,
- priv->bo.offsets, &priv->bo.fb_id, 0);
- if (ret) {
- ALOGE("Failed to add fb %d", ret);
- free_priv(priv);
- return ret;
- }
-
- ret = hwc_import_set_priv(ctx, handle, priv);
- if (ret) {
- /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
- * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
- * only one of which should be used by drm_hwcomposer). */
- ALOGE("Failed to register free callback for imported buffer %d", ret);
- free_priv(priv);
- return ret;
- }
- *bo = priv->bo;
- return ret;
-}
-
-bool hwc_import_bo_release(int fd, hwc_import_context *ctx,
- struct hwc_drm_bo *bo) {
- /* hwc may not close the gem handles, we own them */
- return false;
-}
diff --git a/importer.h b/importer.h
new file mode 100644
index 0000000..8bd40da
--- /dev/null
+++ b/importer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_DRM_IMPORTER_H_
+#define ANDROID_DRM_IMPORTER_H_
+
+#include "drm_hwcomposer.h"
+
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+namespace android {
+
+class DrmResources;
+
+class Importer {
+ public:
+ virtual ~Importer() {
+ }
+
+ // Creates a platform-specific importer instance
+ static Importer *CreateInstance(DrmResources *drm);
+
+ // Imports the buffer referred to by handle into bo.
+ //
+ // Note: This can be called from a different thread than ReleaseBuffer. The
+ // implementation is responsible for ensuring thread safety.
+ virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0;
+
+ // Releases the buffer object (ie: does the inverse of ImportBuffer)
+ //
+ // Note: This can be called from a different thread than ImportBuffer. The
+ // implementation is responsible for ensuring thread safety.
+ virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0;
+};
+}
+
+#endif
diff --git a/nvimporter.cpp b/nvimporter.cpp
new file mode 100644
index 0000000..d673438
--- /dev/null
+++ b/nvimporter.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "hwc-nv-importer"
+
+#include "drmresources.h"
+#include "importer.h"
+#include "nvimporter.h"
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cutils/log.h>
+#include <hardware/gralloc.h>
+
+namespace android {
+
+#ifdef USE_NVIDIA_IMPORTER
+// static
+Importer *Importer::CreateInstance(DrmResources *drm) {
+ NvImporter *importer = new NvImporter(drm);
+ if (!importer)
+ return NULL;
+
+ int ret = importer->Init();
+ if (ret) {
+ ALOGE("Failed to initialize the nv importer %d", ret);
+ delete importer;
+ return NULL;
+ }
+ return importer;
+}
+#endif
+
+NvImporter::NvImporter(DrmResources *drm) : drm_(drm) {
+}
+
+NvImporter::~NvImporter() {
+}
+
+int NvImporter::Init() {
+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&gralloc_);
+ if (ret) {
+ ALOGE("Failed to open gralloc module %d", ret);
+ return ret;
+ }
+
+ if (strcasecmp(gralloc_->common.author, "NVIDIA"))
+ ALOGW("Using non-NVIDIA gralloc module: %s/%s\n", gralloc_->common.name,
+ gralloc_->common.author);
+
+ return 0;
+}
+
+int NvImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+ memset(bo, 0, sizeof(hwc_drm_bo_t));
+ NvBuffer_t *buf = GrallocGetNvBuffer(handle);
+ if (buf) {
+ *bo = buf->bo;
+ return 0;
+ }
+
+ buf = new NvBuffer_t();
+ if (!buf) {
+ ALOGE("Failed to allocate new NvBuffer_t");
+ return -ENOMEM;
+ }
+ buf->importer = this;
+
+ int ret = gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_DRM_IMPORT,
+ drm_->fd(), handle, &buf->bo);
+ if (ret) {
+ ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret);
+ delete buf;
+ return ret;
+ }
+
+ ret = drmModeAddFB2(drm_->fd(), buf->bo.width, buf->bo.height, buf->bo.format,
+ buf->bo.gem_handles, buf->bo.pitches, buf->bo.offsets,
+ &buf->bo.fb_id, 0);
+ if (ret) {
+ ALOGE("Failed to add fb %d", ret);
+ ReleaseBufferImpl(&buf->bo);
+ delete buf;
+ return ret;
+ }
+
+ ret = GrallocSetNvBuffer(handle, buf);
+ if (ret) {
+ /* This will happen is persist.tegra.gpu_mapping_cache is 0/off,
+ * or if NV gralloc runs out of "priv slots" (currently 3 per buffer,
+ * only one of which should be used by drm_hwcomposer). */
+ ALOGE("Failed to register free callback for imported buffer %d", ret);
+ ReleaseBufferImpl(&buf->bo);
+ delete buf;
+ return ret;
+ }
+ *bo = buf->bo;
+ return 0;
+}
+
+int NvImporter::ReleaseBuffer(hwc_drm_bo_t * /* bo */) {
+ /* Stub this out since we don't want hwc releasing buffers */
+ return 0;
+}
+
+// static
+void NvImporter::ReleaseBufferCallback(void *nv_buffer) {
+ NvBuffer_t *buf = (NvBuffer_t *)nv_buffer;
+ buf->importer->ReleaseBufferImpl(&buf->bo);
+ delete buf;
+}
+
+void NvImporter::ReleaseBufferImpl(hwc_drm_bo_t *bo) {
+ if (bo->fb_id) {
+ int ret = drmModeRmFB(drm_->fd(), bo->fb_id);
+ if (ret)
+ ALOGE("Failed to rm fb %d", ret);
+ }
+
+ struct drm_gem_close gem_close;
+ memset(&gem_close, 0, sizeof(gem_close));
+ int num_gem_handles = sizeof(bo->gem_handles) / sizeof(bo->gem_handles[0]);
+ for (int i = 0; i < num_gem_handles; i++) {
+ if (!bo->gem_handles[i])
+ continue;
+
+ gem_close.handle = bo->gem_handles[i];
+ int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret)
+ ALOGE("Failed to close gem handle %d %d", i, ret);
+ else
+ bo->gem_handles[i] = 0;
+ }
+}
+
+NvImporter::NvBuffer_t *NvImporter::GrallocGetNvBuffer(buffer_handle_t handle) {
+ void *priv = NULL;
+ int ret =
+ gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE,
+ handle, ReleaseBufferCallback, &priv);
+ return ret ? NULL : (NvBuffer_t *)priv;
+}
+
+int NvImporter::GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf) {
+ return gralloc_->perform(gralloc_,
+ GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle,
+ ReleaseBufferCallback, buf);
+}
+}
diff --git a/nvimporter.h b/nvimporter.h
new file mode 100644
index 0000000..e3bdd1c
--- /dev/null
+++ b/nvimporter.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_NV_IMPORTER_H_
+#define ANDROID_NV_IMPORTER_H_
+
+#include "drmresources.h"
+#include "importer.h"
+
+#include <hardware/gralloc.h>
+
+namespace android {
+
+class NvImporter : public Importer {
+ public:
+ NvImporter(DrmResources *drm);
+ virtual ~NvImporter();
+
+ int Init();
+
+ virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo);
+ virtual int ReleaseBuffer(hwc_drm_bo_t *bo);
+
+ private:
+ typedef struct NvBuffer {
+ NvImporter *importer;
+ hwc_drm_bo_t bo;
+ } NvBuffer_t;
+
+ static void ReleaseBufferCallback(void *nv_buffer);
+ void ReleaseBufferImpl(hwc_drm_bo_t *bo);
+
+ NvBuffer_t *GrallocGetNvBuffer(buffer_handle_t handle);
+ int GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf);
+
+ DrmResources *drm_;
+
+ const gralloc_module_t *gralloc_;
+};
+}
+
+#endif