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 18 extern "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 27 static const char* queueName[RADEON_QUEUE_MAX] = { 28 "GFX", 29 "CP1", 30 "CP2" 31 }; 32 33 34 int 35 compute_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 48 RingQueue::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 72 RingQueue::~RingQueue() 73 { 74 TRACE("%s: Closing %s RingQueue.\n", __func__, queueName[fQueueType]); 75 free(fData); 76 } 77 78 79 status_t 80 RingQueue::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 94 size_t 95 RingQueue::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 123 size_t 124 RingQueue::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