1/*
2 * Copyright © 2011-2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Chris Wilson <chris@chris-wilson.co.uk>
25 *
26 */
27
28#ifndef GEN6_COMMON_H
29#define GEN6_COMMON_H
30
31#include "sna.h"
32
33#define NO_RING_SWITCH(sna) (!(sna)->kgem.has_semaphores)
34#define PREFER_RENDER 0 /* -1 -> BLT, 1 -> RENDER */
35
36static inline bool is_uncached(struct sna *sna,
37			       struct kgem_bo *bo)
38{
39	return bo->io || (bo->scanout && !sna->kgem.has_wt);
40}
41
42inline static bool can_switch_to_blt(struct sna *sna,
43				     struct kgem_bo *bo,
44				     unsigned flags)
45{
46	if (sna->kgem.ring != KGEM_RENDER)
47		return true;
48
49	if (bo && RQ_IS_BLT(bo->rq))
50		return true;
51
52	if (bo && bo->tiling == I915_TILING_Y)
53		return false;
54
55	if (bo && !kgem_bo_can_blt(&sna->kgem, bo))
56		return false;
57
58	if (sna->render_state.gt < 2)
59		return true;
60
61	if (bo && RQ_IS_RENDER(bo->rq))
62		return false;
63
64	if (NO_RING_SWITCH(sna))
65		return false;
66
67	if (flags & COPY_LAST)
68		return true;
69
70	return kgem_ring_is_idle(&sna->kgem, KGEM_BLT);
71}
72
73static inline bool untiled_tlb_miss(struct kgem_bo *bo)
74{
75	if (kgem_bo_is_render(bo))
76		return false;
77
78	return bo->tiling == I915_TILING_NONE && bo->pitch >= 4096;
79}
80
81static int prefer_blt_bo(struct sna *sna,
82			 struct kgem_bo *src,
83			 struct kgem_bo *dst)
84{
85	assert(dst != NULL);
86
87	if (PREFER_RENDER)
88		return PREFER_RENDER < 0;
89
90	if (dst->rq)
91		return RQ_IS_BLT(dst->rq);
92
93	if (sna->flags & SNA_POWERSAVE)
94		return true;
95
96	if (src) {
97		if (sna->render_state.gt > 1)
98			return false;
99
100		if (src->rq)
101			return RQ_IS_BLT(src->rq);
102
103		if (src->tiling == I915_TILING_Y)
104			return false;
105        } else {
106                if (sna->render_state.gt > 2)
107                        return false;
108        }
109
110	if (sna->render_state.gt < 2)
111		return true;
112
113	return dst->tiling == I915_TILING_NONE || is_uncached(sna, dst);
114}
115
116inline static bool force_blt_ring(struct sna *sna, struct kgem_bo *bo)
117{
118	if (sna->kgem.mode == KGEM_RENDER)
119		return false;
120
121	if (NO_RING_SWITCH(sna))
122		return sna->kgem.ring == KGEM_BLT;
123
124	if (bo->tiling == I915_TILING_Y)
125		return false;
126
127	if (sna->flags & SNA_POWERSAVE)
128		return true;
129
130	if (sna->render_state.gt < 2)
131		return true;
132
133	return false;
134}
135
136nonnull inline static bool
137prefer_blt_ring(struct sna *sna, struct kgem_bo *bo, unsigned flags)
138{
139	if (PREFER_RENDER)
140		return PREFER_RENDER < 0;
141
142	assert(!force_blt_ring(sna, bo));
143	assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna));
144
145	if (kgem_bo_is_blt(bo))
146		return true;
147
148	return can_switch_to_blt(sna, bo, flags);
149}
150
151nonnull inline static bool
152prefer_render_ring(struct sna *sna, struct kgem_bo *bo)
153{
154	if (sna->kgem.ring == KGEM_RENDER)
155		return true;
156
157	if (sna->kgem.ring != KGEM_NONE && NO_RING_SWITCH(sna))
158                return false;
159
160	if (kgem_bo_is_render(bo))
161		return true;
162
163	if (sna->flags & SNA_POWERSAVE)
164		return false;
165
166	if (!prefer_blt_bo(sna, NULL, bo))
167		return true;
168
169	return !kgem_ring_is_idle(&sna->kgem, KGEM_RENDER);
170}
171
172inline static bool
173prefer_blt_composite(struct sna *sna, struct sna_composite_op *tmp)
174{
175	if (PREFER_RENDER)
176		return PREFER_RENDER < 0;
177
178	if (untiled_tlb_miss(tmp->dst.bo) ||
179	    untiled_tlb_miss(tmp->src.bo))
180		return true;
181
182	if (force_blt_ring(sna, tmp->dst.bo))
183		return true;
184
185	if (prefer_render_ring(sna, tmp->dst.bo))
186		return false;
187
188	if (!prefer_blt_ring(sna, tmp->dst.bo, 0))
189		return false;
190
191	return prefer_blt_bo(sna, tmp->src.bo, tmp->dst.bo);
192}
193
194nonnull static inline bool
195prefer_blt_fill(struct sna *sna, struct kgem_bo *bo, unsigned flags)
196{
197	if (PREFER_RENDER)
198		return PREFER_RENDER < 0;
199
200	if (untiled_tlb_miss(bo))
201		return true;
202
203	if (force_blt_ring(sna, bo))
204		return true;
205
206	if ((flags & (FILL_POINTS | FILL_SPANS)) == 0) {
207		if (prefer_render_ring(sna, bo))
208			return false;
209
210		if (!prefer_blt_ring(sna, bo, 0))
211			return false;
212	} else {
213	    if (can_switch_to_blt(sna, bo, COPY_LAST))
214		    return true;
215	}
216
217	return prefer_blt_bo(sna, NULL, bo);
218}
219
220void gen6_render_context_switch(struct kgem *kgem, int new_mode);
221void gen6_render_retire(struct kgem *kgem);
222
223#endif /* GEN6_COMMON_H */
224