summaryrefslogtreecommitdiff
path: root/Source/DirectFB/gfxdrivers/unichrome/uc_fifo.h
blob: e7a3d8f807e591e9d7048665f4e1d791ae8046f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*
   Copyright (c) 2003 Andreas Robinson, All rights reserved.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
*/

#ifndef __UC_FIFO_H__
#define __UC_FIFO_H__

// Note to self: remove when added to makefile as -DUC_DEBUG.
#define UC_DEBUG 1

#include <dfb_types.h>

#include "regs2d.h"
#include "regs3d.h"
#include "mmio.h"

/**
 * uc_fifo - GPU data queue.
 *
 * buf:         buffer start (userspace address)
 * head:        pointer to first unused entry.
 *
 * size:        maximum number of entries in the fifo.
 * prep:        number of entries allocated to be used.
 * used:        number of entries currently in use.
 *
 * hwregs:      GPU register base address
 * reg_tset:    address to GPU TRANSET register
 * reg_tspace:  address to GPU TRANSPACE register
 *
 * flush:       function pointer to flush function (DMA or CPU)
 * flush_sys:   function pointer to flush_sys (non-DMA) function
 */

struct uc_fifo
{
    u32* buf;
    u32* head;

    unsigned int size;
    unsigned int prep;
    unsigned int used;

    //void (*flush)(struct uc_fifo* fifo, volatile void *hwregs);
    //void (*flush_sys)(struct uc_fifo* fifo, volatile void *hwregs);
};

// Help macros ---------------------------------------------------------------

// For the record: Macros suck maintenance- and debugging-wise,
// but provide guaranteed inlining of the code.

/**
 * Send the contents of the FIFO buffer to the hardware, and clear
 * the buffer. The transfer may be performed by the CPU or by DMA.
 */

//#define UC_FIFO_FLUSH(fifo) (fifo)->flush(fifo,ucdrv->hwregs)

/**
 * Same as UC_FIFO_FLUSH(), but always uses the CPU to transfer data.
 */

//#define UC_FIFO_FLUSH_SYS(fifo) (fifo)->flush_sys(fifo,ucdrv->hwregs)

#define UC_FIFO_FLUSH(fifo)     uc_fifo_flush_sys(fifo,ucdrv->hwregs)
#define UC_FIFO_FLUSH_SYS(fifo) uc_fifo_flush_sys(fifo,ucdrv->hwregs)

/**
 * Make sure there is room for dwsize double words in the FIFO.
 * If necessary, the FIFO is flushed first.
 *
 * @param fifo      the fifo
 * @param dwsize    number of double words to allocate
 *
 * @note It is ok to request more space than you will actually
 * be using. This is useful when you don't know exactly beforehand
 * how many entries you need.
 *
 * @note equivalent DRI code is in via_ioctl.c::viaCheckDma()
 */

#ifdef UC_DEBUG

#define UC_FIFO_PREPARE(fifo, dwsize)                            \
    do {                                                         \
        if ((fifo)->used + dwsize + 32 > (fifo)->size) {         \
            D_DEBUG("Unichrome: FIFO full - flushing it.");      \
            UC_FIFO_FLUSH(fifo);                                 \
        }                                                        \
        if (dwsize + (fifo)->prep + 32 > (fifo)->size) {         \
            D_BUG("Unichrome: FIFO too small for allocation.");  \
        }                                                        \
        (fifo)->prep += dwsize;                                  \
    } while(0)

#else

#define UC_FIFO_PREPARE(fifo, dwsize)                       \
    do {                                                    \
        if ((fifo)->used + dwsize + 32 > (fifo)->size) {    \
            UC_FIFO_FLUSH(fifo);                            \
        }                                                   \
        (fifo)->prep += dwsize;                             \
    } while(0)

#endif // UC_FIFO_DEBUG

/**
 * Add a 32-bit data word to the FIFO.
 * Takes one entry in the FIFO.
 */

#define UC_FIFO_ADD(fifo, data)     \
    do {                            \
        *((fifo)->head) = (data);   \
        (fifo)->head++;             \
        (fifo)->used++;             \
    } while(0)

/**
 * Add a command header. (HC_HEADER2 + parameter selection)
 * Takes two entries in the fifo.
 */

#define UC_FIFO_ADD_HDR(fifo, param)    \
    do {                                \
        UC_FIFO_ADD(fifo, HC_HEADER2);  \
        UC_FIFO_ADD(fifo, param);       \
    } while(0);

/**
 * Add a floating point value to the FIFO.
 * Non-floats (e.g integers) are converted first.
 * Takes one entry in the FIFO.
 */

#define UC_FIFO_ADD_FLOAT(fifo, val)        \
    do {                                    \
        union {float f; u32 i;} v;          \
        v.f = (float) (val);                \
        UC_FIFO_ADD(fifo, v.i);             \
    } while(0)

/**
 * Add a vertex on the form (x, y, color) to the FIFO.
 * Takes three entries in the FIFO.
 * The color format is 0xAARRGGBB.
 */

#define UC_FIFO_ADD_XYC(fifo, x, y, color)  \
    do {                                    \
        UC_FIFO_ADD_FLOAT(fifo, x);         \
        UC_FIFO_ADD_FLOAT(fifo, y);         \
        UC_FIFO_ADD(fifo, color);           \
    } while(0)

/**
 * Add a vertex on the form (x, y, w, color, s, t) to the FIFO.
 * Takes six entries in the FIFO.
 * The color format is 0xAARRGGBB.
 */

#define UC_FIFO_ADD_XYWCST(fifo, x, y, w, color, s, t)  \
    do {                                                \
        UC_FIFO_ADD_FLOAT(fifo, x);                     \
        UC_FIFO_ADD_FLOAT(fifo, y);                     \
        UC_FIFO_ADD_FLOAT(fifo, w);                     \
        UC_FIFO_ADD(fifo, color);                       \
        UC_FIFO_ADD_FLOAT(fifo, s);                     \
        UC_FIFO_ADD_FLOAT(fifo, t);                     \
    } while(0)

#define UC_FIFO_ADD_XYZWCST(fifo, x, y, z, w, color, s, t)  \
    do {                                                \
        UC_FIFO_ADD_FLOAT(fifo, x);                     \
        UC_FIFO_ADD_FLOAT(fifo, y);                     \
        UC_FIFO_ADD_FLOAT(fifo, z);                     \
        UC_FIFO_ADD_FLOAT(fifo, w);                     \
        UC_FIFO_ADD(fifo, color);                       \
        UC_FIFO_ADD_FLOAT(fifo, s);                     \
        UC_FIFO_ADD_FLOAT(fifo, t);                     \
    } while(0)

#define UC_FIFO_ADD_XYCST(fifo, x, y, color, s, t)      \
    do {                                                \
        UC_FIFO_ADD_FLOAT(fifo, x);                     \
        UC_FIFO_ADD_FLOAT(fifo, y);                     \
        UC_FIFO_ADD(fifo, color);                       \
        UC_FIFO_ADD_FLOAT(fifo, s);                     \
        UC_FIFO_ADD_FLOAT(fifo, t);                     \
    } while(0)


/**
 * Add data specifically for the 2D controller, to the fifo.
 * Takes two entries in the FIFO.
 *
 * @param reg   2D register index
 * @param data  32-bit data to add
 */

#define UC_FIFO_ADD_2D(fifo, reg, data)                     \
    do {                                                    \
        UC_FIFO_ADD(fifo, ((reg) >> 2) | HALCYON_HEADER1);  \
        UC_FIFO_ADD(fifo, (data));                          \
    } while (0)

/**
 * Add data specifically for a 3D controller register, to the fifo.
 * Takes one entry in the FIFO.
 *
 * @param reg   3D register index (8 bit)
 * @param data  24-bit data to add (make sure bits 24 - 31 are cleared!)
 */

#define UC_FIFO_ADD_3D(fifo, reg, data) \
    UC_FIFO_ADD(fifo, ((reg) << 24) | (data))

/**
 * Pad the FIFO to an even number of entries.
 * Takes zero or one entries in the FIFO.
 */
#define UC_FIFO_PAD_EVEN(fifo)  \
        if (fifo->used & 1) UC_FIFO_ADD(fifo, HC_DUMMY)

/**
 * Check for buffer overruns.
 * Can be redefined to nothing in release builds.
 */

#ifdef UC_DEBUG

#define UC_FIFO_CHECK(fifo)                              \
    do {                                                 \
        if ((fifo)->used > ((fifo)->size) - 32) {        \
            D_BUG("Unichrome: FIFO overrun.");           \
        }                                                \
        if ((fifo)->used > (fifo)->prep) {               \
            D_BUG("Unichrome: FIFO allocation error.");  \
        }                                                \
    } while(0)

#else

#define UC_FIFO_CHECK(fifo) do { } while(0)

#endif // UC_DEBUG


// FIFO functions ------------------------------------------------------------

/** Create a FIFO. Returns NULL on failure. */

struct uc_fifo* uc_fifo_create( FusionSHMPoolShared *pool, size_t size);

/** Destroy a FIFO */

void uc_fifo_destroy(FusionSHMPoolShared *pool, struct uc_fifo* fifo);

void uc_fifo_flush_sys(struct uc_fifo* fifo, volatile void *regs);

#endif // __UC_FIFO_H__