aboutsummaryrefslogtreecommitdiffstats
path: root/emulator/opengl/shared/OpenglCodecCommon
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2014-09-24 19:03:46 -0700
committerDavid 'Digit' Turner <digit@google.com>2014-09-24 19:06:49 -0700
commitdfd49832d5d2058a69486af32373fc90ddc69a3d (patch)
tree3c17f4252e1a0b04ae700410f8094b65add18749 /emulator/opengl/shared/OpenglCodecCommon
parent9746f34af612629b65507e57f667d05e729fa057 (diff)
downloadsdk-dfd49832d5d2058a69486af32373fc90ddc69a3d.zip
sdk-dfd49832d5d2058a69486af32373fc90ddc69a3d.tar.gz
sdk-dfd49832d5d2058a69486af32373fc90ddc69a3d.tar.bz2
emulator/opengl/emugen: Ensure correct buffer alignment.
The decoders generated by emugen pass addresses that come directly from the stream to EGL/GL functions. Sometimes, these addresses are not properly padded with regards to the type of data being transfered and this can crash some implementations (e.g. OSMesa being compiled with -msse by default, and doesn't build without it). This patch introduces two helper classes in ProtocolUtils.h, named InputBuffer and OutputBuffer, which are used to auto-align buffer pointers, then make the generated decoder code use them. Change-Id: I345c7eecc230f62310ced5378b6344f419647e06
Diffstat (limited to 'emulator/opengl/shared/OpenglCodecCommon')
-rw-r--r--emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h80
1 files changed, 80 insertions, 0 deletions
diff --git a/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h b/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
index 1198bd1..472d7ea 100644
--- a/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
+++ b/emulator/opengl/shared/OpenglCodecCommon/ProtocolUtils.h
@@ -3,6 +3,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
namespace emugl {
@@ -102,6 +104,84 @@ inline T Unpack(const void* ptr) {
return UnpackerT<T, S, is_pointer<T>::value>::unpack(ptr);
}
+// Helper class used to ensure input buffers passed to EGL/GL functions
+// are properly aligned (preventing crashes with some backends).
+// Usage example:
+//
+// InputBuffer inputBuffer(ptr, size);
+// glDoStuff(inputBuffer.get());
+//
+// inputBuffer.get() will return the original value of |ptr| if it was
+// aligned on an 8-byte boundary. Otherwise, it will return the address
+// of an aligned heap-allocated copy of the original |size| bytes starting
+// from |ptr|. The heap block is released at scope exit.
+class InputBuffer {
+public:
+ InputBuffer(const void* input, size_t size, size_t align = 8) :
+ mBuff(input), mIsCopy(false) {
+ if (((uintptr_t)input & (align - 1U)) != 0) {
+ void* newBuff = malloc(size);
+ memcpy(newBuff, input, size);
+ mBuff = newBuff;
+ mIsCopy = true;
+ }
+ }
+
+ ~InputBuffer() {
+ if (mIsCopy) {
+ free((void*)mBuff);
+ }
+ }
+
+ const void* get() const {
+ return mBuff;
+ }
+
+private:
+ const void* mBuff;
+ bool mIsCopy;
+};
+
+// Helper class used to ensure that output buffers passed to EGL/GL functions
+// are aligned on 8-byte addresses.
+// Usage example:
+//
+// ptr = stream->alloc(size);
+// OutputBuffer outputBuffer(ptr, size);
+// glGetStuff(outputBuffer.get());
+// outputBuffer.flush();
+//
+// outputBuffer.get() returns the original value of |ptr| if it was already
+// aligned on an 8=byte boundary. Otherwise, it returns the size of an heap
+// allocated zeroed buffer of |size| bytes.
+//
+// outputBuffer.flush() copies the content of the heap allocated buffer back
+// to |ptr| explictly, if needed. If a no-op if |ptr| was aligned.
+class OutputBuffer {
+public:
+ OutputBuffer(unsigned char* ptr, size_t size, size_t align = 8) :
+ mOrgBuff(ptr), mBuff(ptr), mSize(size) {
+ if (((uintptr_t)ptr & (align - 1U)) != 0) {
+ void* newBuff = calloc(1, size);
+ mBuff = newBuff;
+ }
+ }
+
+ void* get() const {
+ return mBuff;
+ }
+
+ void flush() {
+ if (mBuff != mOrgBuff) {
+ memcpy(mOrgBuff, mBuff, mSize);
+ }
+ }
+private:
+ unsigned char* mOrgBuff;
+ void* mBuff;
+ size_t mSize;
+};
+
} // namespace emugl
#endif // EMUGL_PROTOCOL_UTILS_H