aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h')
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h107
1 files changed, 107 insertions, 0 deletions
diff --git a/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h b/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
new file mode 100644
index 0000000..1198bd1
--- /dev/null
+++ b/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
@@ -0,0 +1,107 @@
+#ifndef EMUGL_PROTOCOL_UTILS_H
+#define EMUGL_PROTOCOL_UTILS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace emugl {
+
+// Helper macro
+#define COMPILE_ASSERT(cond) static char kAssert##__LINE__[1 - 2 * !(cond)] __attribute__((unused)) = { 0 }
+
+// Helper template: is_pointer.
+// is_pointer<T>::value is true iff |T| is a pointer type.
+template <typename T> struct is_pointer {
+ static const bool value = false;
+};
+
+template <typename T> struct is_pointer<T*> {
+ static const bool value = true;
+};
+
+// A helper template to extract values form the wire protocol stream
+// and convert them to appropriate host values.
+//
+// The wire protocol uses 32-bit exclusively when transferring
+// GLintptr or GLsizei values, as well as opaque handles like GLeglImage,
+// from the guest (even when the guest is 64-bit).
+//
+// The corresponding host definitions depend on the host bitness. For
+// example, GLintptr is 64-bit on linux-x86_64. The following is a set
+// of templates that can simplify the conversion of protocol values
+// into host ones.
+//
+// The most important one is:
+//
+// unpack<HOST_TYPE,SIZE_TYPE>(const void* ptr)
+//
+// Which reads bytes from |ptr|, using |SIZE_TYPE| as the underlying
+// sized-integer specifier (e.g. 'uint32_t'), and converting the result
+// into a |HOST_TYPE| value. For example:
+//
+// unpack<EGLImage,uint32_t>(ptr + 12);
+//
+// will read a 4-byte value from |ptr + 12| and convert it into
+// an EGLImage, which is a host void*. The template detects host
+// pointer types to perform proper type casting.
+//
+// TODO(digit): Add custom unpackers to handle generic opaque void* values.
+// and map them to unique 32-bit values.
+
+template <typename T, typename S, bool IS_POINTER>
+struct UnpackerT {};
+
+template <typename T, typename S>
+struct UnpackerT<T,S,false> {
+ static inline T unpack(const void* ptr) {
+ COMPILE_ASSERT(sizeof(T) == sizeof(S));
+ return (T)(*(S*)(ptr));
+ }
+};
+
+template <typename T, typename S>
+struct UnpackerT<T,S,true> {
+ static inline T unpack(const void* ptr) {
+ return (T)(uintptr_t)(*(S*)(ptr));
+ }
+};
+
+template <>
+struct UnpackerT<float,uint32_t,false> {
+ static inline float unpack(const void* ptr) {
+ union {
+ float f;
+ uint32_t u;
+ } v;
+ v.u = *(uint32_t*)(ptr);
+ return v.f;
+ }
+};
+
+template <>
+struct UnpackerT<double,uint64_t,false> {
+ static inline double unpack(const void* ptr) {
+ union {
+ double d;
+ uint32_t u;
+ } v;
+ v.u = *(uint64_t*)(ptr);
+ return v.d;
+ }
+};
+
+template <>
+struct UnpackerT<ssize_t,uint32_t,false> {
+ static inline ssize_t unpack(const void* ptr) {
+ return (ssize_t)*(int32_t*)(ptr);
+ }
+};
+
+template <typename T, typename S>
+inline T Unpack(const void* ptr) {
+ return UnpackerT<T, S, is_pointer<T>::value>::unpack(ptr);
+}
+
+} // namespace emugl
+
+#endif // EMUGL_PROTOCOL_UTILS_H