r600_pipe.c revision 09ec30f02830b3cbf9d6ac04d9497634dca86846
1/* 2 * Copyright 2010 Jerome Glisse <glisse@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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23#include <stdio.h> 24#include <errno.h> 25#include "pipe/p_defines.h" 26#include "pipe/p_state.h" 27#include "pipe/p_context.h" 28#include "tgsi/tgsi_scan.h" 29#include "tgsi/tgsi_parse.h" 30#include "tgsi/tgsi_util.h" 31#include "util/u_blitter.h" 32#include "util/u_double_list.h" 33#include "util/u_format.h" 34#include "util/u_format_s3tc.h" 35#include "util/u_transfer.h" 36#include "util/u_surface.h" 37#include "util/u_pack_color.h" 38#include "util/u_memory.h" 39#include "util/u_inlines.h" 40#include "util/u_upload_mgr.h" 41#include "vl/vl_decoder.h" 42#include "vl/vl_video_buffer.h" 43#include "os/os_time.h" 44#include "pipebuffer/pb_buffer.h" 45#include "r600.h" 46#include "r600d.h" 47#include "r600_resource.h" 48#include "r600_shader.h" 49#include "r600_pipe.h" 50#include "r600_hw_context_priv.h" 51 52/* 53 * pipe_context 54 */ 55static struct r600_fence *r600_create_fence(struct r600_context *rctx) 56{ 57 struct r600_screen *rscreen = rctx->screen; 58 struct r600_fence *fence = NULL; 59 60 pipe_mutex_lock(rscreen->fences.mutex); 61 62 if (!rscreen->fences.bo) { 63 /* Create the shared buffer object */ 64 rscreen->fences.bo = (struct r600_resource*) 65 pipe_buffer_create(&rscreen->screen, PIPE_BIND_CUSTOM, 66 PIPE_USAGE_STAGING, 4096); 67 if (!rscreen->fences.bo) { 68 R600_ERR("r600: failed to create bo for fence objects\n"); 69 goto out; 70 } 71 rscreen->fences.data = rctx->ws->buffer_map(rscreen->fences.bo->buf, 72 rctx->cs, 73 PIPE_TRANSFER_READ_WRITE); 74 } 75 76 if (!LIST_IS_EMPTY(&rscreen->fences.pool)) { 77 struct r600_fence *entry; 78 79 /* Try to find a freed fence that has been signalled */ 80 LIST_FOR_EACH_ENTRY(entry, &rscreen->fences.pool, head) { 81 if (rscreen->fences.data[entry->index] != 0) { 82 LIST_DELINIT(&entry->head); 83 fence = entry; 84 break; 85 } 86 } 87 } 88 89 if (!fence) { 90 /* Allocate a new fence */ 91 struct r600_fence_block *block; 92 unsigned index; 93 94 if ((rscreen->fences.next_index + 1) >= 1024) { 95 R600_ERR("r600: too many concurrent fences\n"); 96 goto out; 97 } 98 99 index = rscreen->fences.next_index++; 100 101 if (!(index % FENCE_BLOCK_SIZE)) { 102 /* Allocate a new block */ 103 block = CALLOC_STRUCT(r600_fence_block); 104 if (block == NULL) 105 goto out; 106 107 LIST_ADD(&block->head, &rscreen->fences.blocks); 108 } else { 109 block = LIST_ENTRY(struct r600_fence_block, rscreen->fences.blocks.next, head); 110 } 111 112 fence = &block->fences[index % FENCE_BLOCK_SIZE]; 113 fence->index = index; 114 } 115 116 pipe_reference_init(&fence->reference, 1); 117 118 rscreen->fences.data[fence->index] = 0; 119 r600_context_emit_fence(rctx, rscreen->fences.bo, fence->index, 1); 120 121 /* Create a dummy BO so that fence_finish without a timeout can sleep waiting for completion */ 122 fence->sleep_bo = (struct r600_resource*) 123 pipe_buffer_create(&rctx->screen->screen, PIPE_BIND_CUSTOM, 124 PIPE_USAGE_STAGING, 1); 125 /* Add the fence as a dummy relocation. */ 126 r600_context_bo_reloc(rctx, fence->sleep_bo, RADEON_USAGE_READWRITE); 127 128out: 129 pipe_mutex_unlock(rscreen->fences.mutex); 130 return fence; 131} 132 133 134void r600_flush(struct pipe_context *ctx, struct pipe_fence_handle **fence, 135 unsigned flags) 136{ 137 struct r600_context *rctx = (struct r600_context *)ctx; 138 struct r600_fence **rfence = (struct r600_fence**)fence; 139 struct pipe_query *render_cond = NULL; 140 unsigned render_cond_mode = 0; 141 142 if (rfence) 143 *rfence = r600_create_fence(rctx); 144 145 /* Disable render condition. */ 146 if (rctx->current_render_cond) { 147 render_cond = rctx->current_render_cond; 148 render_cond_mode = rctx->current_render_cond_mode; 149 ctx->render_condition(ctx, NULL, 0); 150 } 151 152 r600_context_flush(rctx, flags); 153 154 /* Re-enable render condition. */ 155 if (render_cond) { 156 ctx->render_condition(ctx, render_cond, render_cond_mode); 157 } 158} 159 160static void r600_flush_from_st(struct pipe_context *ctx, 161 struct pipe_fence_handle **fence) 162{ 163 r600_flush(ctx, fence, 0); 164} 165 166static void r600_flush_from_winsys(void *ctx, unsigned flags) 167{ 168 r600_flush((struct pipe_context*)ctx, NULL, flags); 169} 170 171static void r600_update_num_contexts(struct r600_screen *rscreen, int diff) 172{ 173 pipe_mutex_lock(rscreen->mutex_num_contexts); 174 if (diff > 0) { 175 rscreen->num_contexts++; 176 177 if (rscreen->num_contexts > 1) 178 util_slab_set_thread_safety(&rscreen->pool_buffers, 179 UTIL_SLAB_MULTITHREADED); 180 } else { 181 rscreen->num_contexts--; 182 183 if (rscreen->num_contexts <= 1) 184 util_slab_set_thread_safety(&rscreen->pool_buffers, 185 UTIL_SLAB_SINGLETHREADED); 186 } 187 pipe_mutex_unlock(rscreen->mutex_num_contexts); 188} 189 190static void r600_destroy_context(struct pipe_context *context) 191{ 192 struct r600_context *rctx = (struct r600_context *)context; 193 194 if (rctx->custom_dsa_flush) { 195 rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush); 196 } 197 util_unreference_framebuffer_state(&rctx->framebuffer); 198 199 r600_context_fini(rctx); 200 201 if (rctx->blitter) { 202 util_blitter_destroy(rctx->blitter); 203 } 204 for (int i = 0; i < R600_PIPE_NSTATES; i++) { 205 free(rctx->states[i]); 206 } 207 208 if (rctx->vbuf_mgr) { 209 u_vbuf_destroy(rctx->vbuf_mgr); 210 } 211 util_slab_destroy(&rctx->pool_transfers); 212 213 r600_update_num_contexts(rctx->screen, -1); 214 215 r600_release_command_buffer(&rctx->atom_start_cs); 216 217 if (rctx->cs) { 218 rctx->ws->cs_destroy(rctx->cs); 219 } 220 221 FREE(rctx->range); 222 FREE(rctx); 223} 224 225static struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv) 226{ 227 struct r600_context *rctx = CALLOC_STRUCT(r600_context); 228 struct r600_screen* rscreen = (struct r600_screen *)screen; 229 230 if (rctx == NULL) 231 return NULL; 232 233 util_slab_create(&rctx->pool_transfers, 234 sizeof(struct pipe_transfer), 64, 235 UTIL_SLAB_SINGLETHREADED); 236 237 r600_update_num_contexts(rscreen, 1); 238 239 rctx->context.screen = screen; 240 rctx->context.priv = priv; 241 rctx->context.destroy = r600_destroy_context; 242 rctx->context.flush = r600_flush_from_st; 243 244 /* Easy accessing of screen/winsys. */ 245 rctx->screen = rscreen; 246 rctx->ws = rscreen->ws; 247 rctx->family = rscreen->family; 248 rctx->chip_class = rscreen->chip_class; 249 250 LIST_INITHEAD(&rctx->dirty_states); 251 LIST_INITHEAD(&rctx->active_timer_queries); 252 LIST_INITHEAD(&rctx->active_nontimer_queries); 253 LIST_INITHEAD(&rctx->dirty); 254 LIST_INITHEAD(&rctx->resource_dirty); 255 LIST_INITHEAD(&rctx->enable_list); 256 257 rctx->range = CALLOC(NUM_RANGES, sizeof(struct r600_range)); 258 if (!rctx->range) 259 goto fail; 260 261 r600_init_blit_functions(rctx); 262 r600_init_query_functions(rctx); 263 r600_init_context_resource_functions(rctx); 264 r600_init_surface_functions(rctx); 265 rctx->context.draw_vbo = r600_draw_vbo; 266 267 rctx->context.create_video_decoder = vl_create_decoder; 268 rctx->context.create_video_buffer = vl_video_buffer_create; 269 270 r600_init_common_atoms(rctx); 271 272 switch (rctx->chip_class) { 273 case R600: 274 case R700: 275 r600_init_state_functions(rctx); 276 r600_init_atom_start_cs(rctx); 277 if (r600_context_init(rctx)) 278 goto fail; 279 rctx->custom_dsa_flush = r600_create_db_flush_dsa(rctx); 280 break; 281 case EVERGREEN: 282 case CAYMAN: 283 evergreen_init_state_functions(rctx); 284 evergreen_init_atom_start_cs(rctx); 285 if (evergreen_context_init(rctx)) 286 goto fail; 287 rctx->custom_dsa_flush = evergreen_create_db_flush_dsa(rctx); 288 break; 289 default: 290 R600_ERR("Unsupported chip class %d.\n", rctx->chip_class); 291 goto fail; 292 } 293 294 rctx->cs = rctx->ws->cs_create(rctx->ws); 295 rctx->ws->cs_set_flush_callback(rctx->cs, r600_flush_from_winsys, rctx); 296 r600_emit_atom(rctx, &rctx->atom_start_cs.atom); 297 298 rctx->vbuf_mgr = u_vbuf_create(&rctx->context, 1024 * 1024, 256, 299 PIPE_BIND_VERTEX_BUFFER | 300 PIPE_BIND_INDEX_BUFFER | 301 PIPE_BIND_CONSTANT_BUFFER, 302 U_VERTEX_FETCH_DWORD_ALIGNED); 303 if (!rctx->vbuf_mgr) 304 goto fail; 305 rctx->vbuf_mgr->caps.format_fixed32 = 0; 306 307 rctx->blitter = util_blitter_create(&rctx->context); 308 if (rctx->blitter == NULL) 309 goto fail; 310 311 r600_get_backend_mask(rctx); /* this emits commands and must be last */ 312 313 return &rctx->context; 314 315fail: 316 r600_destroy_context(&rctx->context); 317 return NULL; 318} 319 320/* 321 * pipe_screen 322 */ 323static const char* r600_get_vendor(struct pipe_screen* pscreen) 324{ 325 return "X.Org"; 326} 327 328static const char *r600_get_family_name(enum radeon_family family) 329{ 330 switch(family) { 331 case CHIP_R600: return "AMD R600"; 332 case CHIP_RV610: return "AMD RV610"; 333 case CHIP_RV630: return "AMD RV630"; 334 case CHIP_RV670: return "AMD RV670"; 335 case CHIP_RV620: return "AMD RV620"; 336 case CHIP_RV635: return "AMD RV635"; 337 case CHIP_RS780: return "AMD RS780"; 338 case CHIP_RS880: return "AMD RS880"; 339 case CHIP_RV770: return "AMD RV770"; 340 case CHIP_RV730: return "AMD RV730"; 341 case CHIP_RV710: return "AMD RV710"; 342 case CHIP_RV740: return "AMD RV740"; 343 case CHIP_CEDAR: return "AMD CEDAR"; 344 case CHIP_REDWOOD: return "AMD REDWOOD"; 345 case CHIP_JUNIPER: return "AMD JUNIPER"; 346 case CHIP_CYPRESS: return "AMD CYPRESS"; 347 case CHIP_HEMLOCK: return "AMD HEMLOCK"; 348 case CHIP_PALM: return "AMD PALM"; 349 case CHIP_SUMO: return "AMD SUMO"; 350 case CHIP_SUMO2: return "AMD SUMO2"; 351 case CHIP_BARTS: return "AMD BARTS"; 352 case CHIP_TURKS: return "AMD TURKS"; 353 case CHIP_CAICOS: return "AMD CAICOS"; 354 case CHIP_CAYMAN: return "AMD CAYMAN"; 355 default: return "AMD unknown"; 356 } 357} 358 359static const char* r600_get_name(struct pipe_screen* pscreen) 360{ 361 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 362 363 return r600_get_family_name(rscreen->family); 364} 365 366static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) 367{ 368 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 369 enum radeon_family family = rscreen->family; 370 371 switch (param) { 372 /* Supported features (boolean caps). */ 373 case PIPE_CAP_NPOT_TEXTURES: 374 case PIPE_CAP_TWO_SIDED_STENCIL: 375 case PIPE_CAP_DUAL_SOURCE_BLEND: 376 case PIPE_CAP_ANISOTROPIC_FILTER: 377 case PIPE_CAP_POINT_SPRITE: 378 case PIPE_CAP_OCCLUSION_QUERY: 379 case PIPE_CAP_TEXTURE_SHADOW_MAP: 380 case PIPE_CAP_TEXTURE_MIRROR_CLAMP: 381 case PIPE_CAP_BLEND_EQUATION_SEPARATE: 382 case PIPE_CAP_TEXTURE_SWIZZLE: 383 case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: 384 case PIPE_CAP_DEPTH_CLIP_DISABLE: 385 case PIPE_CAP_SHADER_STENCIL_EXPORT: 386 case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: 387 case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: 388 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: 389 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: 390 case PIPE_CAP_SM3: 391 case PIPE_CAP_SEAMLESS_CUBE_MAP: 392 case PIPE_CAP_PRIMITIVE_RESTART: 393 case PIPE_CAP_CONDITIONAL_RENDER: 394 case PIPE_CAP_TEXTURE_BARRIER: 395 case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: 396 case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: 397 return 1; 398 399 case PIPE_CAP_GLSL_FEATURE_LEVEL: 400 return debug_get_bool_option("R600_GLSL130", FALSE) ? 130 : 120; 401 402 /* Supported except the original R600. */ 403 case PIPE_CAP_INDEP_BLEND_ENABLE: 404 case PIPE_CAP_INDEP_BLEND_FUNC: 405 /* R600 doesn't support per-MRT blends */ 406 return family == CHIP_R600 ? 0 : 1; 407 408 /* Supported on Evergreen. */ 409 case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: 410 return family >= CHIP_CEDAR ? 1 : 0; 411 412 /* Unsupported features. */ 413 case PIPE_CAP_TGSI_INSTANCEID: 414 case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: 415 case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: 416 case PIPE_CAP_SCALED_RESOLVE: 417 case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS: 418 case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: 419 case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: 420 case PIPE_CAP_VERTEX_COLOR_CLAMPED: 421 return 0; 422 423 /* Stream output. */ 424 case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: 425 return rscreen->info.r600_has_streamout ? 4 : 0; 426 case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: 427 return rscreen->info.r600_has_streamout ? 1 : 0; 428 case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: 429 case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: 430 return 16*4; 431 432 /* Texturing. */ 433 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: 434 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: 435 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: 436 if (family >= CHIP_CEDAR) 437 return 15; 438 else 439 return 14; 440 case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: 441 return rscreen->info.drm_minor >= 9 ? 442 (family >= CHIP_CEDAR ? 16384 : 8192) : 0; 443 case PIPE_CAP_MAX_COMBINED_SAMPLERS: 444 return 32; 445 446 /* Render targets. */ 447 case PIPE_CAP_MAX_RENDER_TARGETS: 448 /* FIXME some r6xx are buggy and can only do 4 */ 449 return 8; 450 451 /* Timer queries, present when the clock frequency is non zero. */ 452 case PIPE_CAP_TIMER_QUERY: 453 return rscreen->info.r600_clock_crystal_freq != 0; 454 455 case PIPE_CAP_MIN_TEXEL_OFFSET: 456 return -8; 457 458 case PIPE_CAP_MAX_TEXEL_OFFSET: 459 return 7; 460 } 461 return 0; 462} 463 464static float r600_get_paramf(struct pipe_screen* pscreen, 465 enum pipe_capf param) 466{ 467 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 468 enum radeon_family family = rscreen->family; 469 470 switch (param) { 471 case PIPE_CAPF_MAX_LINE_WIDTH: 472 case PIPE_CAPF_MAX_LINE_WIDTH_AA: 473 case PIPE_CAPF_MAX_POINT_WIDTH: 474 case PIPE_CAPF_MAX_POINT_WIDTH_AA: 475 if (family >= CHIP_CEDAR) 476 return 16384.0f; 477 else 478 return 8192.0f; 479 case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY: 480 return 16.0f; 481 case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS: 482 return 16.0f; 483 case PIPE_CAPF_GUARD_BAND_LEFT: 484 case PIPE_CAPF_GUARD_BAND_TOP: 485 case PIPE_CAPF_GUARD_BAND_RIGHT: 486 case PIPE_CAPF_GUARD_BAND_BOTTOM: 487 return 0.0f; 488 } 489 return 0.0f; 490} 491 492static int r600_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enum pipe_shader_cap param) 493{ 494 switch(shader) 495 { 496 case PIPE_SHADER_FRAGMENT: 497 case PIPE_SHADER_VERTEX: 498 break; 499 case PIPE_SHADER_GEOMETRY: 500 /* TODO: support and enable geometry programs */ 501 return 0; 502 default: 503 /* TODO: support tessellation on Evergreen */ 504 return 0; 505 } 506 507 /* TODO: all these should be fixed, since r600 surely supports much more! */ 508 switch (param) { 509 case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: 510 case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: 511 case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: 512 case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: 513 return 16384; 514 case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: 515 return 8; /* FIXME */ 516 case PIPE_SHADER_CAP_MAX_INPUTS: 517 if(shader == PIPE_SHADER_FRAGMENT) 518 return 34; 519 else 520 return 32; 521 case PIPE_SHADER_CAP_MAX_TEMPS: 522 return 256; /* Max native temporaries. */ 523 case PIPE_SHADER_CAP_MAX_ADDRS: 524 /* FIXME Isn't this equal to TEMPS? */ 525 return 1; /* Max native address registers */ 526 case PIPE_SHADER_CAP_MAX_CONSTS: 527 return R600_MAX_CONST_BUFFER_SIZE; 528 case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: 529 return R600_MAX_CONST_BUFFERS-1; 530 case PIPE_SHADER_CAP_MAX_PREDS: 531 return 0; /* FIXME */ 532 case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: 533 return 1; 534 case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: 535 case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: 536 case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: 537 case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: 538 return 1; 539 case PIPE_SHADER_CAP_SUBROUTINES: 540 return 0; 541 case PIPE_SHADER_CAP_INTEGERS: 542 return 0; 543 case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: 544 return 16; 545 } 546 return 0; 547} 548 549static int r600_get_video_param(struct pipe_screen *screen, 550 enum pipe_video_profile profile, 551 enum pipe_video_cap param) 552{ 553 switch (param) { 554 case PIPE_VIDEO_CAP_SUPPORTED: 555 return vl_profile_supported(screen, profile); 556 case PIPE_VIDEO_CAP_NPOT_TEXTURES: 557 return 1; 558 case PIPE_VIDEO_CAP_MAX_WIDTH: 559 case PIPE_VIDEO_CAP_MAX_HEIGHT: 560 return vl_video_buffer_max_size(screen); 561 case PIPE_VIDEO_CAP_PREFERED_FORMAT: 562 return PIPE_FORMAT_NV12; 563 case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 564 return false; 565 case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 566 return false; 567 case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 568 return true; 569 default: 570 return 0; 571 } 572} 573 574static void r600_destroy_screen(struct pipe_screen* pscreen) 575{ 576 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 577 578 if (rscreen == NULL) 579 return; 580 581 if (rscreen->fences.bo) { 582 struct r600_fence_block *entry, *tmp; 583 584 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, &rscreen->fences.blocks, head) { 585 LIST_DEL(&entry->head); 586 FREE(entry); 587 } 588 589 rscreen->ws->buffer_unmap(rscreen->fences.bo->buf); 590 pipe_resource_reference((struct pipe_resource**)&rscreen->fences.bo, NULL); 591 } 592 pipe_mutex_destroy(rscreen->fences.mutex); 593 594 rscreen->ws->destroy(rscreen->ws); 595 596 util_slab_destroy(&rscreen->pool_buffers); 597 pipe_mutex_destroy(rscreen->mutex_num_contexts); 598 FREE(rscreen); 599} 600 601static void r600_fence_reference(struct pipe_screen *pscreen, 602 struct pipe_fence_handle **ptr, 603 struct pipe_fence_handle *fence) 604{ 605 struct r600_fence **oldf = (struct r600_fence**)ptr; 606 struct r600_fence *newf = (struct r600_fence*)fence; 607 608 if (pipe_reference(&(*oldf)->reference, &newf->reference)) { 609 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 610 pipe_mutex_lock(rscreen->fences.mutex); 611 pipe_resource_reference((struct pipe_resource**)&(*oldf)->sleep_bo, NULL); 612 LIST_ADDTAIL(&(*oldf)->head, &rscreen->fences.pool); 613 pipe_mutex_unlock(rscreen->fences.mutex); 614 } 615 616 *ptr = fence; 617} 618 619static boolean r600_fence_signalled(struct pipe_screen *pscreen, 620 struct pipe_fence_handle *fence) 621{ 622 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 623 struct r600_fence *rfence = (struct r600_fence*)fence; 624 625 return rscreen->fences.data[rfence->index]; 626} 627 628static boolean r600_fence_finish(struct pipe_screen *pscreen, 629 struct pipe_fence_handle *fence, 630 uint64_t timeout) 631{ 632 struct r600_screen *rscreen = (struct r600_screen *)pscreen; 633 struct r600_fence *rfence = (struct r600_fence*)fence; 634 int64_t start_time = 0; 635 unsigned spins = 0; 636 637 if (timeout != PIPE_TIMEOUT_INFINITE) { 638 start_time = os_time_get(); 639 640 /* Convert to microseconds. */ 641 timeout /= 1000; 642 } 643 644 while (rscreen->fences.data[rfence->index] == 0) { 645 /* Special-case infinite timeout - wait for the dummy BO to become idle */ 646 if (timeout == PIPE_TIMEOUT_INFINITE) { 647 rscreen->ws->buffer_wait(rfence->sleep_bo->buf, RADEON_USAGE_READWRITE); 648 break; 649 } 650 651 /* The dummy BO will be busy until the CS including the fence has completed, or 652 * the GPU is reset. Don't bother continuing to spin when the BO is idle. */ 653 if (!rscreen->ws->buffer_is_busy(rfence->sleep_bo->buf, RADEON_USAGE_READWRITE)) 654 break; 655 656 if (++spins % 256) 657 continue; 658#ifdef PIPE_OS_UNIX 659 sched_yield(); 660#else 661 os_time_sleep(10); 662#endif 663 if (timeout != PIPE_TIMEOUT_INFINITE && 664 os_time_get() - start_time >= timeout) { 665 break; 666 } 667 } 668 669 return rscreen->fences.data[rfence->index] != 0; 670} 671 672static int r600_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config) 673{ 674 switch ((tiling_config & 0xe) >> 1) { 675 case 0: 676 rscreen->tiling_info.num_channels = 1; 677 break; 678 case 1: 679 rscreen->tiling_info.num_channels = 2; 680 break; 681 case 2: 682 rscreen->tiling_info.num_channels = 4; 683 break; 684 case 3: 685 rscreen->tiling_info.num_channels = 8; 686 break; 687 default: 688 return -EINVAL; 689 } 690 691 switch ((tiling_config & 0x30) >> 4) { 692 case 0: 693 rscreen->tiling_info.num_banks = 4; 694 break; 695 case 1: 696 rscreen->tiling_info.num_banks = 8; 697 break; 698 default: 699 return -EINVAL; 700 701 } 702 switch ((tiling_config & 0xc0) >> 6) { 703 case 0: 704 rscreen->tiling_info.group_bytes = 256; 705 break; 706 case 1: 707 rscreen->tiling_info.group_bytes = 512; 708 break; 709 default: 710 return -EINVAL; 711 } 712 return 0; 713} 714 715static int evergreen_interpret_tiling(struct r600_screen *rscreen, uint32_t tiling_config) 716{ 717 switch (tiling_config & 0xf) { 718 case 0: 719 rscreen->tiling_info.num_channels = 1; 720 break; 721 case 1: 722 rscreen->tiling_info.num_channels = 2; 723 break; 724 case 2: 725 rscreen->tiling_info.num_channels = 4; 726 break; 727 case 3: 728 rscreen->tiling_info.num_channels = 8; 729 break; 730 default: 731 return -EINVAL; 732 } 733 734 switch ((tiling_config & 0xf0) >> 4) { 735 case 0: 736 rscreen->tiling_info.num_banks = 4; 737 break; 738 case 1: 739 rscreen->tiling_info.num_banks = 8; 740 break; 741 case 2: 742 rscreen->tiling_info.num_banks = 16; 743 break; 744 default: 745 return -EINVAL; 746 } 747 748 switch ((tiling_config & 0xf00) >> 8) { 749 case 0: 750 rscreen->tiling_info.group_bytes = 256; 751 break; 752 case 1: 753 rscreen->tiling_info.group_bytes = 512; 754 break; 755 default: 756 return -EINVAL; 757 } 758 return 0; 759} 760 761static int r600_init_tiling(struct r600_screen *rscreen) 762{ 763 uint32_t tiling_config = rscreen->info.r600_tiling_config; 764 765 /* set default group bytes, overridden by tiling info ioctl */ 766 if (rscreen->chip_class <= R700) { 767 rscreen->tiling_info.group_bytes = 256; 768 } else { 769 rscreen->tiling_info.group_bytes = 512; 770 } 771 772 if (!tiling_config) 773 return 0; 774 775 if (rscreen->chip_class <= R700) { 776 return r600_interpret_tiling(rscreen, tiling_config); 777 } else { 778 return evergreen_interpret_tiling(rscreen, tiling_config); 779 } 780} 781 782static unsigned radeon_family_from_device(unsigned device) 783{ 784 switch (device) { 785#define CHIPSET(pciid, name, family) case pciid: return CHIP_##family; 786#include "pci_ids/r600_pci_ids.h" 787#undef CHIPSET 788 default: 789 return CHIP_UNKNOWN; 790 } 791} 792 793struct pipe_screen *r600_screen_create(struct radeon_winsys *ws) 794{ 795 struct r600_screen *rscreen = CALLOC_STRUCT(r600_screen); 796 if (rscreen == NULL) { 797 return NULL; 798 } 799 800 rscreen->ws = ws; 801 ws->query_info(ws, &rscreen->info); 802 803 rscreen->family = radeon_family_from_device(rscreen->info.pci_id); 804 if (rscreen->family == CHIP_UNKNOWN) { 805 fprintf(stderr, "r600: Unknown chipset 0x%04X\n", rscreen->info.pci_id); 806 FREE(rscreen); 807 return NULL; 808 } 809 810 /* setup class */ 811 if (rscreen->family == CHIP_CAYMAN) { 812 rscreen->chip_class = CAYMAN; 813 } else if (rscreen->family >= CHIP_CEDAR) { 814 rscreen->chip_class = EVERGREEN; 815 } else if (rscreen->family >= CHIP_RV770) { 816 rscreen->chip_class = R700; 817 } else { 818 rscreen->chip_class = R600; 819 } 820 821 if (r600_init_tiling(rscreen)) { 822 FREE(rscreen); 823 return NULL; 824 } 825 826 rscreen->screen.destroy = r600_destroy_screen; 827 rscreen->screen.get_name = r600_get_name; 828 rscreen->screen.get_vendor = r600_get_vendor; 829 rscreen->screen.get_param = r600_get_param; 830 rscreen->screen.get_shader_param = r600_get_shader_param; 831 rscreen->screen.get_paramf = r600_get_paramf; 832 rscreen->screen.get_video_param = r600_get_video_param; 833 if (rscreen->chip_class >= EVERGREEN) { 834 rscreen->screen.is_format_supported = evergreen_is_format_supported; 835 } else { 836 rscreen->screen.is_format_supported = r600_is_format_supported; 837 } 838 rscreen->screen.is_video_format_supported = vl_video_buffer_is_format_supported; 839 rscreen->screen.context_create = r600_create_context; 840 rscreen->screen.fence_reference = r600_fence_reference; 841 rscreen->screen.fence_signalled = r600_fence_signalled; 842 rscreen->screen.fence_finish = r600_fence_finish; 843 r600_init_screen_resource_functions(&rscreen->screen); 844 845 util_format_s3tc_init(); 846 847 util_slab_create(&rscreen->pool_buffers, 848 sizeof(struct r600_resource), 64, 849 UTIL_SLAB_SINGLETHREADED); 850 851 pipe_mutex_init(rscreen->mutex_num_contexts); 852 853 rscreen->fences.bo = NULL; 854 rscreen->fences.data = NULL; 855 rscreen->fences.next_index = 0; 856 LIST_INITHEAD(&rscreen->fences.pool); 857 LIST_INITHEAD(&rscreen->fences.blocks); 858 pipe_mutex_init(rscreen->fences.mutex); 859 860 rscreen->use_surface_alloc = debug_get_bool_option("R600_SURF", TRUE); 861 862 return &rscreen->screen; 863} 864