panfrost: Include glue for out-of-tree legacy code
[mesa.git] / src / gallium / drivers / panfrost / pan_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2014 Broadcom
5 * Copyright 2018 Alyssa Rosenzweig
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31 #include "util/u_memory.h"
32 #include "util/u_format.h"
33 #include "util/u_format_s3tc.h"
34 #include "util/u_video.h"
35 #include "util/u_screen.h"
36 #include "util/os_time.h"
37 #include "pipe/p_defines.h"
38 #include "pipe/p_screen.h"
39 #include "draw/draw_context.h"
40 #include <xf86drm.h>
41
42 #include <fcntl.h>
43
44 #include "drm_fourcc.h"
45
46 #include "pan_screen.h"
47 #include "pan_resource.h"
48 #include "pan_public.h"
49
50 #include "pan_context.h"
51 #include "midgard/midgard_compile.h"
52
53 struct panfrost_driver *panfrost_create_drm_driver(int fd);
54 struct panfrost_driver *panfrost_create_nondrm_driver(int fd);
55
56 static const char *
57 panfrost_get_name(struct pipe_screen *screen)
58 {
59 return "panfrost";
60 }
61
62 static const char *
63 panfrost_get_vendor(struct pipe_screen *screen)
64 {
65 return "panfrost";
66 }
67
68 static const char *
69 panfrost_get_device_vendor(struct pipe_screen *screen)
70 {
71 return "Arm";
72 }
73
74 static int
75 panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param)
76 {
77 switch (param) {
78 case PIPE_CAP_NPOT_TEXTURES:
79 case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
80 case PIPE_CAP_MIXED_COLOR_DEPTH_BITS:
81 return 1;
82
83 case PIPE_CAP_SM3:
84 case PIPE_CAP_POINT_SPRITE:
85 return 1;
86
87 case PIPE_CAP_MAX_RENDER_TARGETS:
88 case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
89 return 1;
90
91 case PIPE_CAP_OCCLUSION_QUERY:
92 case PIPE_CAP_QUERY_TIME_ELAPSED:
93 case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
94 return 1; /* TODO: Queries */
95
96 case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
97 case PIPE_CAP_TEXTURE_SWIZZLE:
98 return 1;
99
100 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
101 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
102 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
103 return 13;
104
105 case PIPE_CAP_BLEND_EQUATION_SEPARATE:
106 return 1;
107
108 case PIPE_CAP_INDEP_BLEND_ENABLE:
109 return 1;
110
111 case PIPE_CAP_INDEP_BLEND_FUNC:
112 return 1;
113
114 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
115 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
116 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
117 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
118 return 1;
119
120 case PIPE_CAP_DEPTH_CLIP_DISABLE:
121 return 1;
122
123 case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
124 case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
125 return 16 * 4;
126
127 case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
128 case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
129 return 1024;
130
131 case PIPE_CAP_MAX_VERTEX_STREAMS:
132 return 1;
133
134 case PIPE_CAP_SHADER_STENCIL_EXPORT:
135 return 1;
136
137 case PIPE_CAP_SEAMLESS_CUBE_MAP:
138 case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
139 return 1;
140
141 case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
142 return 256; /* for GL3 */
143
144 case PIPE_CAP_CONDITIONAL_RENDER:
145 return 1;
146
147 case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
148 case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
149 case PIPE_CAP_VERTEX_COLOR_CLAMPED:
150 return 1;
151
152 case PIPE_CAP_GLSL_FEATURE_LEVEL:
153 return 330;
154
155 case PIPE_CAP_USER_VERTEX_BUFFERS: /* TODO */
156 case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
157 return 0;
158
159 case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
160 case PIPE_CAP_DOUBLES:
161 case PIPE_CAP_INT64:
162 case PIPE_CAP_INT64_DIVMOD:
163 return 1;
164
165 case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
166 return 16;
167
168 case PIPE_CAP_MAX_VERTEX_ELEMENT_SRC_OFFSET:
169 return 0xffff;
170
171 case PIPE_CAP_QUERY_TIMESTAMP:
172 case PIPE_CAP_CUBE_MAP_ARRAY:
173 return 1;
174
175 case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
176 return 1;
177
178 case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
179 return 65536;
180
181 case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
182 return 0;
183
184 case PIPE_CAP_TGSI_TEXCOORD:
185 return 1; /* XXX: What should this me exactly? */
186
187 case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
188 return 0;
189
190 case PIPE_CAP_MAX_VIEWPORTS:
191 return PIPE_MAX_VIEWPORTS;
192
193 case PIPE_CAP_ENDIANNESS:
194 return PIPE_ENDIAN_NATIVE;
195
196 case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
197 return 4;
198
199 case PIPE_CAP_TEXTURE_GATHER_SM5:
200 case PIPE_CAP_TEXTURE_QUERY_LOD:
201 case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
202 case PIPE_CAP_SAMPLER_VIEW_TARGET:
203 case PIPE_CAP_FAKE_SW_MSAA:
204 return 1;
205
206 case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
207 return -32;
208
209 case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
210 return 31;
211
212 case PIPE_CAP_DRAW_INDIRECT:
213 return 1;
214
215 case PIPE_CAP_QUERY_SO_OVERFLOW:
216 return 1;
217
218 case PIPE_CAP_VENDOR_ID:
219 return 0xFFFFFFFF;
220
221 case PIPE_CAP_DEVICE_ID:
222 return 0xFFFFFFFF;
223
224 case PIPE_CAP_ACCELERATED:
225 return 1;
226
227 case PIPE_CAP_VIDEO_MEMORY: {
228 uint64_t system_memory;
229
230 if (!os_get_total_physical_memory(&system_memory))
231 return 0;
232
233 return (int)(system_memory >> 20);
234 }
235
236 case PIPE_CAP_UMA:
237 return 1;
238
239 case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
240 case PIPE_CAP_CLIP_HALFZ:
241 case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
242 case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
243 case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
244 case PIPE_CAP_CULL_DISTANCE:
245 case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
246 case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
247 case PIPE_CAP_CLEAR_TEXTURE:
248 return 1;
249
250 case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
251 return 4;
252
253 default:
254 return u_pipe_screen_get_param_defaults(screen, param);
255 }
256 }
257
258 static int
259 panfrost_get_shader_param(struct pipe_screen *screen,
260 enum pipe_shader_type shader,
261 enum pipe_shader_cap param)
262 {
263 if (shader != PIPE_SHADER_VERTEX &&
264 shader != PIPE_SHADER_FRAGMENT) {
265 return 0;
266 }
267
268 /* this is probably not totally correct.. but it's a start: */
269 switch (param) {
270 case PIPE_SHADER_CAP_SCALAR_ISA:
271 return 0;
272
273 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
274 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
275 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
276 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
277 return 16384;
278
279 case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
280 return 1024;
281
282 case PIPE_SHADER_CAP_MAX_INPUTS:
283 return 16;
284
285 case PIPE_SHADER_CAP_MAX_OUTPUTS:
286 return shader == PIPE_SHADER_FRAGMENT ? 1 : 8;
287
288 case PIPE_SHADER_CAP_MAX_TEMPS:
289 return 256; /* GL_MAX_PROGRAM_TEMPORARIES_ARB */
290
291 case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
292 return 16 * 1024 * sizeof(float);
293
294 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
295 return 1;
296
297 case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
298 return 0;
299
300 case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
301 case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
302 case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
303 return 0;
304
305 case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
306 return 1;
307
308 case PIPE_SHADER_CAP_SUBROUTINES:
309 return 0;
310
311 case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
312 return 0;
313
314 case PIPE_SHADER_CAP_INTEGERS:
315 return 1;
316
317 case PIPE_SHADER_CAP_INT64_ATOMICS:
318 case PIPE_SHADER_CAP_FP16:
319 case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
320 case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED:
321 case PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED:
322 case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
323 case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
324 return 0;
325
326 case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
327 case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
328 return 16; /* XXX: How many? */
329
330 case PIPE_SHADER_CAP_PREFERRED_IR:
331 return PIPE_SHADER_IR_NIR;
332
333 case PIPE_SHADER_CAP_SUPPORTED_IRS:
334 return 0;
335
336 case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
337 return 32;
338
339 case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
340 case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
341 case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
342 case PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS:
343 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS:
344 case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS:
345 return 0;
346
347 default:
348 fprintf(stderr, "unknown shader param %d\n", param);
349 return 0;
350 }
351
352 return 0;
353 }
354
355 static float
356 panfrost_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
357 {
358 switch (param) {
359 case PIPE_CAPF_MAX_LINE_WIDTH:
360
361 /* fall-through */
362 case PIPE_CAPF_MAX_LINE_WIDTH_AA:
363 return 255.0; /* arbitrary */
364
365 case PIPE_CAPF_MAX_POINT_WIDTH:
366
367 /* fall-through */
368 case PIPE_CAPF_MAX_POINT_WIDTH_AA:
369 return 255.0; /* arbitrary */
370
371 case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
372 return 16.0;
373
374 case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
375 return 16.0; /* arbitrary */
376
377 default:
378 debug_printf("Unexpected PIPE_CAPF %d query\n", param);
379 return 0.0;
380 }
381 }
382
383 /**
384 * Query format support for creating a texture, drawing surface, etc.
385 * \param format the format to test
386 * \param type one of PIPE_TEXTURE, PIPE_SURFACE
387 */
388 static boolean
389 panfrost_is_format_supported( struct pipe_screen *screen,
390 enum pipe_format format,
391 enum pipe_texture_target target,
392 unsigned sample_count,
393 unsigned storage_sample_count,
394 unsigned bind)
395 {
396 const struct util_format_description *format_desc;
397
398 assert(target == PIPE_BUFFER ||
399 target == PIPE_TEXTURE_1D ||
400 target == PIPE_TEXTURE_1D_ARRAY ||
401 target == PIPE_TEXTURE_2D ||
402 target == PIPE_TEXTURE_2D_ARRAY ||
403 target == PIPE_TEXTURE_RECT ||
404 target == PIPE_TEXTURE_3D ||
405 target == PIPE_TEXTURE_CUBE ||
406 target == PIPE_TEXTURE_CUBE_ARRAY);
407
408 format_desc = util_format_description(format);
409
410 if (!format_desc)
411 return FALSE;
412
413 if (sample_count > 1)
414 return FALSE;
415
416 /* Format wishlist */
417 if (format == PIPE_FORMAT_Z24X8_UNORM || format == PIPE_FORMAT_X8Z24_UNORM)
418 return FALSE;
419
420 if (bind & PIPE_BIND_RENDER_TARGET) {
421 /* We don't support rendering into anything but RGBA8 yet. We
422 * need more formats for spec compliance, but for now, honesty
423 * is the best policy <3 */
424
425 if (!util_format_is_rgba8_variant(format_desc))
426 return FALSE;
427
428 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
429 return FALSE;
430
431 /*
432 * Although possible, it is unnatural to render into compressed or YUV
433 * surfaces. So disable these here to avoid going into weird paths
434 * inside the state trackers.
435 */
436 if (format_desc->block.width != 1 ||
437 format_desc->block.height != 1)
438 return FALSE;
439 }
440
441 if (bind & PIPE_BIND_DEPTH_STENCIL) {
442 if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
443 return FALSE;
444 }
445
446 if (format_desc->layout == UTIL_FORMAT_LAYOUT_BPTC ||
447 format_desc->layout == UTIL_FORMAT_LAYOUT_ASTC) {
448 /* Compressed formats not yet hooked up. */
449 return FALSE;
450 }
451
452 if ((bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) &&
453 ((bind & PIPE_BIND_DISPLAY_TARGET) == 0) &&
454 target != PIPE_BUFFER) {
455 const struct util_format_description *desc =
456 util_format_description(format);
457
458 if (desc->nr_channels == 3 && desc->is_array) {
459 /* Don't support any 3-component formats for rendering/texturing
460 * since we don't support the corresponding 8-bit 3 channel UNORM
461 * formats. This allows us to support GL_ARB_copy_image between
462 * GL_RGB8 and GL_RGB8UI, for example. Otherwise, we may be asked to
463 * do a resource copy between PIPE_FORMAT_R8G8B8_UINT and
464 * PIPE_FORMAT_R8G8B8X8_UNORM, for example, which will not work
465 * (different bpp).
466 */
467 return FALSE;
468 }
469 }
470
471 return TRUE;
472 }
473
474
475 static void
476 panfrost_destroy_screen( struct pipe_screen *screen )
477 {
478 FREE(screen);
479 }
480
481 static void
482 panfrost_flush_frontbuffer(struct pipe_screen *_screen,
483 struct pipe_resource *resource,
484 unsigned level, unsigned layer,
485 void *context_private,
486 struct pipe_box *sub_box)
487 {
488 /* TODO: Display target integration */
489 }
490
491 static uint64_t
492 panfrost_get_timestamp(struct pipe_screen *_screen)
493 {
494 return os_time_get_nano();
495 }
496
497 static void
498 panfrost_fence_reference(struct pipe_screen *screen,
499 struct pipe_fence_handle **ptr,
500 struct pipe_fence_handle *fence)
501 {
502 *ptr = fence;
503 }
504
505 static boolean
506 panfrost_fence_finish(struct pipe_screen *screen,
507 struct pipe_context *ctx,
508 struct pipe_fence_handle *fence,
509 uint64_t timeout)
510 {
511 assert(fence);
512 return TRUE;
513 }
514
515 static const void *
516 panfrost_screen_get_compiler_options(struct pipe_screen *pscreen,
517 enum pipe_shader_ir ir,
518 enum pipe_shader_type shader)
519 {
520 return &midgard_nir_options;
521 }
522
523 struct pipe_screen *
524 panfrost_create_screen(int fd, struct renderonly *ro, bool is_drm)
525 {
526 struct panfrost_screen *screen = CALLOC_STRUCT(panfrost_screen);
527
528 if (!screen)
529 return NULL;
530
531 if (ro) {
532 screen->ro = renderonly_dup(ro);
533 if (!screen->ro) {
534 fprintf(stderr, "Failed to dup renderonly object\n");
535 free(screen);
536 return NULL;
537 }
538 }
539
540 if (is_drm) {
541 screen->driver = panfrost_create_drm_driver(fd);
542 } else {
543 #ifdef PAN_NONDRM_OVERLAY
544 screen->driver = panfrost_create_nondrm_driver(fd);
545 #else
546 fprintf(stderr, "Legacy (non-DRM) operation requires out-of-tree overlay\n");
547 return NULL;
548 #endif
549 }
550
551 #ifdef DUMP_PERFORMANCE_COUNTERS
552 screen->driver->allocate_slab(screen, &screen->perf_counters, 64, true, 0, 0, 0);
553 screen->driver->enable_counters(screen);
554 #endif
555
556 screen->base.destroy = panfrost_destroy_screen;
557
558 screen->base.get_name = panfrost_get_name;
559 screen->base.get_vendor = panfrost_get_vendor;
560 screen->base.get_device_vendor = panfrost_get_device_vendor;
561 screen->base.get_param = panfrost_get_param;
562 screen->base.get_shader_param = panfrost_get_shader_param;
563 screen->base.get_paramf = panfrost_get_paramf;
564 screen->base.get_timestamp = panfrost_get_timestamp;
565 screen->base.is_format_supported = panfrost_is_format_supported;
566 screen->base.context_create = panfrost_create_context;
567 screen->base.flush_frontbuffer = panfrost_flush_frontbuffer;
568 screen->base.get_compiler_options = panfrost_screen_get_compiler_options;
569 screen->base.fence_reference = panfrost_fence_reference;
570 screen->base.fence_finish = panfrost_fence_finish;
571
572 screen->last_fragment_id = -1;
573 screen->last_fragment_flushed = true;
574
575 panfrost_resource_screen_init(screen);
576
577 return &screen->base;
578 }