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