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 41 if (size & ~(1 << order)) 42 ++order; 43 44 return order; 45} 46 47 48RingQueue::RingQueue(size_t sizeBytes, uint32 queueType) 49 : 50 fQueueType(queueType), 51 fReadPtr(0), 52 fWritePtr(0) 53{ 54 TRACE("%s: Requested %d bytes for %s RingQueue.\n", __func__, sizeBytes, 55 queueName[fQueueType]); 56 57 size_t renderQueueSize = compute_order(sizeBytes / 8); 58 fSize = (1 << (renderQueueSize + 1)) * 4; 59 fWriteBytesAvail = fSize; 60 fAlignMask = 16 - 1; 61 62 TRACE("%s: Allocating %d bytes for %s RingQueue.\n", __func__, fSize, 63 queueName[fQueueType]); 64 65 // Allocate buffer memory 66 fData = (unsigned char*)malloc(fSize); 67 // Clear buffer 68 memset(fData, 0, fSize); 69} 70 71 72RingQueue::~RingQueue() 73{ 74 TRACE("%s: Closing %s RingQueue.\n", __func__, queueName[fQueueType]); 75 free(fData); 76} 77 78 79status_t 80RingQueue::Empty() 81{ 82 TRACE("%s: Clearing %s RingQueue\n", __func__, queueName[fQueueType]); 83 // Clear buffer 84 memset(fData, 0, fSize); 85 86 // Reset counters 87 fReadPtr = 0; 88 fWritePtr = 0; 89 fWriteBytesAvail = fSize; 90 return B_OK; 91} 92 93 94size_t 95RingQueue::Read(unsigned char* dataPtr, size_t bytes) 96{ 97 // If there is no data or nothing to read, return 0 bytes 98 if (dataPtr == 0 || bytes <= 0 || fWriteBytesAvail == fSize) 99 return 0; 100 101 size_t readBytesAvail = fSize - fWriteBytesAvail; 102 103 // Set a high threshold of total available bytes available. 104 if (bytes > readBytesAvail) 105 bytes = readBytesAvail; 106 107 // Keep track of position and pull needed data 108 if (bytes > fSize - fReadPtr) { 109 size_t len = fSize - fReadPtr; 110 memcpy(dataPtr, fData + fReadPtr, len); 111 memcpy(dataPtr + len, fData, bytes - len); 112 } else { 113 memcpy(dataPtr, fData + fReadPtr, bytes); 114 } 115 116 fReadPtr = (fReadPtr + bytes) % fSize; 117 fWriteBytesAvail += bytes; 118 119 return bytes; 120} 121 122 123size_t 124RingQueue::Write(unsigned char* dataPtr, size_t bytes) 125{ 126 // If there is no data, or no room available, 0 bytes written. 127 if (dataPtr == 0 || bytes <= 0 || fWriteBytesAvail == 0) 128 return 0; 129 130 // Set a high threshold of the number of bytes available. 131 if (bytes > fWriteBytesAvail) 132 bytes = fWriteBytesAvail; 133 134 // Keep track of position and push needed data 135 if (bytes > fSize - fWritePtr) { 136 size_t len = fSize - fWritePtr; 137 memcpy(fData + fWritePtr, dataPtr, len); 138 memcpy(fData, dataPtr + len, bytes - len); 139 } else 140 memcpy(fData + fWritePtr, dataPtr, bytes); 141 142 fWritePtr = (fWritePtr + bytes) % fSize; 143 fWriteBytesAvail -= bytes; 144 145 return bytes; 146} 147