1/* 2 * Copyright 2012, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 */ 8 9 10#include "ringqueue.h" 11 12#include <stdlib.h> 13#include <string.h> 14 15 16#define TRACE_RENDER_QUEUE 17#ifdef TRACE_RENDER_QUEUE 18extern "C" void _sPrintf(const char* format, ...); 19# define TRACE(x...) _sPrintf("radeon_hd: " x) 20#else 21# define TRACE(x...) ; 22#endif 23 24#define ERROR(x...) _sPrintf("radeon_hd: " x) 25 26 27static const char* queueName[RADEON_QUEUE_MAX] = { 28 "GFX", 29 "CP1", 30 "CP2" 31}; 32 33 34int 35compute_order(unsigned long size) 36{ 37 int order; 38 unsigned long tmp; 39 for (order = 0, tmp = size; tmp >>= 1; ++order); 40 if (size & ~(1 << order)) 41 ++order; 42 return order; 43} 44 45 46RingQueue::RingQueue(size_t sizeBytes, uint32 queueType) 47 : 48 fQueueType(queueType), 49 fReadPtr(0), 50 fWritePtr(0) 51{ 52 TRACE("%s: Requested %d bytes for %s RingQueue.\n", __func__, sizeBytes, 53 queueName[fQueueType]); 54 55 size_t renderQueueSize = compute_order(sizeBytes / 8); 56 fSize = (1 << (renderQueueSize + 1)) * 4; 57 fWriteBytesAvail = fSize; 58 fAlignMask = 16 - 1; 59 60 TRACE("%s: Allocating %d bytes for %s RingQueue.\n", __func__, fSize, 61 queueName[fQueueType]); 62 63 // Allocate buffer memory 64 fData = (unsigned char*)malloc(fSize); 65 // Clear buffer 66 memset(fData, 0, fSize); 67} 68 69 70RingQueue::~RingQueue() 71{ 72 TRACE("%s: Closing %s RingQueue.\n", __func__, queueName[fQueueType]); 73 free(fData); 74} 75 76 77status_t 78RingQueue::Empty() 79{ 80 TRACE("%s: Clearing %s RingQueue\n", __func__, queueName[fQueueType]); 81 // Clear buffer 82 memset(fData, 0, fSize); 83 84 // Reset counters 85 fReadPtr = 0; 86 fWritePtr = 0; 87 fWriteBytesAvail = fSize; 88 return B_OK; 89} 90 91 92size_t 93RingQueue::Read(unsigned char* dataPtr, size_t bytes) 94{ 95 // If there is no data or nothing to read, return 0 bytes 96 if (dataPtr == 0 || bytes <= 0 || fWriteBytesAvail == fSize) 97 return 0; 98 99 size_t readBytesAvail = fSize - fWriteBytesAvail; 100 101 // Set a high threshold of total available bytes available. 102 if (bytes > readBytesAvail) 103 bytes = readBytesAvail; 104 105 // Keep track of position and pull needed data 106 if (bytes > fSize - fReadPtr) { 107 size_t len = fSize - fReadPtr; 108 memcpy(dataPtr, fData + fReadPtr, len); 109 memcpy(dataPtr + len, fData, bytes - len); 110 } else { 111 memcpy(dataPtr, fData + fReadPtr, bytes); 112 } 113 114 fReadPtr = (fReadPtr + bytes) % fSize; 115 fWriteBytesAvail += bytes; 116 117 return bytes; 118} 119 120 121size_t 122RingQueue::Write(unsigned char* dataPtr, size_t bytes) 123{ 124 // If there is no data, or no room available, 0 bytes written. 125 if (dataPtr == 0 || bytes <= 0 || fWriteBytesAvail == 0) 126 return 0; 127 128 // Set a high threshold of the number of bytes available. 129 if (bytes > fWriteBytesAvail) 130 bytes = fWriteBytesAvail; 131 132 // Keep track of position and push needed data 133 if (bytes > fSize - fWritePtr) { 134 size_t len = fSize - fWritePtr; 135 memcpy(fData + fWritePtr, dataPtr, len); 136 memcpy(fData, dataPtr + len, bytes - len); 137 } else 138 memcpy(fData + fWritePtr, dataPtr, bytes); 139 140 fWritePtr = (fWritePtr + bytes) % fSize; 141 fWriteBytesAvail -= bytes; 142 143 return bytes; 144} 145