1/*
2 * Acceleration for the Creator and Creator3D framebuffer - register caching.
3 *
4 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
5 * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 *
25 */
26
27#ifndef FFBRCACHE_H
28#define FFBRCACHE_H
29
30/* We only need to write the bits which actually change,
31 * writing unnessary bits causes the operation to go more
32 * slowly. -DaveM
33 *
34 * We used to have some hairy code here which tried to
35 * avoid writing attribute bits unnecessarily.  It has been
36 * removed because various two bit fields have different
37 * semantics.  For example, for some the higher bit is the
38 * edit bit, for others there are three state patterns
39 * and zero is a special "no edit" value.  Ho hum, it was
40 * a nice idea...
41 */
42#define FFB_WRITE_PPC(__fpriv, __ffb, __val, __chg_mask) \
43do {	unsigned int __oldval = (__fpriv)->ppc_cache; \
44	unsigned int __t; \
45	__t = (__oldval & (__chg_mask)) ^ (__val); \
46	if (__t) { \
47		unsigned int __newval = __oldval & ~(__chg_mask); \
48		__newval |= (__val); \
49		(__fpriv)->ppc_cache = __newval; \
50		FFBFifo((__fpriv), 1); \
51		(__ffb)->ppc = (__val); \
52	} \
53} while(0)
54
55#define FFB_WRITE_PMASK(__fpriv, __ffb, __val) \
56do {	if((__fpriv)->pmask_cache != (__val)) { \
57		(__fpriv)->pmask_cache = (__val); \
58		FFBFifo((__fpriv), 1); \
59		(__ffb)->pmask = (__val); \
60	} \
61} while(0)
62
63#define FFB_WRITE_ROP(__fpriv, __ffb, __val) \
64do {	if((__fpriv)->rop_cache != (__val)) { \
65		(__fpriv)->rop_cache = (__val); \
66		FFBFifo((__fpriv), 1); \
67		(__ffb)->rop = (__val); \
68	} \
69} while(0)
70
71#define FFB_WRITE_DRAWOP(__fpriv, __ffb, __val) \
72do {	if((__fpriv)->drawop_cache != (__val)) { \
73		(__fpriv)->drawop_cache = (__val); \
74		FFBFifo((__fpriv), 1); \
75		(__ffb)->drawop = (__val); \
76	} \
77} while(0)
78
79#define FFB_WRITE_FG(__fpriv, __ffb, __val) \
80do {	if((__fpriv)->fg_cache != (__val)) { \
81		(__fpriv)->fg_cache = (__val); \
82		FFBFifo((__fpriv), 1); \
83		(__ffb)->fg = (__val); \
84	} \
85} while(0)
86
87#define FFB_WRITE_BG(__fpriv, __ffb, __val) \
88do {	if((__fpriv)->bg_cache != (__val)) { \
89		(__fpriv)->bg_cache = (__val); \
90		FFBFifo((__fpriv), 1); \
91		(__ffb)->bg = (__val); \
92	} \
93} while(0)
94
95#define FFB_WRITE_FONTW(__fpriv, __ffb, __val) \
96do {	if((__fpriv)->fontw_cache != (__val)) { \
97		(__fpriv)->fontw_cache = (__val); \
98		FFBFifo((__fpriv), 1); \
99		(__ffb)->fontw = (__val); \
100	} \
101} while(0)
102
103#define FFB_WRITE_FONTINC(__fpriv, __ffb, __val) \
104do {	if((__fpriv)->fontinc_cache != (__val)) { \
105		(__fpriv)->fontinc_cache = (__val); \
106		FFBFifo((__fpriv), 1); \
107		(__ffb)->fontinc = (__val); \
108	} \
109} while(0)
110
111#define FFB_WRITE_FBC(__fpriv, __ffb, __val) \
112do {	if((__fpriv)->fbc_cache != (__val)) { \
113		(__fpriv)->fbc_cache = (__val); \
114		FFBFifo((__fpriv), 1); \
115		(__ffb)->fbc = (__val); \
116	} \
117} while(0)
118
119#define FFB_WRITE_WID(__fpriv, __ffb, __val) \
120do {	if((__fpriv)->wid_cache != (__val)) { \
121		(__fpriv)->wid_cache = (__val); \
122		FFBFifo((__fpriv), 1); \
123		(__ffb)->wid = (__val); \
124	} \
125} while(0)
126
127extern void __FFB_Attr_Raw(FFBPtr pFfb,
128			   unsigned int ppc,
129			   unsigned int ppc_mask,
130			   unsigned int pmask,
131			   unsigned int rop,
132			   int drawop, int fg,
133			   unsigned int fbc,
134			   unsigned int wid);
135
136#define FFB_ATTR_RAW(__fpriv, __ppc, __ppc_mask, __pmask, __rop, __drawop, __fg, __fbc, __wid) \
137	if((((__fpriv)->ppc_cache & (__ppc_mask)) != (__ppc))			|| \
138	   ((__fpriv)->pmask_cache != (__pmask))				|| \
139	   ((__fpriv)->rop_cache != (__rop))					|| \
140	   (((__drawop) != -1) && ((__fpriv)->drawop_cache != (__drawop)))	|| \
141	   ((__fpriv)->fg_cache != (__fg))					|| \
142	   ((__fpriv)->fbc_cache != (__fbc))					|| \
143	   ((__fpriv)->wid_cache != (__wid))) \
144		__FFB_Attr_Raw((__fpriv), (__ppc), (__ppc_mask), (__pmask), \
145			       (__rop), (__drawop), (__fg), (__fbc), (__wid))
146
147#define FFB_PPC_GCMASK	(FFB_PPC_APE_MASK | FFB_PPC_CS_MASK)
148
149#define FFB_PPC_WINMASK	(FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK)
150
151/* We have to be careful when copying windows around.  For that
152 * case we will use either VIS copies or hw accelerated VSCROLL.
153 * All of the planes needs to be copied in the framebuffer from
154 * src to dst in order to handle child windows using different WIDs
155 * than the parent window being copied.
156 */
157
158/* Setup to access the smart frame buffer (SFB) directly where the
159 * pixel color comes from the cpu on writes.
160 */
161#define FFB_PPC_WINCOPY		(FFB_PPC_APE_DISABLE | FFB_PPC_XS_VAR | FFB_PPC_CS_VAR)
162#define FFB_PPC_WINCOPY_MASK	(FFB_PPC_APE_MASK | FFB_PPC_XS_MASK | FFB_PPC_CS_MASK)
163#define FFB_FBC_WINCOPY		(FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_WE_FORCEON | \
164				 FFB_FBC_RB_A | FFB_FBC_SB_BOTH | FFB_FBC_XE_ON | \
165				 FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_ON)
166
167#define FFB_ATTR_SFB_VAR_WINCOPY(__fpriv) \
168do {	unsigned int __ppc = FFB_PPC_WINCOPY; \
169	unsigned int __ppc_mask = FFB_PPC_WINCOPY_MASK; \
170	unsigned int __rop = FFB_ROP_NEW|(FFB_ROP_NEW<<8); \
171	unsigned int __fbc = FFB_FBC_WINCOPY; \
172	if((__fpriv)->has_double_buffer) { \
173		__fbc &= ~FFB_FBC_WB_MASK; \
174		__fbc |= FFB_FBC_WB_AB; \
175	} \
176	if (((__fpriv)->ppc_cache & __ppc_mask) != __ppc || \
177	    (__fpriv)->fbc_cache != __fbc || \
178	    (__fpriv)->rop_cache != __rop || \
179	    (__fpriv)->pmask_cache != 0xffffffff) { \
180		ffb_fbcPtr __ffb = (__fpriv)->regs; \
181		(__fpriv)->ppc_cache &= ~__ppc_mask; \
182		(__fpriv)->ppc_cache |= __ppc; \
183		(__fpriv)->fbc_cache = __fbc; \
184		(__fpriv)->rop_cache = __rop; \
185		(__fpriv)->pmask_cache = 0xffffffff; \
186		(__fpriv)->rp_active = 1; \
187		FFBFifo(__fpriv, 4); \
188		(__ffb)->ppc = __ppc; \
189		(__ffb)->fbc = __fbc; \
190		(__ffb)->rop = __rop; \
191		(__ffb)->pmask = 0xffffffff; \
192		(__fpriv)->rp_active = 1; \
193	} \
194} while(0)
195
196extern void __FFB_Attr_SFB_VAR(FFBPtr pFfb, unsigned int ppc, unsigned int ppc_mask, unsigned int fbc,
197			       unsigned int wid, unsigned int rop, unsigned int pmask);
198
199#define FFB_ATTR_SFB_VAR_WIN(__fpriv, __pmask, __alu, __pwin) \
200do {	unsigned int __ppc = FFB_PPC_APE_DISABLE | FFB_PPC_CS_VAR | FFB_PPC_XS_WID; \
201	unsigned int __ppc_mask = FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK; \
202	unsigned int __rop = (FFB_ROP_EDIT_BIT | (__alu))|(FFB_ROP_NEW<<8); \
203	unsigned int __fbc = FFB_FBC_WIN(__pwin); \
204	if((__fpriv)->has_double_buffer) { \
205		__fbc &= ~FFB_FBC_WB_MASK; \
206		__fbc |= FFB_FBC_WB_AB; \
207	} \
208	if(((__fpriv)->ppc_cache & __ppc_mask) != __ppc || \
209	   (__fpriv)->fbc_cache != __fbc || \
210	   (__fpriv)->wid_cache != FFB_WID_WIN(__pwin) || \
211	   (__fpriv)->rop_cache != __rop || \
212	   (__fpriv)->pmask_cache != (__pmask)) \
213		__FFB_Attr_SFB_VAR(__fpriv, __ppc, __ppc_mask, __fbc, \
214				   FFB_WID_WIN(__pwin), __rop, (__pmask)); \
215} while(0)
216
217/* VSCROLL Attributes:
218 *
219 * PPC) VCE_DISABLE must be set, all other attributes are effectively
220 *      ignored since this drawop just copies pixels within the ram
221 *      chips and bypasses the pixel processor entirely.  So you
222 *	end up with a PPC color source behavior of {ZS,YS,XS,CS}_VAR.
223 * FBC) all options are allowed, but the SRC/DST buffers are determined
224 *      solely by the WB_* setting, that is, the RB_* setting is effectively
225 *      ignored since the pixels are copied directly through the write buffer
226 * ROP) must be FFB_ROP_OLD (even for the X plane!)
227 * PMASK) all options allowed
228 */
229#define FFB_ATTR_VSCROLL_WINCOPY(__fpriv) \
230do {	unsigned int __rop = (FFB_ROP_OLD | (FFB_ROP_OLD << 8)); \
231	unsigned int __fbc = FFB_FBC_WINCOPY; \
232	if((__fpriv)->has_double_buffer) { \
233		__fbc &= ~FFB_FBC_WB_MASK; \
234		__fbc |= FFB_FBC_WB_AB; \
235	} \
236	if((__fpriv)->fbc_cache != __fbc || \
237	   (__fpriv)->rop_cache != __rop || \
238	   (__fpriv)->pmask_cache != 0xffffffff || \
239	   (__fpriv)->drawop_cache != FFB_DRAWOP_VSCROLL) { \
240		ffb_fbcPtr __ffb = (__fpriv)->regs; \
241		(__fpriv)->fbc_cache = __fbc; \
242		(__fpriv)->rop_cache = __rop; \
243		(__fpriv)->pmask_cache = 0xffffffff; \
244		(__fpriv)->drawop_cache = FFB_DRAWOP_VSCROLL; \
245		(__fpriv)->rp_active = 1; \
246		FFBFifo(__fpriv, 4); \
247		(__ffb)->fbc = __fbc; \
248		(__ffb)->rop = __rop; \
249		(__ffb)->pmask = 0xffffffff; \
250		(__ffb)->drawop = FFB_DRAWOP_VSCROLL; \
251		(__fpriv)->rp_active = 1; \
252	} \
253} while(0)
254
255#define FFB_ATTR_VSCROLL_WIN(__fpriv, __pmask, __pwin) \
256do {	unsigned int __rop = (FFB_ROP_OLD | (FFB_ROP_OLD << 8)); \
257	unsigned int __fbc = FFB_FBC_WIN(__pwin); \
258	if((__fpriv)->has_double_buffer) { \
259		__fbc &= ~FFB_FBC_WB_MASK; \
260		__fbc |= FFB_FBC_WB_AB; \
261	} \
262	if((__fpriv)->fbc_cache != __fbc || \
263	   (__fpriv)->rop_cache != __rop || \
264	   (__fpriv)->pmask_cache != (__pmask) || \
265	   (__fpriv)->drawop_cache != FFB_DRAWOP_VSCROLL) { \
266		ffb_fbcPtr __ffb = (__fpriv)->regs; \
267		(__fpriv)->fbc_cache = __fbc; \
268		(__fpriv)->rop_cache = __rop; \
269		(__fpriv)->pmask_cache = (__pmask); \
270		(__fpriv)->drawop_cache = FFB_DRAWOP_VSCROLL; \
271		(__fpriv)->rp_active = 1; \
272		FFBFifo(__fpriv, 4); \
273		(__ffb)->fbc = __fbc; \
274		(__ffb)->rop = __rop; \
275		(__ffb)->pmask = (__pmask); \
276		(__ffb)->drawop = FFB_DRAWOP_VSCROLL; \
277	} \
278} while(0)
279
280#endif /* FFBRCACHE_H */
281