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
compute_order(unsigned long size)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
RingQueue(size_t sizeBytes,uint32 queueType)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
~RingQueue()72 RingQueue::~RingQueue()
73 {
74 TRACE("%s: Closing %s RingQueue.\n", __func__, queueName[fQueueType]);
75 free(fData);
76 }
77
78
79 status_t
Empty()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
Read(unsigned char * dataPtr,size_t bytes)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
Write(unsigned char * dataPtr,size_t bytes)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