1848b8605Smrg/*
2848b8605Smrg * Copyright © 2014 Broadcom
3848b8605Smrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
10848b8605Smrg * Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice (including the next
13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
14848b8605Smrg * Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22848b8605Smrg * IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25b8e80941Smrg#include "util/os_misc.h"
26848b8605Smrg#include "pipe/p_defines.h"
27848b8605Smrg#include "pipe/p_screen.h"
28848b8605Smrg#include "pipe/p_state.h"
29848b8605Smrg
30b8e80941Smrg#include "util/u_cpu_detect.h"
31848b8605Smrg#include "util/u_debug.h"
32848b8605Smrg#include "util/u_memory.h"
33848b8605Smrg#include "util/u_format.h"
34b8e80941Smrg#include "util/u_hash_table.h"
35b8e80941Smrg#include "util/u_screen.h"
36b8e80941Smrg#include "util/u_transfer_helper.h"
37b8e80941Smrg#include "util/ralloc.h"
38b8e80941Smrg
39b8e80941Smrg#include <xf86drm.h>
40b8e80941Smrg#include "drm-uapi/drm_fourcc.h"
41b8e80941Smrg#include "drm-uapi/vc4_drm.h"
42848b8605Smrg#include "vc4_screen.h"
43848b8605Smrg#include "vc4_context.h"
44848b8605Smrg#include "vc4_resource.h"
45848b8605Smrg
46848b8605Smrgstatic const struct debug_named_value debug_options[] = {
47848b8605Smrg        { "cl",       VC4_DEBUG_CL,
48848b8605Smrg          "Dump command list during creation" },
49b8e80941Smrg        { "surf",       VC4_DEBUG_SURFACE,
50b8e80941Smrg          "Dump surface layouts" },
51848b8605Smrg        { "qpu",      VC4_DEBUG_QPU,
52848b8605Smrg          "Dump generated QPU instructions" },
53848b8605Smrg        { "qir",      VC4_DEBUG_QIR,
54848b8605Smrg          "Dump QPU IR during program compile" },
55b8e80941Smrg        { "nir",      VC4_DEBUG_NIR,
56b8e80941Smrg          "Dump NIR during program compile" },
57848b8605Smrg        { "tgsi",     VC4_DEBUG_TGSI,
58848b8605Smrg          "Dump TGSI during program compile" },
59848b8605Smrg        { "shaderdb", VC4_DEBUG_SHADERDB,
60848b8605Smrg          "Dump program compile information for shader-db analysis" },
61848b8605Smrg        { "perf",     VC4_DEBUG_PERF,
62848b8605Smrg          "Print during performance-related events" },
63848b8605Smrg        { "norast",   VC4_DEBUG_NORAST,
64848b8605Smrg          "Skip actual hardware execution of commands" },
65b8e80941Smrg        { "always_flush", VC4_DEBUG_ALWAYS_FLUSH,
66b8e80941Smrg          "Flush after each draw call" },
67b8e80941Smrg        { "always_sync", VC4_DEBUG_ALWAYS_SYNC,
68b8e80941Smrg          "Wait for finish after each flush" },
69b8e80941Smrg#ifdef USE_VC4_SIMULATOR
70b8e80941Smrg        { "dump", VC4_DEBUG_DUMP,
71b8e80941Smrg          "Write a GPU command stream trace file" },
72b8e80941Smrg#endif
73b8e80941Smrg        { NULL }
74848b8605Smrg};
75848b8605Smrg
76848b8605SmrgDEBUG_GET_ONCE_FLAGS_OPTION(vc4_debug, "VC4_DEBUG", debug_options, 0)
77848b8605Smrguint32_t vc4_debug;
78848b8605Smrg
79848b8605Smrgstatic const char *
80848b8605Smrgvc4_screen_get_name(struct pipe_screen *pscreen)
81848b8605Smrg{
82b8e80941Smrg        struct vc4_screen *screen = vc4_screen(pscreen);
83b8e80941Smrg
84b8e80941Smrg        if (!screen->name) {
85b8e80941Smrg                screen->name = ralloc_asprintf(screen,
86b8e80941Smrg                                               "VC4 V3D %d.%d",
87b8e80941Smrg                                               screen->v3d_ver / 10,
88b8e80941Smrg                                               screen->v3d_ver % 10);
89b8e80941Smrg        }
90b8e80941Smrg
91b8e80941Smrg        return screen->name;
92848b8605Smrg}
93848b8605Smrg
94848b8605Smrgstatic const char *
95848b8605Smrgvc4_screen_get_vendor(struct pipe_screen *pscreen)
96848b8605Smrg{
97848b8605Smrg        return "Broadcom";
98848b8605Smrg}
99848b8605Smrg
100848b8605Smrgstatic void
101848b8605Smrgvc4_screen_destroy(struct pipe_screen *pscreen)
102848b8605Smrg{
103b8e80941Smrg        struct vc4_screen *screen = vc4_screen(pscreen);
104b8e80941Smrg
105b8e80941Smrg        util_hash_table_destroy(screen->bo_handles);
106b8e80941Smrg        vc4_bufmgr_destroy(pscreen);
107b8e80941Smrg        slab_destroy_parent(&screen->transfer_pool);
108b8e80941Smrg        free(screen->ro);
109b8e80941Smrg
110b8e80941Smrg#ifdef USE_VC4_SIMULATOR
111b8e80941Smrg        vc4_simulator_destroy(screen);
112b8e80941Smrg#endif
113b8e80941Smrg
114b8e80941Smrg        u_transfer_helper_destroy(pscreen->transfer_helper);
115b8e80941Smrg
116b8e80941Smrg        close(screen->fd);
117b8e80941Smrg        ralloc_free(pscreen);
118b8e80941Smrg}
119b8e80941Smrg
120b8e80941Smrgstatic bool
121b8e80941Smrgvc4_has_feature(struct vc4_screen *screen, uint32_t feature)
122b8e80941Smrg{
123b8e80941Smrg        struct drm_vc4_get_param p = {
124b8e80941Smrg                .param = feature,
125b8e80941Smrg        };
126b8e80941Smrg        int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
127b8e80941Smrg
128b8e80941Smrg        if (ret != 0)
129b8e80941Smrg                return false;
130b8e80941Smrg
131b8e80941Smrg        return p.value;
132848b8605Smrg}
133848b8605Smrg
134848b8605Smrgstatic int
135848b8605Smrgvc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
136848b8605Smrg{
137b8e80941Smrg        struct vc4_screen *screen = vc4_screen(pscreen);
138b8e80941Smrg
139848b8605Smrg        switch (param) {
140848b8605Smrg                /* Supported features (boolean caps). */
141b8e80941Smrg        case PIPE_CAP_VERTEX_COLOR_CLAMPED:
142848b8605Smrg        case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
143b8e80941Smrg        case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
144848b8605Smrg        case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
145848b8605Smrg        case PIPE_CAP_NPOT_TEXTURES:
146b8e80941Smrg        case PIPE_CAP_SHAREABLE_SHADERS:
147848b8605Smrg        case PIPE_CAP_BLEND_EQUATION_SEPARATE:
148b8e80941Smrg        case PIPE_CAP_TEXTURE_MULTISAMPLE:
149b8e80941Smrg        case PIPE_CAP_TEXTURE_SWIZZLE:
150b8e80941Smrg        case PIPE_CAP_TEXTURE_BARRIER:
151848b8605Smrg                return 1;
152848b8605Smrg
153b8e80941Smrg        case PIPE_CAP_NATIVE_FENCE_FD:
154b8e80941Smrg                return screen->has_syncobj;
155b8e80941Smrg
156b8e80941Smrg        case PIPE_CAP_TILE_RASTER_ORDER:
157b8e80941Smrg                return vc4_has_feature(screen,
158b8e80941Smrg                                       DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER);
159b8e80941Smrg
160848b8605Smrg                /* lying for GL 2.0 */
161848b8605Smrg        case PIPE_CAP_OCCLUSION_QUERY:
162848b8605Smrg        case PIPE_CAP_POINT_SPRITE:
163848b8605Smrg                return 1;
164848b8605Smrg
165848b8605Smrg        case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
166848b8605Smrg        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
167848b8605Smrg                return 1;
168848b8605Smrg
169848b8605Smrg        case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
170b8e80941Smrg        case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
171b8e80941Smrg                return 1;
172848b8605Smrg
173848b8605Smrg                /* Texturing. */
174848b8605Smrg        case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
175848b8605Smrg        case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
176848b8605Smrg                return VC4_MAX_MIP_LEVELS;
177848b8605Smrg        case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
178848b8605Smrg                /* Note: Not supported in hardware, just faking it. */
179848b8605Smrg                return 5;
180848b8605Smrg
181b8e80941Smrg        case PIPE_CAP_MAX_VARYINGS:
182b8e80941Smrg                return 8;
183848b8605Smrg
184848b8605Smrg        case PIPE_CAP_VENDOR_ID:
185848b8605Smrg                return 0x14E4;
186848b8605Smrg        case PIPE_CAP_ACCELERATED:
187848b8605Smrg                return 1;
188848b8605Smrg        case PIPE_CAP_VIDEO_MEMORY: {
189848b8605Smrg                uint64_t system_memory;
190848b8605Smrg
191848b8605Smrg                if (!os_get_total_physical_memory(&system_memory))
192848b8605Smrg                        return 0;
193848b8605Smrg
194848b8605Smrg                return (int)(system_memory >> 20);
195848b8605Smrg        }
196848b8605Smrg        case PIPE_CAP_UMA:
197848b8605Smrg                return 1;
198848b8605Smrg
199848b8605Smrg        default:
200b8e80941Smrg                return u_pipe_screen_get_param_defaults(pscreen, param);
201848b8605Smrg        }
202848b8605Smrg}
203848b8605Smrg
204848b8605Smrgstatic float
205848b8605Smrgvc4_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
206848b8605Smrg{
207848b8605Smrg        switch (param) {
208848b8605Smrg        case PIPE_CAPF_MAX_LINE_WIDTH:
209848b8605Smrg        case PIPE_CAPF_MAX_LINE_WIDTH_AA:
210b8e80941Smrg                return 32;
211b8e80941Smrg
212848b8605Smrg        case PIPE_CAPF_MAX_POINT_WIDTH:
213848b8605Smrg        case PIPE_CAPF_MAX_POINT_WIDTH_AA:
214b8e80941Smrg                return 512.0f;
215b8e80941Smrg
216848b8605Smrg        case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
217848b8605Smrg                return 0.0f;
218848b8605Smrg        case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
219848b8605Smrg                return 0.0f;
220b8e80941Smrg
221b8e80941Smrg        case PIPE_CAPF_MIN_CONSERVATIVE_RASTER_DILATE:
222b8e80941Smrg        case PIPE_CAPF_MAX_CONSERVATIVE_RASTER_DILATE:
223b8e80941Smrg        case PIPE_CAPF_CONSERVATIVE_RASTER_DILATE_GRANULARITY:
224848b8605Smrg                return 0.0f;
225848b8605Smrg        default:
226848b8605Smrg                fprintf(stderr, "unknown paramf %d\n", param);
227848b8605Smrg                return 0;
228848b8605Smrg        }
229848b8605Smrg}
230848b8605Smrg
231848b8605Smrgstatic int
232b8e80941Smrgvc4_screen_get_shader_param(struct pipe_screen *pscreen,
233b8e80941Smrg                            enum pipe_shader_type shader,
234b8e80941Smrg                            enum pipe_shader_cap param)
235848b8605Smrg{
236848b8605Smrg        if (shader != PIPE_SHADER_VERTEX &&
237848b8605Smrg            shader != PIPE_SHADER_FRAGMENT) {
238848b8605Smrg                return 0;
239848b8605Smrg        }
240848b8605Smrg
241848b8605Smrg        /* this is probably not totally correct.. but it's a start: */
242848b8605Smrg        switch (param) {
243848b8605Smrg        case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
244848b8605Smrg        case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
245848b8605Smrg        case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
246848b8605Smrg        case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
247848b8605Smrg                return 16384;
248b8e80941Smrg
249848b8605Smrg        case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
250b8e80941Smrg                return vc4_screen(pscreen)->has_control_flow;
251b8e80941Smrg
252848b8605Smrg        case PIPE_SHADER_CAP_MAX_INPUTS:
253b8e80941Smrg                return 8;
254b8e80941Smrg        case PIPE_SHADER_CAP_MAX_OUTPUTS:
255b8e80941Smrg                return shader == PIPE_SHADER_FRAGMENT ? 1 : 8;
256848b8605Smrg        case PIPE_SHADER_CAP_MAX_TEMPS:
257b8e80941Smrg                return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
258848b8605Smrg        case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
259b8e80941Smrg                return 16 * 1024 * sizeof(float);
260848b8605Smrg        case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
261848b8605Smrg                return 1;
262848b8605Smrg        case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
263848b8605Smrg                return 0;
264848b8605Smrg        case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
265848b8605Smrg        case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
266848b8605Smrg        case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
267848b8605Smrg                return 0;
268b8e80941Smrg        case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
269b8e80941Smrg                return 1;
270848b8605Smrg        case PIPE_SHADER_CAP_SUBROUTINES:
271848b8605Smrg                return 0;
272848b8605Smrg        case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
273848b8605Smrg                return 0;
274848b8605Smrg        case PIPE_SHADER_CAP_INTEGERS:
275b8e80941Smrg                return 1;
276b8e80941Smrg        case PIPE_SHADER_CAP_INT64_ATOMICS:
277b8e80941Smrg        case PIPE_SHADER_CAP_FP16:
278b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
279b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
280b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
281b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
282b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
283848b8605Smrg                return 0;
284848b8605Smrg        case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
285848b8605Smrg        case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
286848b8605Smrg                return VC4_MAX_TEXTURE_SAMPLERS;
287848b8605Smrg        case PIPE_SHADER_CAP_PREFERRED_IR:
288b8e80941Smrg                return PIPE_SHADER_IR_NIR;
289b8e80941Smrg        case PIPE_SHADER_CAP_SUPPORTED_IRS:
290848b8605Smrg                return 0;
291b8e80941Smrg        case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
292b8e80941Smrg                return 32;
293b8e80941Smrg        case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
294b8e80941Smrg        case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
295b8e80941Smrg        case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
296b8e80941Smrg        case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
297b8e80941Smrg        case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
298b8e80941Smrg        case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
299848b8605Smrg                return 0;
300b8e80941Smrg        case PIPE_SHADER_CAP_SCALAR_ISA:
301848b8605Smrg                return 1;
302848b8605Smrg        default:
303b8e80941Smrg                fprintf(stderr, "unknown shader param %d\n", param);
304b8e80941Smrg                return 0;
305848b8605Smrg        }
306b8e80941Smrg        return 0;
307848b8605Smrg}
308848b8605Smrg
309848b8605Smrgstatic boolean
310848b8605Smrgvc4_screen_is_format_supported(struct pipe_screen *pscreen,
311848b8605Smrg                               enum pipe_format format,
312848b8605Smrg                               enum pipe_texture_target target,
313848b8605Smrg                               unsigned sample_count,
314b8e80941Smrg                               unsigned storage_sample_count,
315848b8605Smrg                               unsigned usage)
316848b8605Smrg{
317b8e80941Smrg        struct vc4_screen *screen = vc4_screen(pscreen);
318b8e80941Smrg
319b8e80941Smrg        if (MAX2(1, sample_count) != MAX2(1, storage_sample_count))
320b8e80941Smrg                return false;
321848b8605Smrg
322b8e80941Smrg        if (sample_count > 1 && sample_count != VC4_MAX_SAMPLES)
323b8e80941Smrg                return FALSE;
324b8e80941Smrg
325b8e80941Smrg        if (target >= PIPE_MAX_TEXTURE_TYPES) {
326848b8605Smrg                return FALSE;
327848b8605Smrg        }
328848b8605Smrg
329b8e80941Smrg        if (usage & PIPE_BIND_VERTEX_BUFFER) {
330b8e80941Smrg                switch (format) {
331b8e80941Smrg                case PIPE_FORMAT_R32G32B32A32_FLOAT:
332b8e80941Smrg                case PIPE_FORMAT_R32G32B32_FLOAT:
333b8e80941Smrg                case PIPE_FORMAT_R32G32_FLOAT:
334b8e80941Smrg                case PIPE_FORMAT_R32_FLOAT:
335b8e80941Smrg                case PIPE_FORMAT_R32G32B32A32_SNORM:
336b8e80941Smrg                case PIPE_FORMAT_R32G32B32_SNORM:
337b8e80941Smrg                case PIPE_FORMAT_R32G32_SNORM:
338b8e80941Smrg                case PIPE_FORMAT_R32_SNORM:
339b8e80941Smrg                case PIPE_FORMAT_R32G32B32A32_SSCALED:
340b8e80941Smrg                case PIPE_FORMAT_R32G32B32_SSCALED:
341b8e80941Smrg                case PIPE_FORMAT_R32G32_SSCALED:
342b8e80941Smrg                case PIPE_FORMAT_R32_SSCALED:
343b8e80941Smrg                case PIPE_FORMAT_R16G16B16A16_UNORM:
344b8e80941Smrg                case PIPE_FORMAT_R16G16B16_UNORM:
345b8e80941Smrg                case PIPE_FORMAT_R16G16_UNORM:
346b8e80941Smrg                case PIPE_FORMAT_R16_UNORM:
347b8e80941Smrg                case PIPE_FORMAT_R16G16B16A16_SNORM:
348b8e80941Smrg                case PIPE_FORMAT_R16G16B16_SNORM:
349b8e80941Smrg                case PIPE_FORMAT_R16G16_SNORM:
350b8e80941Smrg                case PIPE_FORMAT_R16_SNORM:
351b8e80941Smrg                case PIPE_FORMAT_R16G16B16A16_USCALED:
352b8e80941Smrg                case PIPE_FORMAT_R16G16B16_USCALED:
353b8e80941Smrg                case PIPE_FORMAT_R16G16_USCALED:
354b8e80941Smrg                case PIPE_FORMAT_R16_USCALED:
355b8e80941Smrg                case PIPE_FORMAT_R16G16B16A16_SSCALED:
356b8e80941Smrg                case PIPE_FORMAT_R16G16B16_SSCALED:
357b8e80941Smrg                case PIPE_FORMAT_R16G16_SSCALED:
358b8e80941Smrg                case PIPE_FORMAT_R16_SSCALED:
359b8e80941Smrg                case PIPE_FORMAT_R8G8B8A8_UNORM:
360b8e80941Smrg                case PIPE_FORMAT_R8G8B8_UNORM:
361b8e80941Smrg                case PIPE_FORMAT_R8G8_UNORM:
362b8e80941Smrg                case PIPE_FORMAT_R8_UNORM:
363b8e80941Smrg                case PIPE_FORMAT_R8G8B8A8_SNORM:
364b8e80941Smrg                case PIPE_FORMAT_R8G8B8_SNORM:
365b8e80941Smrg                case PIPE_FORMAT_R8G8_SNORM:
366b8e80941Smrg                case PIPE_FORMAT_R8_SNORM:
367b8e80941Smrg                case PIPE_FORMAT_R8G8B8A8_USCALED:
368b8e80941Smrg                case PIPE_FORMAT_R8G8B8_USCALED:
369b8e80941Smrg                case PIPE_FORMAT_R8G8_USCALED:
370b8e80941Smrg                case PIPE_FORMAT_R8_USCALED:
371b8e80941Smrg                case PIPE_FORMAT_R8G8B8A8_SSCALED:
372b8e80941Smrg                case PIPE_FORMAT_R8G8B8_SSCALED:
373b8e80941Smrg                case PIPE_FORMAT_R8G8_SSCALED:
374b8e80941Smrg                case PIPE_FORMAT_R8_SSCALED:
375b8e80941Smrg                        break;
376b8e80941Smrg                default:
377b8e80941Smrg                        return FALSE;
378b8e80941Smrg                }
379848b8605Smrg        }
380848b8605Smrg
381848b8605Smrg        if ((usage & PIPE_BIND_RENDER_TARGET) &&
382b8e80941Smrg            !vc4_rt_format_supported(format)) {
383b8e80941Smrg                return FALSE;
384848b8605Smrg        }
385848b8605Smrg
386848b8605Smrg        if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
387b8e80941Smrg            (!vc4_tex_format_supported(format) ||
388b8e80941Smrg             (format == PIPE_FORMAT_ETC1_RGB8 && !screen->has_etc1))) {
389b8e80941Smrg                return FALSE;
390848b8605Smrg        }
391848b8605Smrg
392848b8605Smrg        if ((usage & PIPE_BIND_DEPTH_STENCIL) &&
393b8e80941Smrg            format != PIPE_FORMAT_S8_UINT_Z24_UNORM &&
394b8e80941Smrg            format != PIPE_FORMAT_X8Z24_UNORM) {
395b8e80941Smrg                return FALSE;
396848b8605Smrg        }
397848b8605Smrg
398848b8605Smrg        if ((usage & PIPE_BIND_INDEX_BUFFER) &&
399b8e80941Smrg            format != PIPE_FORMAT_I8_UINT &&
400b8e80941Smrg            format != PIPE_FORMAT_I16_UINT) {
401b8e80941Smrg                return FALSE;
402848b8605Smrg        }
403848b8605Smrg
404b8e80941Smrg        return TRUE;
405b8e80941Smrg}
406848b8605Smrg
407b8e80941Smrgstatic void
408b8e80941Smrgvc4_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
409b8e80941Smrg                                  enum pipe_format format, int max,
410b8e80941Smrg                                  uint64_t *modifiers,
411b8e80941Smrg                                  unsigned int *external_only,
412b8e80941Smrg                                  int *count)
413b8e80941Smrg{
414b8e80941Smrg        int m, i;
415b8e80941Smrg        uint64_t available_modifiers[] = {
416b8e80941Smrg                DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
417b8e80941Smrg                DRM_FORMAT_MOD_LINEAR,
418b8e80941Smrg        };
419b8e80941Smrg        struct vc4_screen *screen = vc4_screen(pscreen);
420b8e80941Smrg        int num_modifiers = screen->has_tiling_ioctl ? 2 : 1;
421b8e80941Smrg
422b8e80941Smrg        if (!modifiers) {
423b8e80941Smrg                *count = num_modifiers;
424b8e80941Smrg                return;
425b8e80941Smrg        }
426b8e80941Smrg
427b8e80941Smrg        *count = MIN2(max, num_modifiers);
428b8e80941Smrg        m = screen->has_tiling_ioctl ? 0 : 1;
429b8e80941Smrg        /* We support both modifiers (tiled and linear) for all sampler
430b8e80941Smrg         * formats, but if we don't have the DRM_VC4_GET_TILING ioctl
431b8e80941Smrg         * we shouldn't advertise the tiled formats.
432b8e80941Smrg         */
433b8e80941Smrg        for (i = 0; i < *count; i++) {
434b8e80941Smrg                modifiers[i] = available_modifiers[m++];
435b8e80941Smrg                if (external_only)
436b8e80941Smrg                        external_only[i] = false;
437b8e80941Smrg       }
438b8e80941Smrg}
439b8e80941Smrg
440b8e80941Smrg#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
441b8e80941Smrg
442b8e80941Smrgstatic unsigned handle_hash(void *key)
443b8e80941Smrg{
444b8e80941Smrg    return PTR_TO_UINT(key);
445b8e80941Smrg}
446b8e80941Smrg
447b8e80941Smrgstatic int handle_compare(void *key1, void *key2)
448b8e80941Smrg{
449b8e80941Smrg    return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
450b8e80941Smrg}
451b8e80941Smrg
452b8e80941Smrgstatic bool
453b8e80941Smrgvc4_get_chip_info(struct vc4_screen *screen)
454b8e80941Smrg{
455b8e80941Smrg        struct drm_vc4_get_param ident0 = {
456b8e80941Smrg                .param = DRM_VC4_PARAM_V3D_IDENT0,
457b8e80941Smrg        };
458b8e80941Smrg        struct drm_vc4_get_param ident1 = {
459b8e80941Smrg                .param = DRM_VC4_PARAM_V3D_IDENT1,
460b8e80941Smrg        };
461b8e80941Smrg        int ret;
462b8e80941Smrg
463b8e80941Smrg        ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident0);
464b8e80941Smrg        if (ret != 0) {
465b8e80941Smrg                if (errno == EINVAL) {
466b8e80941Smrg                        /* Backwards compatibility with 2835 kernels which
467b8e80941Smrg                         * only do V3D 2.1.
468b8e80941Smrg                         */
469b8e80941Smrg                        screen->v3d_ver = 21;
470b8e80941Smrg                        return true;
471b8e80941Smrg                } else {
472b8e80941Smrg                        fprintf(stderr, "Couldn't get V3D IDENT0: %s\n",
473b8e80941Smrg                                strerror(errno));
474b8e80941Smrg                        return false;
475b8e80941Smrg                }
476b8e80941Smrg        }
477b8e80941Smrg        ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident1);
478b8e80941Smrg        if (ret != 0) {
479b8e80941Smrg                fprintf(stderr, "Couldn't get V3D IDENT1: %s\n",
480b8e80941Smrg                        strerror(errno));
481b8e80941Smrg                return false;
482b8e80941Smrg        }
483b8e80941Smrg
484b8e80941Smrg        uint32_t major = (ident0.value >> 24) & 0xff;
485b8e80941Smrg        uint32_t minor = (ident1.value >> 0) & 0xf;
486b8e80941Smrg        screen->v3d_ver = major * 10 + minor;
487b8e80941Smrg
488b8e80941Smrg        if (screen->v3d_ver != 21 && screen->v3d_ver != 26) {
489b8e80941Smrg                fprintf(stderr,
490b8e80941Smrg                        "V3D %d.%d not supported by this version of Mesa.\n",
491b8e80941Smrg                        screen->v3d_ver / 10,
492b8e80941Smrg                        screen->v3d_ver % 10);
493b8e80941Smrg                return false;
494b8e80941Smrg        }
495b8e80941Smrg
496b8e80941Smrg        return true;
497848b8605Smrg}
498848b8605Smrg
499848b8605Smrgstruct pipe_screen *
500b8e80941Smrgvc4_screen_create(int fd, struct renderonly *ro)
501848b8605Smrg{
502b8e80941Smrg        struct vc4_screen *screen = rzalloc(NULL, struct vc4_screen);
503b8e80941Smrg        uint64_t syncobj_cap = 0;
504848b8605Smrg        struct pipe_screen *pscreen;
505b8e80941Smrg        int err;
506848b8605Smrg
507848b8605Smrg        pscreen = &screen->base;
508848b8605Smrg
509848b8605Smrg        pscreen->destroy = vc4_screen_destroy;
510848b8605Smrg        pscreen->get_param = vc4_screen_get_param;
511848b8605Smrg        pscreen->get_paramf = vc4_screen_get_paramf;
512848b8605Smrg        pscreen->get_shader_param = vc4_screen_get_shader_param;
513848b8605Smrg        pscreen->context_create = vc4_context_create;
514848b8605Smrg        pscreen->is_format_supported = vc4_screen_is_format_supported;
515848b8605Smrg
516848b8605Smrg        screen->fd = fd;
517b8e80941Smrg        if (ro) {
518b8e80941Smrg                screen->ro = renderonly_dup(ro);
519b8e80941Smrg                if (!screen->ro) {
520b8e80941Smrg                        fprintf(stderr, "Failed to dup renderonly object\n");
521b8e80941Smrg                        ralloc_free(screen);
522b8e80941Smrg                        return NULL;
523b8e80941Smrg                }
524b8e80941Smrg        }
525b8e80941Smrg
526b8e80941Smrg        list_inithead(&screen->bo_cache.time_list);
527b8e80941Smrg        (void) mtx_init(&screen->bo_handles_mutex, mtx_plain);
528b8e80941Smrg        screen->bo_handles = util_hash_table_create(handle_hash, handle_compare);
529b8e80941Smrg
530b8e80941Smrg        screen->has_control_flow =
531b8e80941Smrg                vc4_has_feature(screen, DRM_VC4_PARAM_SUPPORTS_BRANCHES);
532b8e80941Smrg        screen->has_etc1 =
533b8e80941Smrg                vc4_has_feature(screen, DRM_VC4_PARAM_SUPPORTS_ETC1);
534b8e80941Smrg        screen->has_threaded_fs =
535b8e80941Smrg                vc4_has_feature(screen, DRM_VC4_PARAM_SUPPORTS_THREADED_FS);
536b8e80941Smrg        screen->has_madvise =
537b8e80941Smrg                vc4_has_feature(screen, DRM_VC4_PARAM_SUPPORTS_MADVISE);
538b8e80941Smrg        screen->has_perfmon_ioctl =
539b8e80941Smrg                vc4_has_feature(screen, DRM_VC4_PARAM_SUPPORTS_PERFMON);
540b8e80941Smrg
541b8e80941Smrg        err = drmGetCap(fd, DRM_CAP_SYNCOBJ, &syncobj_cap);
542b8e80941Smrg        if (err == 0 && syncobj_cap)
543b8e80941Smrg                screen->has_syncobj = true;
544b8e80941Smrg
545b8e80941Smrg        if (!vc4_get_chip_info(screen))
546b8e80941Smrg                goto fail;
547b8e80941Smrg
548b8e80941Smrg        util_cpu_detect();
549b8e80941Smrg
550b8e80941Smrg        slab_create_parent(&screen->transfer_pool, sizeof(struct vc4_transfer), 16);
551848b8605Smrg
552b8e80941Smrg        vc4_fence_screen_init(screen);
553b8e80941Smrg
554b8e80941Smrg        vc4_debug = debug_get_option_vc4_debug();
555848b8605Smrg        if (vc4_debug & VC4_DEBUG_SHADERDB)
556848b8605Smrg                vc4_debug |= VC4_DEBUG_NORAST;
557848b8605Smrg
558b8e80941Smrg#ifdef USE_VC4_SIMULATOR
559848b8605Smrg        vc4_simulator_init(screen);
560848b8605Smrg#endif
561848b8605Smrg
562848b8605Smrg        vc4_resource_screen_init(pscreen);
563848b8605Smrg
564848b8605Smrg        pscreen->get_name = vc4_screen_get_name;
565848b8605Smrg        pscreen->get_vendor = vc4_screen_get_vendor;
566b8e80941Smrg        pscreen->get_device_vendor = vc4_screen_get_vendor;
567b8e80941Smrg        pscreen->get_compiler_options = vc4_screen_get_compiler_options;
568b8e80941Smrg        pscreen->query_dmabuf_modifiers = vc4_screen_query_dmabuf_modifiers;
569848b8605Smrg
570b8e80941Smrg        if (screen->has_perfmon_ioctl) {
571b8e80941Smrg                pscreen->get_driver_query_group_info = vc4_get_driver_query_group_info;
572b8e80941Smrg                pscreen->get_driver_query_info = vc4_get_driver_query_info;
573848b8605Smrg        }
574848b8605Smrg
575b8e80941Smrg        return pscreen;
576848b8605Smrg
577b8e80941Smrgfail:
578b8e80941Smrg        close(fd);
579b8e80941Smrg        ralloc_free(pscreen);
580b8e80941Smrg        return NULL;
581848b8605Smrg}
582