1cf24119d38360bfb25fa2683fe86a139826084f0Michel Dänzer/************************************************************************** 2 3Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 4 5The Weather Channel (TM) funded Tungsten Graphics to develop the 6initial release of the Radeon 8500 driver under the XFree86 license. 7This notice must be preserved. 8 9Permission is hereby granted, free of charge, to any person obtaining 10a copy of this software and associated documentation files (the 11"Software"), to deal in the Software without restriction, including 12without limitation the rights to use, copy, modify, merge, publish, 13distribute, sublicense, and/or sell copies of the Software, and to 14permit persons to whom the Software is furnished to do so, subject to 15the following conditions: 16 17The above copyright notice and this permission notice (including the 18next paragraph) shall be included in all copies or substantial 19portions of the Software. 20 21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 29**************************************************************************/ 30 31/* 32 * Authors: 33 * Keith Whitwell <keithw@vmware.com> 34 */ 35 36/* 37 - Scissor implementation 38 - buffer swap/copy ioctls 39 - finish/flush 40 - state emission 41 - cmdbuffer management 42*/ 43 44#include <errno.h> 45#include "main/glheader.h" 46#include "main/imports.h" 47#include "main/context.h" 48#include "main/enums.h" 49#include "main/fbobject.h" 50#include "main/framebuffer.h" 51#include "main/renderbuffer.h" 52#include "drivers/common/meta.h" 53 54#include "radeon_common.h" 55#include "radeon_drm.h" 56#include "radeon_queryobj.h" 57 58/** 59 * Enable verbose debug output for emit code. 60 * 0 no output 61 * 1 most output 62 * 2 also print state alues 63 */ 64#define RADEON_CMDBUF 0 65 66/* ============================================================= 67 * Scissoring 68 */ 69 70/** 71 * Update cliprects and scissors. 72 */ 73void radeonSetCliprects(radeonContextPtr radeon) 74{ 75 __DRIdrawable *const drawable = radeon_get_drawable(radeon); 76 __DRIdrawable *const readable = radeon_get_readable(radeon); 77 78 if(drawable == NULL && readable == NULL) 79 return; 80 81 struct radeon_framebuffer *const draw_rfb = drawable->driverPrivate; 82 struct radeon_framebuffer *const read_rfb = readable->driverPrivate; 83 84 if ((draw_rfb->base.Width != drawable->w) || 85 (draw_rfb->base.Height != drawable->h)) { 86 _mesa_resize_framebuffer(&radeon->glCtx, &draw_rfb->base, 87 drawable->w, drawable->h); 88 } 89 90 if (drawable != readable) { 91 if ((read_rfb->base.Width != readable->w) || 92 (read_rfb->base.Height != readable->h)) { 93 _mesa_resize_framebuffer(&radeon->glCtx, &read_rfb->base, 94 readable->w, readable->h); 95 } 96 } 97 98 if (radeon->state.scissor.enabled) 99 radeonUpdateScissor(&radeon->glCtx); 100 101} 102 103 104 105void radeonUpdateScissor( struct gl_context *ctx ) 106{ 107 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 108 GLint x = ctx->Scissor.ScissorArray[0].X, y = ctx->Scissor.ScissorArray[0].Y; 109 GLsizei w = ctx->Scissor.ScissorArray[0].Width, h = ctx->Scissor.ScissorArray[0].Height; 110 int x1, y1, x2, y2; 111 int min_x, min_y, max_x, max_y; 112 113 if (!ctx->DrawBuffer) 114 return; 115 min_x = min_y = 0; 116 max_x = ctx->DrawBuffer->Width - 1; 117 max_y = ctx->DrawBuffer->Height - 1; 118 119 if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { 120 x1 = x; 121 y1 = ctx->DrawBuffer->Height - (y + h); 122 x2 = x + w - 1; 123 y2 = y1 + h - 1; 124 } else { 125 x1 = x; 126 y1 = y; 127 x2 = x + w - 1; 128 y2 = y + h - 1; 129 130 } 131 132 rmesa->state.scissor.rect.x1 = CLAMP(x1, min_x, max_x); 133 rmesa->state.scissor.rect.y1 = CLAMP(y1, min_y, max_y); 134 rmesa->state.scissor.rect.x2 = CLAMP(x2, min_x, max_x); 135 rmesa->state.scissor.rect.y2 = CLAMP(y2, min_y, max_y); 136 137 if (rmesa->vtbl.update_scissor) 138 rmesa->vtbl.update_scissor(ctx); 139} 140 141/* ============================================================= 142 * Scissoring 143 */ 144 145void radeonScissor(struct gl_context *ctx) 146{ 147 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 148 if (ctx->Scissor.EnableFlags) { 149 /* We don't pipeline cliprect changes */ 150 radeon_firevertices(radeon); 151 radeonUpdateScissor(ctx); 152 } 153} 154 155/* ================================================================ 156 * SwapBuffers with client-side throttling 157 */ 158 159uint32_t radeonGetAge(radeonContextPtr radeon) 160{ 161 drm_radeon_getparam_t gp; 162 int ret; 163 uint32_t age; 164 165 gp.param = RADEON_PARAM_LAST_CLEAR; 166 gp.value = (int *)&age; 167 ret = drmCommandWriteRead(radeon->radeonScreen->driScreen->fd, DRM_RADEON_GETPARAM, 168 &gp, sizeof(gp)); 169 if (ret) { 170 fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __func__, 171 ret); 172 exit(1); 173 } 174 175 return age; 176} 177 178/** 179 * Check if we're about to draw into the front color buffer. 180 * If so, set the intel->front_buffer_dirty field to true. 181 */ 182void 183radeon_check_front_buffer_rendering(struct gl_context *ctx) 184{ 185 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 186 const struct gl_framebuffer *fb = ctx->DrawBuffer; 187 188 if (fb->Name == 0) { 189 /* drawing to window system buffer */ 190 if (fb->_NumColorDrawBuffers > 0) { 191 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { 192 radeon->front_buffer_dirty = GL_TRUE; 193 } 194 } 195 } 196} 197 198 199void radeon_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb) 200{ 201 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 202 struct radeon_renderbuffer *rrbDepth = NULL, *rrbStencil = NULL, 203 *rrbColor = NULL; 204 uint32_t offset = 0; 205 206 207 if (!fb) { 208 /* this can happen during the initial context initialization */ 209 return; 210 } 211 212 /* radeons only handle 1 color draw so far */ 213 if (fb->_NumColorDrawBuffers != 1) { 214 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE); 215 return; 216 } 217 218 /* Do this here, note core Mesa, since this function is called from 219 * many places within the driver. 220 */ 221 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { 222 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ 223 _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); 224 /* this updates the DrawBuffer's Width/Height if it's a FBO */ 225 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); 226 } 227 228 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 229 /* this may occur when we're called by glBindFrameBuffer() during 230 * the process of someone setting up renderbuffers, etc. 231 */ 232 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ 233 return; 234 } 235 236 if (fb->Name) { 237 ;/* do something depthy/stencily TODO */ 238 } 239 240 /* none */ 241 if (fb->Name == 0) { 242 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { 243 rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); 244 radeon->front_cliprects = GL_TRUE; 245 } else { 246 rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); 247 radeon->front_cliprects = GL_FALSE; 248 } 249 } else { 250 /* user FBO in theory */ 251 struct radeon_renderbuffer *rrb; 252 rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[0]); 253 if (rrb) { 254 offset = rrb->draw_offset; 255 rrbColor = rrb; 256 } 257 } 258 259 if (rrbColor == NULL) 260 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE); 261 else 262 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE); 263 264 265 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { 266 rrbDepth = radeon_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); 267 if (rrbDepth && rrbDepth->bo) { 268 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE); 269 } else { 270 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_TRUE); 271 } 272 } else { 273 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE); 274 rrbDepth = NULL; 275 } 276 277 if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { 278 rrbStencil = radeon_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); 279 if (rrbStencil && rrbStencil->bo) { 280 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE); 281 /* need to re-compute stencil hw state */ 282 if (!rrbDepth) 283 rrbDepth = rrbStencil; 284 } else { 285 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_TRUE); 286 } 287 } else { 288 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE); 289 if (ctx->Driver.Enable != NULL) 290 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); 291 else 292 ctx->NewState |= _NEW_STENCIL; 293 } 294 295 /* Update culling direction which changes depending on the 296 * orientation of the buffer: 297 */ 298 if (ctx->Driver.FrontFace) 299 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); 300 else 301 ctx->NewState |= _NEW_POLYGON; 302 303 /* 304 * Update depth test state 305 */ 306 if (ctx->Driver.Enable) { 307 ctx->Driver.Enable(ctx, GL_DEPTH_TEST, 308 (ctx->Depth.Test && fb->Visual.depthBits > 0)); 309 /* Need to update the derived ctx->Stencil._Enabled first */ 310 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, 311 (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0)); 312 } else { 313 ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL); 314 } 315 316 _mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base.Base); 317 _mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base.Base); 318 radeon->state.color.draw_offset = offset; 319 320 ctx->NewState |= _NEW_VIEWPORT; 321 322 /* Set state we know depends on drawable parameters: 323 */ 324 radeonUpdateScissor(ctx); 325 radeon->NewGLState |= _NEW_SCISSOR; 326 327 if (ctx->Driver.DepthRange) 328 ctx->Driver.DepthRange(ctx); 329 330 /* Update culling direction which changes depending on the 331 * orientation of the buffer: 332 */ 333 if (ctx->Driver.FrontFace) 334 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); 335 else 336 ctx->NewState |= _NEW_POLYGON; 337} 338 339/** 340 * Called via glDrawBuffer. 341 */ 342void radeonDrawBuffer( struct gl_context *ctx, GLenum mode ) 343{ 344 if (RADEON_DEBUG & RADEON_DRI) 345 fprintf(stderr, "%s %s\n", __func__, 346 _mesa_enum_to_string( mode )); 347 348 if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { 349 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 350 351 const GLboolean was_front_buffer_rendering = 352 radeon->is_front_buffer_rendering; 353 354 radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || 355 (mode == GL_FRONT); 356 357 /* If we weren't front-buffer rendering before but we are now, make sure 358 * that the front-buffer has actually been allocated. 359 */ 360 if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) { 361 radeon_update_renderbuffers(radeon->driContext, 362 radeon->driContext->driDrawablePriv, GL_FALSE); 363 } 364 } 365 366 radeon_draw_buffer(ctx, ctx->DrawBuffer); 367} 368 369void radeonReadBuffer( struct gl_context *ctx, GLenum mode ) 370{ 371 if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { 372 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); 373 const GLboolean was_front_buffer_reading = rmesa->is_front_buffer_reading; 374 rmesa->is_front_buffer_reading = (mode == GL_FRONT_LEFT) 375 || (mode == GL_FRONT); 376 377 if (!was_front_buffer_reading && rmesa->is_front_buffer_reading) { 378 radeon_update_renderbuffers(rmesa->driContext, 379 rmesa->driContext->driReadablePriv, GL_FALSE); 380 } 381 } 382 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ 383 if (ctx->ReadBuffer == ctx->DrawBuffer) { 384 /* This will update FBO completeness status. 385 * A framebuffer will be incomplete if the GL_READ_BUFFER setting 386 * refers to a missing renderbuffer. Calling glReadBuffer can set 387 * that straight and can make the drawing buffer complete. 388 */ 389 radeon_draw_buffer(ctx, ctx->DrawBuffer); 390 } 391} 392 393void radeon_window_moved(radeonContextPtr radeon) 394{ 395 /* Cliprects has to be updated before doing anything else */ 396 radeonSetCliprects(radeon); 397} 398 399void radeon_viewport(struct gl_context *ctx) 400{ 401 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 402 __DRIcontext *driContext = radeon->driContext; 403 void (*old_viewport)(struct gl_context *ctx); 404 405 if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { 406 if (radeon->is_front_buffer_rendering) { 407 ctx->Driver.Flush(ctx); 408 } 409 radeon_update_renderbuffers(driContext, driContext->driDrawablePriv, GL_FALSE); 410 if (driContext->driDrawablePriv != driContext->driReadablePriv) 411 radeon_update_renderbuffers(driContext, driContext->driReadablePriv, GL_FALSE); 412 } 413 414 old_viewport = ctx->Driver.Viewport; 415 ctx->Driver.Viewport = NULL; 416 radeon_window_moved(radeon); 417 radeon_draw_buffer(ctx, radeon->glCtx.DrawBuffer); 418 ctx->Driver.Viewport = old_viewport; 419} 420 421static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state) 422{ 423 int i, j, reg, count; 424 int dwords; 425 uint32_t packet0; 426 if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) ) 427 return; 428 429 dwords = state->check(&radeon->glCtx, state); 430 431 fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size); 432 433 if (state->cmd && radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) { 434 if (dwords > state->cmd_size) 435 dwords = state->cmd_size; 436 for (i = 0; i < dwords;) { 437 packet0 = state->cmd[i]; 438 reg = (packet0 & 0x1FFF) << 2; 439 count = ((packet0 & 0x3FFF0000) >> 16) + 1; 440 fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n", 441 state->name, i, reg, count); 442 ++i; 443 for (j = 0; j < count && i < dwords; j++) { 444 fprintf(stderr, " %s[%d]: 0x%04x = %08x\n", 445 state->name, i, reg, state->cmd[i]); 446 reg += 4; 447 ++i; 448 } 449 } 450 } 451} 452 453/** 454 * Count total size for next state emit. 455 **/ 456GLuint radeonCountStateEmitSize(radeonContextPtr radeon) 457{ 458 struct radeon_state_atom *atom; 459 GLuint dwords = 0; 460 /* check if we are going to emit full state */ 461 462 if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) { 463 if (!radeon->hw.is_dirty) 464 goto out; 465 foreach(atom, &radeon->hw.atomlist) { 466 if (atom->dirty) { 467 const GLuint atom_size = atom->check(&radeon->glCtx, atom); 468 dwords += atom_size; 469 if (RADEON_CMDBUF && atom_size) { 470 radeon_print_state_atom(radeon, atom); 471 } 472 } 473 } 474 } else { 475 foreach(atom, &radeon->hw.atomlist) { 476 const GLuint atom_size = atom->check(&radeon->glCtx, atom); 477 dwords += atom_size; 478 if (RADEON_CMDBUF && atom_size) { 479 radeon_print_state_atom(radeon, atom); 480 } 481 482 } 483 } 484out: 485 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords); 486 return dwords; 487} 488 489static inline void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom) 490{ 491 BATCH_LOCALS(radeon); 492 int dwords; 493 494 dwords = atom->check(&radeon->glCtx, atom); 495 if (dwords) { 496 497 radeon_print_state_atom(radeon, atom); 498 499 if (atom->emit) { 500 atom->emit(&radeon->glCtx, atom); 501 } else { 502 BEGIN_BATCH(dwords); 503 OUT_BATCH_TABLE(atom->cmd, dwords); 504 END_BATCH(); 505 } 506 atom->dirty = GL_FALSE; 507 508 } else { 509 radeon_print(RADEON_STATE, RADEON_VERBOSE, " skip state %s\n", atom->name); 510 } 511 512} 513 514static inline void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll) 515{ 516 struct radeon_state_atom *atom; 517 518 /* Emit actual atoms */ 519 if (radeon->hw.all_dirty || emitAll) { 520 foreach(atom, &radeon->hw.atomlist) 521 radeon_emit_atom( radeon, atom ); 522 } else { 523 foreach(atom, &radeon->hw.atomlist) { 524 if ( atom->dirty ) 525 radeon_emit_atom( radeon, atom ); 526 } 527 } 528 529 COMMIT_BATCH(); 530} 531 532void radeonEmitState(radeonContextPtr radeon) 533{ 534 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __func__); 535 536 if (radeon->vtbl.pre_emit_state) 537 radeon->vtbl.pre_emit_state(radeon); 538 539 /* this code used to return here but now it emits zbs */ 540 if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty) 541 return; 542 543 if (!radeon->cmdbuf.cs->cdw) { 544 if (RADEON_DEBUG & RADEON_STATE) 545 fprintf(stderr, "Begin reemit state\n"); 546 547 radeonEmitAtoms(radeon, GL_TRUE); 548 } else { 549 550 if (RADEON_DEBUG & RADEON_STATE) 551 fprintf(stderr, "Begin dirty state\n"); 552 553 radeonEmitAtoms(radeon, GL_FALSE); 554 } 555 556 radeon->hw.is_dirty = GL_FALSE; 557 radeon->hw.all_dirty = GL_FALSE; 558} 559 560 561void radeonFlush(struct gl_context *ctx) 562{ 563 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 564 if (RADEON_DEBUG & RADEON_IOCTL) 565 fprintf(stderr, "%s %d\n", __func__, radeon->cmdbuf.cs->cdw); 566 567 /* okay if we have no cmds in the buffer && 568 we have no DMA flush && 569 we have no DMA buffer allocated. 570 then no point flushing anything at all. 571 */ 572 if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved)) 573 goto flush_front; 574 575 if (radeon->dma.flush) 576 radeon->dma.flush( ctx ); 577 578 if (radeon->cmdbuf.cs->cdw) 579 rcommonFlushCmdBuf(radeon, __func__); 580 581flush_front: 582 if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && radeon->front_buffer_dirty) { 583 __DRIscreen *const screen = radeon->radeonScreen->driScreen; 584 585 if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2) 586 && (screen->dri2.loader->flushFrontBuffer != NULL)) { 587 __DRIdrawable * drawable = radeon_get_drawable(radeon); 588 589 /* We set the dirty bit in radeon_prepare_render() if we're 590 * front buffer rendering once we get there. 591 */ 592 radeon->front_buffer_dirty = GL_FALSE; 593 594 screen->dri2.loader->flushFrontBuffer(drawable, drawable->loaderPrivate); 595 } 596 } 597} 598 599/* Make sure all commands have been sent to the hardware and have 600 * completed processing. 601 */ 602void radeonFinish(struct gl_context * ctx) 603{ 604 radeonContextPtr radeon = RADEON_CONTEXT(ctx); 605 struct gl_framebuffer *fb = ctx->DrawBuffer; 606 struct radeon_renderbuffer *rrb; 607 int i; 608 609 if (ctx->Driver.Flush) 610 ctx->Driver.Flush(ctx); /* +r6/r7 */ 611 612 for (i = 0; i < fb->_NumColorDrawBuffers; i++) { 613 struct radeon_renderbuffer *rrb; 614 rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]); 615 if (rrb && rrb->bo) 616 radeon_bo_wait(rrb->bo); 617 } 618 rrb = radeon_get_depthbuffer(radeon); 619 if (rrb && rrb->bo) 620 radeon_bo_wait(rrb->bo); 621} 622 623/* cmdbuffer */ 624/** 625 * Send the current command buffer via ioctl to the hardware. 626 */ 627int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller) 628{ 629 int ret = 0; 630 631 if (rmesa->cmdbuf.flushing) { 632 fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n"); 633 exit(-1); 634 } 635 rmesa->cmdbuf.flushing = 1; 636 637 if (RADEON_DEBUG & RADEON_IOCTL) { 638 fprintf(stderr, "%s from %s\n", __func__, caller); 639 } 640 641 radeonEmitQueryEnd(&rmesa->glCtx); 642 643 if (rmesa->cmdbuf.cs->cdw) { 644 ret = radeon_cs_emit(rmesa->cmdbuf.cs); 645 rmesa->hw.all_dirty = GL_TRUE; 646 } 647 radeon_cs_erase(rmesa->cmdbuf.cs); 648 rmesa->cmdbuf.flushing = 0; 649 650 if (!rmesa->vtbl.revalidate_all_buffers(&rmesa->glCtx)) 651 fprintf(stderr,"failed to revalidate buffers\n"); 652 653 return ret; 654} 655 656int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller) 657{ 658 int ret; 659 660 radeonReleaseDmaRegions(rmesa); 661 662 ret = rcommonFlushCmdBufLocked(rmesa, caller); 663 664 if (ret) { 665 fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to " 666 "parse or rejected command stream. See dmesg " 667 "for more info.\n", ret); 668 exit(ret); 669 } 670 671 return ret; 672} 673 674/** 675 * Make sure that enough space is available in the command buffer 676 * by flushing if necessary. 677 * 678 * \param dwords The number of dwords we need to be free on the command buffer 679 */ 680GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller) 681{ 682 if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size 683 || radeon_cs_need_flush(rmesa->cmdbuf.cs)) { 684 /* If we try to flush empty buffer there is too big rendering operation. */ 685 assert(rmesa->cmdbuf.cs->cdw); 686 rcommonFlushCmdBuf(rmesa, caller); 687 return GL_TRUE; 688 } 689 return GL_FALSE; 690} 691 692void rcommonInitCmdBuf(radeonContextPtr rmesa) 693{ 694 GLuint size; 695 struct drm_radeon_gem_info mminfo = { 0 }; 696 int fd = rmesa->radeonScreen->driScreen->fd; 697 698 /* Initialize command buffer */ 699 size = 256 * driQueryOptioni(&rmesa->optionCache, 700 "command_buffer_size"); 701 if (size < 2 * rmesa->hw.max_state_size) { 702 size = 2 * rmesa->hw.max_state_size + 65535; 703 } 704 if (size > 64 * 256) 705 size = 64 * 256; 706 707 radeon_print(RADEON_CS, RADEON_VERBOSE, 708 "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t)); 709 radeon_print(RADEON_CS, RADEON_VERBOSE, 710 "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t)); 711 radeon_print(RADEON_CS, RADEON_VERBOSE, 712 "Allocating %d bytes command buffer (max state is %d bytes)\n", 713 size * 4, rmesa->hw.max_state_size * 4); 714 715 rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd); 716 if (rmesa->cmdbuf.csm == NULL) { 717 /* FIXME: fatal error */ 718 return; 719 } 720 rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size); 721 assert(rmesa->cmdbuf.cs != NULL); 722 rmesa->cmdbuf.size = size; 723 724 radeon_cs_space_set_flush(rmesa->cmdbuf.cs, 725 (void (*)(void *))rmesa->glCtx.Driver.Flush, &rmesa->glCtx); 726 727 728 if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, 729 &mminfo, sizeof(mminfo))) { 730 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, 731 mminfo.vram_visible); 732 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, 733 mminfo.gart_size); 734 } 735} 736 737/** 738 * Destroy the command buffer 739 */ 740void rcommonDestroyCmdBuf(radeonContextPtr rmesa) 741{ 742 radeon_cs_destroy(rmesa->cmdbuf.cs); 743 radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm); 744} 745 746void rcommonBeginBatch(radeonContextPtr rmesa, int n, 747 const char *file, 748 const char *function, 749 int line) 750{ 751 radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line); 752 753 radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n", 754 n, rmesa->cmdbuf.cs->cdw, function, line); 755 756} 757 758void radeonUserClear(struct gl_context *ctx, GLuint mask) 759{ 760 _mesa_meta_Clear(ctx, mask); 761} 762