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