1/* 2 * Copyright (c) 2017-2019 Lima Project 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, sub license, 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 12 * next paragraph) shall be included in all copies or substantial portions 13 * of the 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 NON-INFRINGEMENT. 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 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#include <string.h> 26 27#include "util/ralloc.h" 28#include "util/u_debug.h" 29#include "util/u_screen.h" 30#include "renderonly/renderonly.h" 31 32#include "drm-uapi/drm_fourcc.h" 33#include "drm-uapi/lima_drm.h" 34 35#include "lima_screen.h" 36#include "lima_context.h" 37#include "lima_resource.h" 38#include "lima_program.h" 39#include "lima_bo.h" 40#include "lima_fence.h" 41#include "ir/lima_ir.h" 42 43#include "xf86drm.h" 44 45static void 46lima_screen_destroy(struct pipe_screen *pscreen) 47{ 48 struct lima_screen *screen = lima_screen(pscreen); 49 50 if (lima_dump_command_stream) { 51 fclose(lima_dump_command_stream); 52 lima_dump_command_stream = NULL; 53 } 54 55 slab_destroy_parent(&screen->transfer_pool); 56 57 if (screen->ro) 58 free(screen->ro); 59 60 if (screen->pp_buffer) 61 lima_bo_free(screen->pp_buffer); 62 63 lima_bo_table_fini(screen); 64 ralloc_free(screen); 65} 66 67static const char * 68lima_screen_get_name(struct pipe_screen *pscreen) 69{ 70 struct lima_screen *screen = lima_screen(pscreen); 71 72 switch (screen->gpu_type) { 73 case DRM_LIMA_PARAM_GPU_ID_MALI400: 74 return "Mali400"; 75 case DRM_LIMA_PARAM_GPU_ID_MALI450: 76 return "Mali450"; 77 } 78 79 return NULL; 80} 81 82static const char * 83lima_screen_get_vendor(struct pipe_screen *pscreen) 84{ 85 return "lima"; 86} 87 88static const char * 89lima_screen_get_device_vendor(struct pipe_screen *pscreen) 90{ 91 return "ARM"; 92} 93 94static int 95lima_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) 96{ 97 switch (param) { 98 case PIPE_CAP_NPOT_TEXTURES: 99 case PIPE_CAP_BLEND_EQUATION_SEPARATE: 100 case PIPE_CAP_ACCELERATED: 101 case PIPE_CAP_UMA: 102 case PIPE_CAP_NATIVE_FENCE_FD: 103 return 1; 104 105 /* Unimplemented, but for exporting OpenGL 2.0 */ 106 case PIPE_CAP_OCCLUSION_QUERY: 107 case PIPE_CAP_POINT_SPRITE: 108 return 1; 109 110 /* not clear supported */ 111 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 112 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 113 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 114 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 115 return 1; 116 117 case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: 118 return 1; 119 120 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: 121 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 122 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 123 return LIMA_MAX_MIP_LEVELS; 124 125 case PIPE_CAP_VENDOR_ID: 126 return 0x13B5; 127 128 case PIPE_CAP_VIDEO_MEMORY: 129 return 0; 130 131 case PIPE_CAP_PCI_GROUP: 132 case PIPE_CAP_PCI_BUS: 133 case PIPE_CAP_PCI_DEVICE: 134 case PIPE_CAP_PCI_FUNCTION: 135 return 0; 136 137 case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: 138 return 0; 139 140 default: 141 return u_pipe_screen_get_param_defaults(pscreen, param); 142 } 143} 144 145static float 146lima_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param) 147{ 148 switch (param) { 149 case PIPE_CAPF_MAX_LINE_WIDTH: 150 case PIPE_CAPF_MAX_LINE_WIDTH_AA: 151 case PIPE_CAPF_MAX_POINT_WIDTH: 152 case PIPE_CAPF_MAX_POINT_WIDTH_AA: 153 return 255.0f; 154 case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: 155 return 16.0f; 156 case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: 157 return 16.0f; 158 159 default: 160 return 0.0f; 161 } 162} 163 164static int 165get_vertex_shader_param(struct lima_screen *screen, 166 enum pipe_shader_cap param) 167{ 168 switch (param) { 169 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 170 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 171 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 172 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 173 return 16384; /* need investigate */ 174 175 case PIPE_SHADER_CAP_MAX_INPUTS: 176 return 16; /* attributes */ 177 178 case PIPE_SHADER_CAP_MAX_OUTPUTS: 179 return LIMA_MAX_VARYING_NUM; /* varying */ 180 181 case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: 182 return 4096; /* need investigate */ 183 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 184 return 1; 185 186 case PIPE_SHADER_CAP_PREFERRED_IR: 187 return PIPE_SHADER_IR_NIR; 188 189 case PIPE_SHADER_CAP_MAX_TEMPS: 190 return 256; /* need investigate */ 191 192 default: 193 return 0; 194 } 195} 196 197static int 198get_fragment_shader_param(struct lima_screen *screen, 199 enum pipe_shader_cap param) 200{ 201 switch (param) { 202 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 203 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 204 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 205 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 206 return 16384; /* need investigate */ 207 208 case PIPE_SHADER_CAP_MAX_INPUTS: 209 return LIMA_MAX_VARYING_NUM - 1; /* varying, minus gl_Position */ 210 211 case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: 212 return 4096; /* need investigate */ 213 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 214 return 1; 215 216 case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: 217 return 16; /* need investigate */ 218 219 case PIPE_SHADER_CAP_PREFERRED_IR: 220 return PIPE_SHADER_IR_NIR; 221 222 case PIPE_SHADER_CAP_MAX_TEMPS: 223 return 256; /* need investigate */ 224 225 default: 226 return 0; 227 } 228} 229 230static int 231lima_screen_get_shader_param(struct pipe_screen *pscreen, 232 enum pipe_shader_type shader, 233 enum pipe_shader_cap param) 234{ 235 struct lima_screen *screen = lima_screen(pscreen); 236 237 switch (shader) { 238 case PIPE_SHADER_FRAGMENT: 239 return get_fragment_shader_param(screen, param); 240 case PIPE_SHADER_VERTEX: 241 return get_vertex_shader_param(screen, param); 242 243 default: 244 return 0; 245 } 246} 247 248static boolean 249lima_screen_is_format_supported(struct pipe_screen *pscreen, 250 enum pipe_format format, 251 enum pipe_texture_target target, 252 unsigned sample_count, 253 unsigned storage_sample_count, 254 unsigned usage) 255{ 256 switch (target) { 257 case PIPE_BUFFER: 258 case PIPE_TEXTURE_1D: 259 case PIPE_TEXTURE_2D: 260 break; 261 default: 262 return FALSE; 263 } 264 265 if (MAX2(1, sample_count) != MAX2(1, storage_sample_count)) 266 return false; 267 268 /* be able to support 16, now limit to 4 */ 269 if (sample_count > 1 && sample_count != 4) 270 return FALSE; 271 272 if (usage & PIPE_BIND_RENDER_TARGET) { 273 switch (format) { 274 case PIPE_FORMAT_B8G8R8A8_UNORM: 275 case PIPE_FORMAT_B8G8R8X8_UNORM: 276 case PIPE_FORMAT_R8G8B8A8_UNORM: 277 case PIPE_FORMAT_R8G8B8X8_UNORM: 278 case PIPE_FORMAT_Z16_UNORM: 279 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 280 case PIPE_FORMAT_Z24X8_UNORM: 281 break; 282 default: 283 return FALSE; 284 } 285 } 286 287 if (usage & PIPE_BIND_DEPTH_STENCIL) { 288 switch (format) { 289 case PIPE_FORMAT_Z16_UNORM: 290 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 291 case PIPE_FORMAT_Z24X8_UNORM: 292 break; 293 default: 294 return FALSE; 295 } 296 } 297 298 if (usage & PIPE_BIND_VERTEX_BUFFER) { 299 switch (format) { 300 case PIPE_FORMAT_R32G32B32_FLOAT: 301 break; 302 default: 303 return FALSE; 304 } 305 } 306 307 if (usage & PIPE_BIND_INDEX_BUFFER) { 308 switch (format) { 309 case PIPE_FORMAT_I8_UINT: 310 case PIPE_FORMAT_I16_UINT: 311 case PIPE_FORMAT_I32_UINT: 312 break; 313 default: 314 return FALSE; 315 } 316 } 317 318 if (usage & PIPE_BIND_SAMPLER_VIEW) { 319 switch (format) { 320 case PIPE_FORMAT_R8G8B8X8_UNORM: 321 case PIPE_FORMAT_R8G8B8A8_UNORM: 322 case PIPE_FORMAT_B8G8R8X8_UNORM: 323 case PIPE_FORMAT_B8G8R8A8_UNORM: 324 case PIPE_FORMAT_A8B8G8R8_SRGB: 325 case PIPE_FORMAT_B8G8R8A8_SRGB: 326 case PIPE_FORMAT_Z16_UNORM: 327 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 328 case PIPE_FORMAT_Z24X8_UNORM: 329 break; 330 default: 331 return FALSE; 332 } 333 } 334 335 return TRUE; 336} 337 338static const void * 339lima_screen_get_compiler_options(struct pipe_screen *pscreen, 340 enum pipe_shader_ir ir, 341 enum pipe_shader_type shader) 342{ 343 return lima_program_get_compiler_options(shader); 344} 345 346static bool 347lima_screen_query_info(struct lima_screen *screen) 348{ 349 struct drm_lima_get_param param; 350 351 memset(¶m, 0, sizeof(param)); 352 param.param = DRM_LIMA_PARAM_GPU_ID; 353 if (drmIoctl(screen->fd, DRM_IOCTL_LIMA_GET_PARAM, ¶m)) 354 return false; 355 356 switch (param.value) { 357 case DRM_LIMA_PARAM_GPU_ID_MALI400: 358 case DRM_LIMA_PARAM_GPU_ID_MALI450: 359 screen->gpu_type = param.value; 360 break; 361 default: 362 return false; 363 } 364 365 memset(¶m, 0, sizeof(param)); 366 param.param = DRM_LIMA_PARAM_NUM_PP; 367 if (drmIoctl(screen->fd, DRM_IOCTL_LIMA_GET_PARAM, ¶m)) 368 return false; 369 370 screen->num_pp = param.value; 371 372 return true; 373} 374 375static void 376lima_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, 377 enum pipe_format format, int max, 378 uint64_t *modifiers, 379 unsigned int *external_only, 380 int *count) 381{ 382 uint64_t available_modifiers[] = { 383 DRM_FORMAT_MOD_LINEAR, 384 }; 385 386 if (!modifiers) { 387 *count = ARRAY_SIZE(available_modifiers); 388 return; 389 } 390 391 for (int i = 0; i < *count; i++) { 392 modifiers[i] = available_modifiers[i]; 393 if (external_only) 394 external_only = false; 395 } 396} 397 398static const struct debug_named_value debug_options[] = { 399 { "gp", LIMA_DEBUG_GP, 400 "print GP shader compiler result of each stage" }, 401 { "pp", LIMA_DEBUG_PP, 402 "print PP shader compiler result of each stage" }, 403 { "dump", LIMA_DEBUG_DUMP, 404 "dump GPU command stream to $PWD/lima.dump" }, 405 { NULL } 406}; 407 408DEBUG_GET_ONCE_FLAGS_OPTION(lima_debug, "LIMA_DEBUG", debug_options, 0) 409uint32_t lima_debug; 410 411static void 412lima_screen_parse_env(void) 413{ 414 lima_debug = debug_get_option_lima_debug(); 415 416 if (lima_debug & LIMA_DEBUG_DUMP) { 417 const char *dump_command = "lima.dump"; 418 printf("lima: dump command stream to file %s\n", dump_command); 419 lima_dump_command_stream = fopen(dump_command, "w"); 420 if (!lima_dump_command_stream) 421 fprintf(stderr, "lima: fail to open command stream log file %s\n", 422 dump_command); 423 } 424 425 lima_ctx_num_plb = debug_get_num_option("LIMA_CTX_NUM_PLB", LIMA_CTX_PLB_DEF_NUM); 426 if (lima_ctx_num_plb > LIMA_CTX_PLB_MAX_NUM || 427 lima_ctx_num_plb < LIMA_CTX_PLB_MIN_NUM) { 428 fprintf(stderr, "lima: LIMA_CTX_NUM_PLB %d out of range [%d %d], " 429 "reset to default %d\n", lima_ctx_num_plb, LIMA_CTX_PLB_MIN_NUM, 430 LIMA_CTX_PLB_MAX_NUM, LIMA_CTX_PLB_DEF_NUM); 431 lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM; 432 } 433 434 lima_ppir_force_spilling = debug_get_num_option("LIMA_PPIR_FORCE_SPILLING", 0); 435 if (lima_ppir_force_spilling < 0) { 436 fprintf(stderr, "lima: LIMA_PPIR_FORCE_SPILLING %d less than 0, " 437 "reset to default 0\n", lima_ppir_force_spilling); 438 lima_ppir_force_spilling = 0; 439 } 440} 441 442struct pipe_screen * 443lima_screen_create(int fd, struct renderonly *ro) 444{ 445 struct lima_screen *screen; 446 447 screen = rzalloc(NULL, struct lima_screen); 448 if (!screen) 449 return NULL; 450 451 screen->fd = fd; 452 453 if (!lima_screen_query_info(screen)) 454 goto err_out0; 455 456 if (!lima_bo_table_init(screen)) 457 goto err_out0; 458 459 screen->pp_ra = ppir_regalloc_init(screen); 460 if (!screen->pp_ra) 461 goto err_out1; 462 463 screen->pp_buffer = lima_bo_create(screen, pp_buffer_size, 0); 464 if (!screen->pp_buffer) 465 goto err_out1; 466 467 /* fs program for clear buffer? 468 * const0 1 0 0 -1.67773, mov.v0 $0 ^const0.xxxx, stop 469 */ 470 static const uint32_t pp_clear_program[] = { 471 0x00020425, 0x0000000c, 0x01e007cf, 0xb0000000, 472 0x000005f5, 0x00000000, 0x00000000, 0x00000000, 473 }; 474 memcpy(lima_bo_map(screen->pp_buffer) + pp_clear_program_offset, 475 pp_clear_program, sizeof(pp_clear_program)); 476 477 /* copy texture to framebuffer, used to reload gpu tile buffer 478 * load.v $1 0.xy, texld_2d 0, mov.v0 $0 ^tex_sampler, sync, stop 479 */ 480 static const uint32_t pp_reload_program[] = { 481 0x000005e6, 0xf1003c20, 0x00000000, 0x39001000, 482 0x00000e4e, 0x000007cf, 0x00000000, 0x00000000, 483 }; 484 memcpy(lima_bo_map(screen->pp_buffer) + pp_reload_program_offset, 485 pp_reload_program, sizeof(pp_reload_program)); 486 487 /* 0/1/2 vertex index for reload/clear draw */ 488 static const uint8_t pp_shared_index[] = { 0, 1, 2 }; 489 memcpy(lima_bo_map(screen->pp_buffer) + pp_shared_index_offset, 490 pp_shared_index, sizeof(pp_shared_index)); 491 492 /* 4096x4096 gl pos used for partial clear */ 493 static const float pp_clear_gl_pos[] = { 494 4096, 0, 1, 1, 495 0, 0, 1, 1, 496 0, 4096, 1, 1, 497 }; 498 memcpy(lima_bo_map(screen->pp_buffer) + pp_clear_gl_pos_offset, 499 pp_clear_gl_pos, sizeof(pp_clear_gl_pos)); 500 501 /* is pp frame render state static? */ 502 uint32_t *pp_frame_rsw = lima_bo_map(screen->pp_buffer) + pp_frame_rsw_offset; 503 memset(pp_frame_rsw, 0, 0x40); 504 pp_frame_rsw[8] = 0x0000f008; 505 pp_frame_rsw[9] = screen->pp_buffer->va + pp_clear_program_offset; 506 pp_frame_rsw[13] = 0x00000100; 507 508 if (ro) { 509 screen->ro = renderonly_dup(ro); 510 if (!screen->ro) { 511 fprintf(stderr, "Failed to dup renderonly object\n"); 512 goto err_out2; 513 } 514 } 515 516 screen->base.destroy = lima_screen_destroy; 517 screen->base.get_name = lima_screen_get_name; 518 screen->base.get_vendor = lima_screen_get_vendor; 519 screen->base.get_device_vendor = lima_screen_get_device_vendor; 520 screen->base.get_param = lima_screen_get_param; 521 screen->base.get_paramf = lima_screen_get_paramf; 522 screen->base.get_shader_param = lima_screen_get_shader_param; 523 screen->base.context_create = lima_context_create; 524 screen->base.is_format_supported = lima_screen_is_format_supported; 525 screen->base.get_compiler_options = lima_screen_get_compiler_options; 526 screen->base.query_dmabuf_modifiers = lima_screen_query_dmabuf_modifiers; 527 528 lima_resource_screen_init(screen); 529 lima_fence_screen_init(screen); 530 531 slab_create_parent(&screen->transfer_pool, sizeof(struct lima_transfer), 16); 532 533 screen->refcnt = 1; 534 535 lima_screen_parse_env(); 536 537 return &screen->base; 538 539err_out2: 540 lima_bo_free(screen->pp_buffer); 541err_out1: 542 lima_bo_table_fini(screen); 543err_out0: 544 ralloc_free(screen); 545 return NULL; 546} 547