From 138f82612179c09850de52a50151eae29b0a5edb Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 10 Apr 2012 13:52:25 -0500 Subject: [PATCH] radeon_hd: Add simple ring buffer * Does radeon specific buffer alignment. * Still very early (and not used yet). --- src/add-ons/accelerants/radeon_hd/Jamfile | 1 + .../accelerants/radeon_hd/renderqueue.cpp | 134 ++++++++++++++++++ .../accelerants/radeon_hd/renderqueue.h | 33 +++++ 3 files changed, 168 insertions(+) create mode 100644 src/add-ons/accelerants/radeon_hd/renderqueue.cpp create mode 100644 src/add-ons/accelerants/radeon_hd/renderqueue.h diff --git a/src/add-ons/accelerants/radeon_hd/Jamfile b/src/add-ons/accelerants/radeon_hd/Jamfile index 39d08ebd3e..d0683c45ce 100644 --- a/src/add-ons/accelerants/radeon_hd/Jamfile +++ b/src/add-ons/accelerants/radeon_hd/Jamfile @@ -23,5 +23,6 @@ Addon radeon_hd.accelerant : hooks.cpp mode.cpp pll.cpp + renderqueue.cpp : be libaccelerantscommon.a ; diff --git a/src/add-ons/accelerants/radeon_hd/renderqueue.cpp b/src/add-ons/accelerants/radeon_hd/renderqueue.cpp new file mode 100644 index 0000000000..bd1944c07d --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/renderqueue.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com + */ + + +#include "renderqueue.h" + +#include +#include + + +#define TRACE_RENDER_QUEUE +#ifdef TRACE_RENDER_QUEUE +extern "C" void _sPrintf(const char* format, ...); +# define TRACE(x...) _sPrintf("radeon_hd: " x) +#else +# define TRACE(x...) ; +#endif + +#define ERROR(x...) _sPrintf("radeon_hd: " x) + + +static int +compute_order(unsigned long size) +{ + int order; + unsigned long tmp; + for (order = 0, tmp = size; tmp >>= 1; ++order); + if (size & ~(1 << order)) + ++order; + return order; +} + + +RenderQueue::RenderQueue(size_t sizeBytes) + : + _readPtr(0), + _writePtr(0) +{ + TRACE("%s: Requested %d bytes for RenderQueue.\n", __func__, sizeBytes); + + size_t renderQueueSize = compute_order(sizeBytes / 8); + _size = (1 << (renderQueueSize + 1)) * 4; + _writeBytesAvail = _size; + _alignMask = 16 - 1; + + TRACE("%s: Allocating %d bytes for RenderQueue.\n", __func__, _size); + + // Allocate buffer memory + _data = (unsigned char*)malloc(_size); + // Clear buffer + memset(_data, 0, _size); +} + + +RenderQueue::~RenderQueue() +{ + TRACE("%s: Closing RenderQueue.\n", __func__); + free(_data); +} + + +status_t +RenderQueue::Empty() +{ + TRACE("%s: Clearing RenderQueue\n", __func__); + // Clear buffer + memset(_data, 0, _size); + + // Reset counters + _readPtr = 0; + _writePtr = 0; + _writeBytesAvail = _size; + return B_OK; +} + + +size_t +RenderQueue::Read(unsigned char* dataPtr, size_t bytes) +{ + // If there is no data or nothing to read, return 0 bytes + if (dataPtr == 0 || bytes <= 0 || _writeBytesAvail == _size) + return 0; + + size_t readBytesAvail = _size - _writeBytesAvail; + + // Set a high threshold of total available bytes available. + if (bytes > readBytesAvail) + bytes = readBytesAvail; + + // Keep track of position and pull needed data + if (bytes > _size - _readPtr) { + size_t len = _size - _readPtr; + memcpy(dataPtr, _data + _readPtr, len); + memcpy(dataPtr + len, _data, bytes - len); + } else { + memcpy(dataPtr, _data + _readPtr, bytes); + } + + _readPtr = (_readPtr + bytes) % _size; + _writeBytesAvail += bytes; + + return bytes; +} + + +size_t +RenderQueue::Write(unsigned char* dataPtr, size_t bytes) +{ + // If there is no data, or no room available, 0 bytes written. + if (dataPtr == 0 || bytes <= 0 || _writeBytesAvail == 0) + return 0; + + // Set a high threshold of the number of bytes available. + if (bytes > _writeBytesAvail) + bytes = _writeBytesAvail; + + // Keep track of position and push needed data + if (bytes > _size - _writePtr) { + size_t len = _size - _writePtr; + memcpy(_data + _writePtr, dataPtr, len); + memcpy(_data, dataPtr + len, bytes - len); + } else + memcpy(_data + _writePtr, dataPtr, bytes); + + _writePtr = (_writePtr + bytes) % _size; + _writeBytesAvail -= bytes; + + return bytes; +} diff --git a/src/add-ons/accelerants/radeon_hd/renderqueue.h b/src/add-ons/accelerants/radeon_hd/renderqueue.h new file mode 100644 index 0000000000..33324de60c --- /dev/null +++ b/src/add-ons/accelerants/radeon_hd/renderqueue.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck, kallisti5@unixzen.com + */ + + +#include "Accelerant.h" + + +// A basic ring buffer for passing render data into card. +class RenderQueue { +public: + RenderQueue(size_t bytes); + ~RenderQueue(); + size_t Read(unsigned char* data, size_t bytes); + size_t Write(unsigned char* data, size_t bytes); + status_t Empty(); + + size_t GetSize() {return _size;}; + size_t GetWriteAvail() {return _writeBytesAvail;} + size_t GetReadAvail() {return _size - _writeBytesAvail;} +private: + unsigned char* _data; + size_t _size; + size_t _writeBytesAvail; + int _readPtr; + int _writePtr; + + uint32 _alignMask; +};