1/*
2 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
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 *    Rob Clark <robclark@freedesktop.org>
25 */
26
27#ifndef FREEDRENO_SCREEN_H_
28#define FREEDRENO_SCREEN_H_
29
30#include "common/freedreno_dev_info.h"
31#include "drm/freedreno_drmif.h"
32#include "drm/freedreno_ringbuffer.h"
33#include "perfcntrs/freedreno_perfcntr.h"
34
35#include "pipe/p_screen.h"
36#include "renderonly/renderonly.h"
37#include "util/debug.h"
38#include "util/simple_mtx.h"
39#include "util/slab.h"
40#include "util/u_idalloc.h"
41#include "util/u_memory.h"
42#include "util/u_queue.h"
43
44#include "freedreno_batch_cache.h"
45#include "freedreno_gmem.h"
46#include "freedreno_util.h"
47
48struct fd_bo;
49
50/* Potential reasons for needing to skip bypass path and use GMEM, the
51 * generation backend can override this with screen->gmem_reason_mask
52 */
53enum fd_gmem_reason {
54   FD_GMEM_CLEARS_DEPTH_STENCIL = BIT(0),
55   FD_GMEM_DEPTH_ENABLED = BIT(1),
56   FD_GMEM_STENCIL_ENABLED = BIT(2),
57   FD_GMEM_BLEND_ENABLED = BIT(3),
58   FD_GMEM_LOGICOP_ENABLED = BIT(4),
59   FD_GMEM_FB_READ = BIT(5),
60};
61
62struct fd_screen {
63   struct pipe_screen base;
64
65   struct list_head context_list;
66
67   simple_mtx_t lock;
68
69   /* it would be tempting to use pipe_reference here, but that
70    * really doesn't work well if it isn't the first member of
71    * the struct, so not quite so awesome to be adding refcnting
72    * further down the inheritance hierarchy:
73    */
74   int refcnt;
75
76   /* place for winsys to stash it's own stuff: */
77   void *winsys_priv;
78
79   struct slab_parent_pool transfer_pool;
80
81   uint64_t gmem_base;
82   uint32_t gmemsize_bytes;
83
84   const struct fd_dev_id *dev_id;
85   uint8_t gen;      /* GPU (major) generation */
86   uint32_t gpu_id;  /* 220, 305, etc */
87   uint64_t chip_id; /* coreid:8 majorrev:8 minorrev:8 patch:8 */
88   uint32_t max_freq;
89   uint32_t ram_size;
90   uint32_t max_rts; /* max # of render targets */
91   uint32_t priority_mask;
92   bool has_timestamp;
93   bool has_robustness;
94   bool has_syncobj;
95
96   const struct fd_dev_info *info;
97   uint32_t ccu_offset_gmem;
98   uint32_t ccu_offset_bypass;
99
100   /* Bitmask of gmem_reasons that do not force GMEM path over bypass
101    * for current generation.
102    */
103   enum fd_gmem_reason gmem_reason_mask;
104
105   unsigned num_perfcntr_groups;
106   const struct fd_perfcntr_group *perfcntr_groups;
107
108   /* generated at startup from the perfcntr groups: */
109   unsigned num_perfcntr_queries;
110   struct pipe_driver_query_info *perfcntr_queries;
111
112   void *compiler;                  /* currently unused for a2xx */
113   struct util_queue compile_queue; /* currently unused for a2xx */
114
115   struct fd_device *dev;
116
117   /* NOTE: we still need a pipe associated with the screen in a few
118    * places, like screen->get_timestamp().  For anything context
119    * related, use ctx->pipe instead.
120    */
121   struct fd_pipe *pipe;
122
123   uint32_t (*setup_slices)(struct fd_resource *rsc);
124   unsigned (*tile_mode)(const struct pipe_resource *prsc);
125   int (*layout_resource_for_modifier)(struct fd_resource *rsc,
126                                       uint64_t modifier);
127
128   /* indirect-branch emit: */
129   void (*emit_ib)(struct fd_ringbuffer *ring, struct fd_ringbuffer *target);
130
131   /* simple gpu "memcpy": */
132   void (*mem_to_mem)(struct fd_ringbuffer *ring, struct pipe_resource *dst,
133                      unsigned dst_off, struct pipe_resource *src,
134                      unsigned src_off, unsigned sizedwords);
135
136   int64_t cpu_gpu_time_delta;
137
138   struct fd_batch_cache batch_cache;
139   struct fd_gmem_cache gmem_cache;
140
141   bool reorder;
142
143   uint16_t rsc_seqno;
144   uint16_t ctx_seqno;
145   struct util_idalloc_mt buffer_ids;
146
147   unsigned num_supported_modifiers;
148   const uint64_t *supported_modifiers;
149
150   struct renderonly *ro;
151
152   /* the blob seems to always use 8K factor and 128K param sizes, copy them */
153#define FD6_TESS_FACTOR_SIZE (8 * 1024)
154#define FD6_TESS_PARAM_SIZE (128 * 1024)
155#define FD6_TESS_BO_SIZE (FD6_TESS_FACTOR_SIZE + FD6_TESS_PARAM_SIZE)
156   struct fd_bo *tess_bo;
157
158   /* table with PIPE_PRIM_MAX+1 entries mapping PIPE_PRIM_x to
159    * DI_PT_x value to use for draw initiator.  There are some
160    * slight differences between generation.
161    *
162    * Note that primtypes[PRIM_TYPE_MAX] is used to map to the
163    * internal RECTLIST primtype, if available, used for blits/
164    * clears.
165    */
166   const enum pc_di_primtype *primtypes;
167   uint32_t primtypes_mask;
168};
169
170static inline struct fd_screen *
171fd_screen(struct pipe_screen *pscreen)
172{
173   return (struct fd_screen *)pscreen;
174}
175
176static inline void
177fd_screen_lock(struct fd_screen *screen)
178{
179   simple_mtx_lock(&screen->lock);
180}
181
182static inline void
183fd_screen_unlock(struct fd_screen *screen)
184{
185   simple_mtx_unlock(&screen->lock);
186}
187
188static inline void
189fd_screen_assert_locked(struct fd_screen *screen)
190{
191   simple_mtx_assert_locked(&screen->lock);
192}
193
194bool fd_screen_bo_get_handle(struct pipe_screen *pscreen, struct fd_bo *bo,
195                             struct renderonly_scanout *scanout,
196                             unsigned stride, struct winsys_handle *whandle);
197struct fd_bo *fd_screen_bo_from_handle(struct pipe_screen *pscreen,
198                                       struct winsys_handle *whandle);
199
200struct pipe_screen *fd_screen_create(struct fd_device *dev,
201                                     struct renderonly *ro,
202                                     const struct pipe_screen_config *config);
203
204static inline boolean
205is_a20x(struct fd_screen *screen)
206{
207   return (screen->gpu_id >= 200) && (screen->gpu_id < 210);
208}
209
210static inline boolean
211is_a2xx(struct fd_screen *screen)
212{
213   return screen->gen == 2;
214}
215
216/* is a3xx patch revision 0? */
217/* TODO a306.0 probably doesn't need this.. be more clever?? */
218static inline boolean
219is_a3xx_p0(struct fd_screen *screen)
220{
221   return (screen->chip_id & 0xff0000ff) == 0x03000000;
222}
223
224static inline boolean
225is_a3xx(struct fd_screen *screen)
226{
227   return screen->gen == 3;
228}
229
230static inline boolean
231is_a4xx(struct fd_screen *screen)
232{
233   return screen->gen == 4;
234}
235
236static inline boolean
237is_a5xx(struct fd_screen *screen)
238{
239   return screen->gen == 5;
240}
241
242static inline boolean
243is_a6xx(struct fd_screen *screen)
244{
245   return screen->gen == 6;
246}
247
248/* is it using the ir3 compiler (shader isa introduced with a3xx)? */
249static inline boolean
250is_ir3(struct fd_screen *screen)
251{
252   return is_a3xx(screen) || is_a4xx(screen) || is_a5xx(screen) ||
253          is_a6xx(screen);
254}
255
256static inline bool
257has_compute(struct fd_screen *screen)
258{
259   return is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen);
260}
261
262#endif /* FREEDRENO_SCREEN_H_ */
263