[magma] Add connection and context
This change adds basic scaffolding for connection and context objects.
Bug: b/272307395
Test: m libgfxstream_backend
Change-Id: I8dd1aea47ab273ca2f592ef309519c4137c42a71
diff --git a/host/magma/Android.bp b/host/magma/Android.bp
index 26c92f8..1ce98fb 100644
--- a/host/magma/Android.bp
+++ b/host/magma/Android.bp
@@ -22,7 +22,9 @@
target: {
android: {
srcs: [
+ "Connection.cpp",
"DrmBuffer.cpp",
+ "DrmContext.cpp",
"DrmDevice.cpp",
"IntelDrmDecoder.cpp",
],
@@ -35,7 +37,9 @@
},
not_windows: {
srcs: [
+ "Connection.cpp",
"DrmBuffer.cpp",
+ "DrmContext.cpp",
"DrmDevice.cpp",
"IntelDrmDecoder.cpp",
],
diff --git a/host/magma/CMakeLists.txt b/host/magma/CMakeLists.txt
index c2c389a..32aece0 100644
--- a/host/magma/CMakeLists.txt
+++ b/host/magma/CMakeLists.txt
@@ -1,7 +1,9 @@
if (LINUX AND DEPENDENCY_RESOLUTION STREQUAL "DOWNLOAD")
set(
gfxstream-magma-server-backend-sources
+ Connection.cpp
DrmBuffer.cpp
+ DrmContext.cpp
DrmDevice.cpp
IntelDrmDecoder.cpp)
set(
diff --git a/host/magma/Connection.cpp b/host/magma/Connection.cpp
new file mode 100644
index 0000000..e6e3a37
--- /dev/null
+++ b/host/magma/Connection.cpp
@@ -0,0 +1,57 @@
+// Copyright (C) 2023 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 "host/magma/Connection.h"
+
+#include <i915_drm.h>
+#include <sys/mman.h>
+
+#include <cerrno>
+#include <cinttypes>
+
+#include "host-common/logging.h"
+#include "host/magma/DrmDevice.h"
+
+namespace gfxstream {
+namespace magma {
+
+Connection::Connection(DrmDevice& device) : mDevice(device) {}
+
+std::optional<uint32_t> Connection::createContext() {
+ auto context = DrmContext::create(*this);
+ if (!context) {
+ ERR("Failed to create context");
+ return std::nullopt;
+ }
+
+ auto id = context->getId();
+ auto [_, emplaced] = mContexts.emplace(id, std::move(*context));
+ if (!emplaced) {
+ ERR("GEM produced duplicate context ID %" PRIu32, id);
+ return std::nullopt;
+ }
+
+ return id;
+}
+
+DrmContext* Connection::getContext(uint32_t id) {
+ auto it = mContexts.find(id);
+ if (it == mContexts.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
+} // namespace magma
+} // namespace gfxstream
diff --git a/host/magma/Connection.h b/host/magma/Connection.h
new file mode 100644
index 0000000..429f16c
--- /dev/null
+++ b/host/magma/Connection.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License") override;
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <optional>
+#include <unordered_map>
+
+#include "DrmContext.h"
+
+namespace gfxstream {
+namespace magma {
+
+class DrmDevice;
+
+// A Connection represents an unique magma object ID namespace.
+// Magma objects from different connections may share the same ID.
+class Connection {
+ public:
+ Connection(DrmDevice& device);
+ ~Connection() = default;
+ DISALLOW_COPY_AND_ASSIGN(Connection);
+ Connection(Connection&&) noexcept = default;
+ Connection& operator=(Connection&&) = delete;
+
+ // Creates a new context and returns its ID. Returns nullopt on error.
+ std::optional<uint32_t> createContext();
+
+ // Returns the context for the given ID, or nullptr if invalid.
+ DrmContext* getContext(uint32_t id);
+
+ private:
+ friend class DrmContext;
+
+ DrmDevice& mDevice;
+
+ // Maps context IDs to contexts.
+ std::unordered_map<uint32_t, DrmContext> mContexts;
+};
+
+} // namespace magma
+} // namespace gfxstream
diff --git a/host/magma/DrmContext.cpp b/host/magma/DrmContext.cpp
new file mode 100644
index 0000000..47f648f
--- /dev/null
+++ b/host/magma/DrmContext.cpp
@@ -0,0 +1,67 @@
+// Copyright (C) 2023 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 "host/magma/DrmContext.h"
+
+#include <i915_drm.h>
+#include <sys/mman.h>
+
+#include <cerrno>
+#include <cinttypes>
+
+#include "host-common/logging.h"
+#include "host/magma/Connection.h"
+#include "host/magma/DrmDevice.h"
+
+namespace gfxstream {
+namespace magma {
+
+DrmContext::DrmContext(Connection& connection) : mConnection(connection) {}
+
+DrmContext::DrmContext(DrmContext&& other) noexcept
+ : mConnection(other.mConnection), mId(other.mId) {
+ other.mId = std::nullopt;
+}
+
+DrmContext::~DrmContext() {
+ if (!mId) {
+ return;
+ }
+ drm_i915_gem_context_destroy params{.ctx_id = mId.value()};
+ int result = mConnection.mDevice.ioctl(DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, ¶ms);
+ if (result) {
+ ERR("DRM_IOCTL_I915_GEM_CONTEXT_DESTROY(%d) failed: %d", mId.value(), errno);
+ }
+}
+
+std::unique_ptr<DrmContext> DrmContext::create(Connection& connection) {
+ // Create a new GEM context.
+ drm_i915_gem_context_create_ext params{};
+ int result = connection.mDevice.ioctl(DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, ¶ms);
+ if (result) {
+ ERR("DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT failed: %d", errno);
+ return nullptr;
+ }
+
+ auto context = std::unique_ptr<DrmContext>(new DrmContext(connection));
+ context->mId = params.ctx_id;
+
+ INFO("Created DrmContext id %" PRIu32, context->mId);
+ return context;
+}
+
+uint32_t DrmContext::getId() { return mId.value(); }
+
+} // namespace magma
+} // namespace gfxstream
diff --git a/host/magma/DrmContext.h b/host/magma/DrmContext.h
new file mode 100644
index 0000000..db3ef45
--- /dev/null
+++ b/host/magma/DrmContext.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License") override;
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <optional>
+
+#include "aemu/base/Compiler.h"
+
+namespace gfxstream {
+namespace magma {
+
+class Connection;
+
+class DrmContext {
+ public:
+ ~DrmContext();
+ DISALLOW_COPY_AND_ASSIGN(DrmContext);
+ DrmContext(DrmContext&&) noexcept;
+ DrmContext& operator=(DrmContext&&) = delete;
+
+ static std::unique_ptr<DrmContext> create(Connection& connection);
+ uint32_t getId();
+
+ private:
+ DrmContext(Connection& device);
+
+ Connection& mConnection;
+ std::optional<uint32_t> mId;
+};
+
+} // namespace magma
+} // namespace gfxstream
diff --git a/host/magma/DrmDevice.cpp b/host/magma/DrmDevice.cpp
index a898636..c9e5ee7 100644
--- a/host/magma/DrmDevice.cpp
+++ b/host/magma/DrmDevice.cpp
@@ -24,6 +24,7 @@
#include <string>
#include "host-common/logging.h"
+#include "magma/magma_common_defs.h"
namespace gfxstream {
namespace magma {
diff --git a/host/magma/DrmDevice.h b/host/magma/DrmDevice.h
index bce1dcb..3f74235 100644
--- a/host/magma/DrmDevice.h
+++ b/host/magma/DrmDevice.h
@@ -20,6 +20,7 @@
#include <memory>
#include "DrmBuffer.h"
+#include "DrmContext.h"
#include "MonotonicMap.h"
#include "aemu/base/Compiler.h"
#include "aemu/base/ManagedDescriptor.hpp"
diff --git a/host/magma/IntelDrmDecoder.cpp b/host/magma/IntelDrmDecoder.cpp
index 3bffcda..83839d1 100644
--- a/host/magma/IntelDrmDecoder.cpp
+++ b/host/magma/IntelDrmDecoder.cpp
@@ -25,6 +25,7 @@
#include <vector>
#include "RenderThreadInfoMagma.h"
+#include "host/magma/Connection.h"
#include "host/magma/DrmDevice.h"
#include "magma/magma_common_defs.h"
@@ -320,12 +321,19 @@
magma_status_t IntelDrmDecoder::magma_device_create_connection(magma_device_t device,
magma_connection_t* connection_out) {
*connection_out = MAGMA_INVALID_OBJECT_ID;
- WARN("%s not implemented", __FUNCTION__);
- return MAGMA_STATUS_UNIMPLEMENTED;
+ auto dev = mDevices.get(device);
+ if (!dev) {
+ return MAGMA_STATUS_INVALID_ARGS;
+ }
+ *connection_out = mConnections.create(*dev);
+ return MAGMA_STATUS_OK;
}
void IntelDrmDecoder::magma_connection_release(magma_connection_t connection) {
- WARN("%s not implemented", __FUNCTION__);
+ bool erased = mConnections.erase(connection);
+ if (!erased) {
+ WARN("invalid connection %" PRIu64, connection);
+ }
}
magma_status_t IntelDrmDecoder::magma_connection_create_buffer(magma_connection_t connection,
@@ -404,8 +412,17 @@
magma_status_t IntelDrmDecoder::magma_connection_create_context(magma_connection_t connection,
uint32_t* context_id_out) {
*context_id_out = MAGMA_INVALID_OBJECT_ID;
- WARN("%s not implemented", __FUNCTION__);
- return MAGMA_STATUS_UNIMPLEMENTED;
+ auto con = mConnections.get(connection);
+ if (!con) {
+ return MAGMA_STATUS_INVALID_ARGS;
+ }
+ auto ctx = con->createContext();
+ if (!ctx) {
+ WARN("error creating context");
+ return MAGMA_STATUS_INTERNAL_ERROR;
+ }
+ *context_id_out = ctx.value();
+ return MAGMA_STATUS_OK;
}
void IntelDrmDecoder::magma_connection_release_context(magma_connection_t connection,
diff --git a/host/magma/IntelDrmDecoder.h b/host/magma/IntelDrmDecoder.h
index f4f5a32..d6f9316 100644
--- a/host/magma/IntelDrmDecoder.h
+++ b/host/magma/IntelDrmDecoder.h
@@ -17,6 +17,7 @@
#include "Decoder.h"
#include "MonotonicMap.h"
#include "DrmDevice.h"
+#include "Connection.h"
namespace gfxstream {
namespace magma {
@@ -52,6 +53,7 @@
uint32_t mContextId;
MonotonicMap<magma_device_t, DrmDevice> mDevices;
MonotonicMap<magma_buffer_t, DrmBuffer> mBuffers;
+ MonotonicMap<magma_connection_t, Connection> mConnections;
// Maps GEM handles to Buffers.
std::unordered_map<uint32_t, magma_buffer_t> mGemHandleToBuffer;