xref: /haiku/src/add-ons/accelerants/radeon_hd/ringqueue.cpp (revision 2897df967633aab846ff4917b53e2af7d1e54eeb)
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