diff options
author | David 'Digit' Turner <digit@google.com> | 2014-09-24 19:03:46 -0700 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2014-09-24 19:06:49 -0700 |
commit | dfd49832d5d2058a69486af32373fc90ddc69a3d (patch) | |
tree | 3c17f4252e1a0b04ae700410f8094b65add18749 /emulator/opengl/shared/OpenglCodecCommon | |
parent | 9746f34af612629b65507e57f667d05e729fa057 (diff) | |
download | sdk-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.h | 80 |
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 |