mesa: replace _mesa_update_stencil() with helper functions
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_common.c
1 /**************************************************************************
2
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH 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 */
73 void 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
105 void 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
145 void 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
159 uint32_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 */
182 void
183 radeon_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
199 void 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 ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
310 (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
311 } else {
312 ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
313 }
314
315 _mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base.Base);
316 _mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base.Base);
317 radeon->state.color.draw_offset = offset;
318
319 ctx->NewState |= _NEW_VIEWPORT;
320
321 /* Set state we know depends on drawable parameters:
322 */
323 radeonUpdateScissor(ctx);
324 radeon->NewGLState |= _NEW_SCISSOR;
325
326 if (ctx->Driver.DepthRange)
327 ctx->Driver.DepthRange(ctx);
328
329 /* Update culling direction which changes depending on the
330 * orientation of the buffer:
331 */
332 if (ctx->Driver.FrontFace)
333 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
334 else
335 ctx->NewState |= _NEW_POLYGON;
336 }
337
338 /**
339 * Called via glDrawBuffer.
340 */
341 void radeonDrawBuffer( struct gl_context *ctx, GLenum mode )
342 {
343 if (RADEON_DEBUG & RADEON_DRI)
344 fprintf(stderr, "%s %s\n", __func__,
345 _mesa_enum_to_string( mode ));
346
347 if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
348 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
349
350 const GLboolean was_front_buffer_rendering =
351 radeon->is_front_buffer_rendering;
352
353 radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) ||
354 (mode == GL_FRONT);
355
356 /* If we weren't front-buffer rendering before but we are now, make sure
357 * that the front-buffer has actually been allocated.
358 */
359 if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) {
360 radeon_update_renderbuffers(radeon->driContext,
361 radeon->driContext->driDrawablePriv, GL_FALSE);
362 }
363 }
364
365 radeon_draw_buffer(ctx, ctx->DrawBuffer);
366 }
367
368 void radeonReadBuffer( struct gl_context *ctx, GLenum mode )
369 {
370 if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
371 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
372 const GLboolean was_front_buffer_reading = rmesa->is_front_buffer_reading;
373 rmesa->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
374 || (mode == GL_FRONT);
375
376 if (!was_front_buffer_reading && rmesa->is_front_buffer_reading) {
377 radeon_update_renderbuffers(rmesa->driContext,
378 rmesa->driContext->driReadablePriv, GL_FALSE);
379 }
380 }
381 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
382 if (ctx->ReadBuffer == ctx->DrawBuffer) {
383 /* This will update FBO completeness status.
384 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
385 * refers to a missing renderbuffer. Calling glReadBuffer can set
386 * that straight and can make the drawing buffer complete.
387 */
388 radeon_draw_buffer(ctx, ctx->DrawBuffer);
389 }
390 }
391
392 void radeon_window_moved(radeonContextPtr radeon)
393 {
394 /* Cliprects has to be updated before doing anything else */
395 radeonSetCliprects(radeon);
396 }
397
398 void radeon_viewport(struct gl_context *ctx)
399 {
400 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
401 __DRIcontext *driContext = radeon->driContext;
402 void (*old_viewport)(struct gl_context *ctx);
403
404 if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
405 if (radeon->is_front_buffer_rendering) {
406 ctx->Driver.Flush(ctx);
407 }
408 radeon_update_renderbuffers(driContext, driContext->driDrawablePriv, GL_FALSE);
409 if (driContext->driDrawablePriv != driContext->driReadablePriv)
410 radeon_update_renderbuffers(driContext, driContext->driReadablePriv, GL_FALSE);
411 }
412
413 old_viewport = ctx->Driver.Viewport;
414 ctx->Driver.Viewport = NULL;
415 radeon_window_moved(radeon);
416 radeon_draw_buffer(ctx, radeon->glCtx.DrawBuffer);
417 ctx->Driver.Viewport = old_viewport;
418 }
419
420 static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state)
421 {
422 int i, j, reg, count;
423 int dwords;
424 uint32_t packet0;
425 if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) )
426 return;
427
428 dwords = state->check(&radeon->glCtx, state);
429
430 fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size);
431
432 if (state->cmd && radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) {
433 if (dwords > state->cmd_size)
434 dwords = state->cmd_size;
435 for (i = 0; i < dwords;) {
436 packet0 = state->cmd[i];
437 reg = (packet0 & 0x1FFF) << 2;
438 count = ((packet0 & 0x3FFF0000) >> 16) + 1;
439 fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
440 state->name, i, reg, count);
441 ++i;
442 for (j = 0; j < count && i < dwords; j++) {
443 fprintf(stderr, " %s[%d]: 0x%04x = %08x\n",
444 state->name, i, reg, state->cmd[i]);
445 reg += 4;
446 ++i;
447 }
448 }
449 }
450 }
451
452 /**
453 * Count total size for next state emit.
454 **/
455 GLuint radeonCountStateEmitSize(radeonContextPtr radeon)
456 {
457 struct radeon_state_atom *atom;
458 GLuint dwords = 0;
459 /* check if we are going to emit full state */
460
461 if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) {
462 if (!radeon->hw.is_dirty)
463 goto out;
464 foreach(atom, &radeon->hw.atomlist) {
465 if (atom->dirty) {
466 const GLuint atom_size = atom->check(&radeon->glCtx, atom);
467 dwords += atom_size;
468 if (RADEON_CMDBUF && atom_size) {
469 radeon_print_state_atom(radeon, atom);
470 }
471 }
472 }
473 } else {
474 foreach(atom, &radeon->hw.atomlist) {
475 const GLuint atom_size = atom->check(&radeon->glCtx, atom);
476 dwords += atom_size;
477 if (RADEON_CMDBUF && atom_size) {
478 radeon_print_state_atom(radeon, atom);
479 }
480
481 }
482 }
483 out:
484 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords);
485 return dwords;
486 }
487
488 static inline void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom)
489 {
490 BATCH_LOCALS(radeon);
491 int dwords;
492
493 dwords = atom->check(&radeon->glCtx, atom);
494 if (dwords) {
495
496 radeon_print_state_atom(radeon, atom);
497
498 if (atom->emit) {
499 atom->emit(&radeon->glCtx, atom);
500 } else {
501 BEGIN_BATCH(dwords);
502 OUT_BATCH_TABLE(atom->cmd, dwords);
503 END_BATCH();
504 }
505 atom->dirty = GL_FALSE;
506
507 } else {
508 radeon_print(RADEON_STATE, RADEON_VERBOSE, " skip state %s\n", atom->name);
509 }
510
511 }
512
513 static inline void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll)
514 {
515 struct radeon_state_atom *atom;
516
517 /* Emit actual atoms */
518 if (radeon->hw.all_dirty || emitAll) {
519 foreach(atom, &radeon->hw.atomlist)
520 radeon_emit_atom( radeon, atom );
521 } else {
522 foreach(atom, &radeon->hw.atomlist) {
523 if ( atom->dirty )
524 radeon_emit_atom( radeon, atom );
525 }
526 }
527
528 COMMIT_BATCH();
529 }
530
531 void radeonEmitState(radeonContextPtr radeon)
532 {
533 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __func__);
534
535 if (radeon->vtbl.pre_emit_state)
536 radeon->vtbl.pre_emit_state(radeon);
537
538 /* this code used to return here but now it emits zbs */
539 if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty)
540 return;
541
542 if (!radeon->cmdbuf.cs->cdw) {
543 if (RADEON_DEBUG & RADEON_STATE)
544 fprintf(stderr, "Begin reemit state\n");
545
546 radeonEmitAtoms(radeon, GL_TRUE);
547 } else {
548
549 if (RADEON_DEBUG & RADEON_STATE)
550 fprintf(stderr, "Begin dirty state\n");
551
552 radeonEmitAtoms(radeon, GL_FALSE);
553 }
554
555 radeon->hw.is_dirty = GL_FALSE;
556 radeon->hw.all_dirty = GL_FALSE;
557 }
558
559
560 void radeonFlush(struct gl_context *ctx)
561 {
562 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
563 if (RADEON_DEBUG & RADEON_IOCTL)
564 fprintf(stderr, "%s %d\n", __func__, radeon->cmdbuf.cs->cdw);
565
566 /* okay if we have no cmds in the buffer &&
567 we have no DMA flush &&
568 we have no DMA buffer allocated.
569 then no point flushing anything at all.
570 */
571 if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved))
572 goto flush_front;
573
574 if (radeon->dma.flush)
575 radeon->dma.flush( ctx );
576
577 if (radeon->cmdbuf.cs->cdw)
578 rcommonFlushCmdBuf(radeon, __func__);
579
580 flush_front:
581 if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && radeon->front_buffer_dirty) {
582 __DRIscreen *const screen = radeon->radeonScreen->driScreen;
583
584 if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
585 && (screen->dri2.loader->flushFrontBuffer != NULL)) {
586 __DRIdrawable * drawable = radeon_get_drawable(radeon);
587
588 /* We set the dirty bit in radeon_prepare_render() if we're
589 * front buffer rendering once we get there.
590 */
591 radeon->front_buffer_dirty = GL_FALSE;
592
593 screen->dri2.loader->flushFrontBuffer(drawable, drawable->loaderPrivate);
594 }
595 }
596 }
597
598 /* Make sure all commands have been sent to the hardware and have
599 * completed processing.
600 */
601 void radeonFinish(struct gl_context * ctx)
602 {
603 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
604 struct gl_framebuffer *fb = ctx->DrawBuffer;
605 struct radeon_renderbuffer *rrb;
606 int i;
607
608 if (ctx->Driver.Flush)
609 ctx->Driver.Flush(ctx); /* +r6/r7 */
610
611 for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
612 struct radeon_renderbuffer *rrb;
613 rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]);
614 if (rrb && rrb->bo)
615 radeon_bo_wait(rrb->bo);
616 }
617 rrb = radeon_get_depthbuffer(radeon);
618 if (rrb && rrb->bo)
619 radeon_bo_wait(rrb->bo);
620 }
621
622 /* cmdbuffer */
623 /**
624 * Send the current command buffer via ioctl to the hardware.
625 */
626 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
627 {
628 int ret = 0;
629
630 if (rmesa->cmdbuf.flushing) {
631 fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
632 exit(-1);
633 }
634 rmesa->cmdbuf.flushing = 1;
635
636 if (RADEON_DEBUG & RADEON_IOCTL) {
637 fprintf(stderr, "%s from %s\n", __func__, caller);
638 }
639
640 radeonEmitQueryEnd(&rmesa->glCtx);
641
642 if (rmesa->cmdbuf.cs->cdw) {
643 ret = radeon_cs_emit(rmesa->cmdbuf.cs);
644 rmesa->hw.all_dirty = GL_TRUE;
645 }
646 radeon_cs_erase(rmesa->cmdbuf.cs);
647 rmesa->cmdbuf.flushing = 0;
648
649 if (!rmesa->vtbl.revalidate_all_buffers(&rmesa->glCtx))
650 fprintf(stderr,"failed to revalidate buffers\n");
651
652 return ret;
653 }
654
655 int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller)
656 {
657 int ret;
658
659 radeonReleaseDmaRegions(rmesa);
660
661 ret = rcommonFlushCmdBufLocked(rmesa, caller);
662
663 if (ret) {
664 fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to "
665 "parse or rejected command stream. See dmesg "
666 "for more info.\n", ret);
667 exit(ret);
668 }
669
670 return ret;
671 }
672
673 /**
674 * Make sure that enough space is available in the command buffer
675 * by flushing if necessary.
676 *
677 * \param dwords The number of dwords we need to be free on the command buffer
678 */
679 GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
680 {
681 if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size
682 || radeon_cs_need_flush(rmesa->cmdbuf.cs)) {
683 /* If we try to flush empty buffer there is too big rendering operation. */
684 assert(rmesa->cmdbuf.cs->cdw);
685 rcommonFlushCmdBuf(rmesa, caller);
686 return GL_TRUE;
687 }
688 return GL_FALSE;
689 }
690
691 void rcommonInitCmdBuf(radeonContextPtr rmesa)
692 {
693 GLuint size;
694 struct drm_radeon_gem_info mminfo = { 0 };
695 int fd = rmesa->radeonScreen->driScreen->fd;
696
697 /* Initialize command buffer */
698 size = 256 * driQueryOptioni(&rmesa->optionCache,
699 "command_buffer_size");
700 if (size < 2 * rmesa->hw.max_state_size) {
701 size = 2 * rmesa->hw.max_state_size + 65535;
702 }
703 if (size > 64 * 256)
704 size = 64 * 256;
705
706 radeon_print(RADEON_CS, RADEON_VERBOSE,
707 "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t));
708 radeon_print(RADEON_CS, RADEON_VERBOSE,
709 "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t));
710 radeon_print(RADEON_CS, RADEON_VERBOSE,
711 "Allocating %d bytes command buffer (max state is %d bytes)\n",
712 size * 4, rmesa->hw.max_state_size * 4);
713
714 rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
715 if (rmesa->cmdbuf.csm == NULL) {
716 /* FIXME: fatal error */
717 return;
718 }
719 rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
720 assert(rmesa->cmdbuf.cs != NULL);
721 rmesa->cmdbuf.size = size;
722
723 radeon_cs_space_set_flush(rmesa->cmdbuf.cs,
724 (void (*)(void *))rmesa->glCtx.Driver.Flush, &rmesa->glCtx);
725
726
727 if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
728 &mminfo, sizeof(mminfo))) {
729 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM,
730 mminfo.vram_visible);
731 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT,
732 mminfo.gart_size);
733 }
734 }
735
736 /**
737 * Destroy the command buffer
738 */
739 void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
740 {
741 radeon_cs_destroy(rmesa->cmdbuf.cs);
742 radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
743 }
744
745 void rcommonBeginBatch(radeonContextPtr rmesa, int n,
746 const char *file,
747 const char *function,
748 int line)
749 {
750 radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line);
751
752 radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
753 n, rmesa->cmdbuf.cs->cdw, function, line);
754
755 }
756
757 void radeonUserClear(struct gl_context *ctx, GLuint mask)
758 {
759 _mesa_meta_Clear(ctx, mask);
760 }