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 if (size & ~(1 << order)) 41 ++order; 42 return order; 43 } 44 45 46 RingQueue::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 70 RingQueue::~RingQueue() 71 { 72 TRACE("%s: Closing %s RingQueue.\n", __func__, queueName[fQueueType]); 73 free(fData); 74 } 75 76 77 status_t 78 RingQueue::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 92 size_t 93 RingQueue::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 121 size_t 122 RingQueue::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