radeon: Drop dri2 checks now that it's always true.
[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 <keith@tungstengraphics.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/framebuffer.h"
50 #include "main/renderbuffer.h"
51 #include "drivers/common/meta.h"
52
53 #include "vblank.h"
54
55 #include "radeon_common.h"
56 #include "radeon_bocs_wrapper.h"
57 #include "radeon_drm.h"
58 #include "radeon_queryobj.h"
59
60 /**
61 * Enable verbose debug output for emit code.
62 * 0 no output
63 * 1 most output
64 * 2 also print state alues
65 */
66 #define RADEON_CMDBUF 0
67
68 /* =============================================================
69 * Scissoring
70 */
71
72 static GLboolean intersect_rect(drm_clip_rect_t * out,
73 drm_clip_rect_t * a, drm_clip_rect_t * b)
74 {
75 *out = *a;
76 if (b->x1 > out->x1)
77 out->x1 = b->x1;
78 if (b->y1 > out->y1)
79 out->y1 = b->y1;
80 if (b->x2 < out->x2)
81 out->x2 = b->x2;
82 if (b->y2 < out->y2)
83 out->y2 = b->y2;
84 if (out->x1 >= out->x2)
85 return GL_FALSE;
86 if (out->y1 >= out->y2)
87 return GL_FALSE;
88 return GL_TRUE;
89 }
90
91 void radeonRecalcScissorRects(radeonContextPtr radeon)
92 {
93 drm_clip_rect_t *out;
94 int i;
95
96 /* Grow cliprect store?
97 */
98 if (radeon->state.scissor.numAllocedClipRects < radeon->numClipRects) {
99 while (radeon->state.scissor.numAllocedClipRects <
100 radeon->numClipRects) {
101 radeon->state.scissor.numAllocedClipRects += 1; /* zero case */
102 radeon->state.scissor.numAllocedClipRects *= 2;
103 }
104
105 if (radeon->state.scissor.pClipRects)
106 FREE(radeon->state.scissor.pClipRects);
107
108 radeon->state.scissor.pClipRects =
109 MALLOC(radeon->state.scissor.numAllocedClipRects *
110 sizeof(drm_clip_rect_t));
111
112 if (radeon->state.scissor.pClipRects == NULL) {
113 radeon->state.scissor.numAllocedClipRects = 0;
114 return;
115 }
116 }
117
118 out = radeon->state.scissor.pClipRects;
119 radeon->state.scissor.numClipRects = 0;
120
121 for (i = 0; i < radeon->numClipRects; i++) {
122 if (intersect_rect(out,
123 &radeon->pClipRects[i],
124 &radeon->state.scissor.rect)) {
125 radeon->state.scissor.numClipRects++;
126 out++;
127 }
128 }
129
130 if (radeon->vtbl.update_scissor)
131 radeon->vtbl.update_scissor(radeon->glCtx);
132 }
133
134 void radeon_get_cliprects(radeonContextPtr radeon,
135 struct drm_clip_rect **cliprects,
136 unsigned int *num_cliprects,
137 int *x_off, int *y_off)
138 {
139 __DRIdrawable *dPriv = radeon_get_drawable(radeon);
140 struct radeon_framebuffer *rfb = dPriv->driverPrivate;
141
142 if (radeon->constant_cliprect) {
143 radeon->fboRect.x1 = 0;
144 radeon->fboRect.y1 = 0;
145 radeon->fboRect.x2 = radeon->glCtx->DrawBuffer->Width;
146 radeon->fboRect.y2 = radeon->glCtx->DrawBuffer->Height;
147
148 *cliprects = &radeon->fboRect;
149 *num_cliprects = 1;
150 *x_off = 0;
151 *y_off = 0;
152 } else if (radeon->front_cliprects ||
153 rfb->pf_active || dPriv->numBackClipRects == 0) {
154 *cliprects = dPriv->pClipRects;
155 *num_cliprects = dPriv->numClipRects;
156 *x_off = dPriv->x;
157 *y_off = dPriv->y;
158 } else {
159 *num_cliprects = dPriv->numBackClipRects;
160 *cliprects = dPriv->pBackClipRects;
161 *x_off = dPriv->backX;
162 *y_off = dPriv->backY;
163 }
164 }
165
166 /**
167 * Update cliprects and scissors.
168 */
169 void radeonSetCliprects(radeonContextPtr radeon)
170 {
171 __DRIdrawable *const drawable = radeon_get_drawable(radeon);
172 __DRIdrawable *const readable = radeon_get_readable(radeon);
173
174 if(drawable == NULL && readable == NULL)
175 return;
176
177 struct radeon_framebuffer *const draw_rfb = drawable->driverPrivate;
178 struct radeon_framebuffer *const read_rfb = readable->driverPrivate;
179 int x_off, y_off;
180
181 radeon_get_cliprects(radeon, &radeon->pClipRects,
182 &radeon->numClipRects, &x_off, &y_off);
183
184 if ((draw_rfb->base.Width != drawable->w) ||
185 (draw_rfb->base.Height != drawable->h)) {
186 _mesa_resize_framebuffer(radeon->glCtx, &draw_rfb->base,
187 drawable->w, drawable->h);
188 draw_rfb->base.Initialized = GL_TRUE;
189 }
190
191 if (drawable != readable) {
192 if ((read_rfb->base.Width != readable->w) ||
193 (read_rfb->base.Height != readable->h)) {
194 _mesa_resize_framebuffer(radeon->glCtx, &read_rfb->base,
195 readable->w, readable->h);
196 read_rfb->base.Initialized = GL_TRUE;
197 }
198 }
199
200 if (radeon->state.scissor.enabled)
201 radeonRecalcScissorRects(radeon);
202
203 }
204
205
206
207 void radeonUpdateScissor( struct gl_context *ctx )
208 {
209 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
210 GLint x = ctx->Scissor.X, y = ctx->Scissor.Y;
211 GLsizei w = ctx->Scissor.Width, h = ctx->Scissor.Height;
212 int x1, y1, x2, y2;
213 int min_x, min_y, max_x, max_y;
214
215 if (!ctx->DrawBuffer)
216 return;
217 min_x = min_y = 0;
218 max_x = ctx->DrawBuffer->Width - 1;
219 max_y = ctx->DrawBuffer->Height - 1;
220
221 if ( !ctx->DrawBuffer->Name ) {
222 x1 = x;
223 y1 = ctx->DrawBuffer->Height - (y + h);
224 x2 = x + w - 1;
225 y2 = y1 + h - 1;
226 } else {
227 x1 = x;
228 y1 = y;
229 x2 = x + w - 1;
230 y2 = y + h - 1;
231
232 }
233
234 rmesa->state.scissor.rect.x1 = CLAMP(x1, min_x, max_x);
235 rmesa->state.scissor.rect.y1 = CLAMP(y1, min_y, max_y);
236 rmesa->state.scissor.rect.x2 = CLAMP(x2, min_x, max_x);
237 rmesa->state.scissor.rect.y2 = CLAMP(y2, min_y, max_y);
238
239 radeonRecalcScissorRects( rmesa );
240 }
241
242 /* =============================================================
243 * Scissoring
244 */
245
246 void radeonScissor(struct gl_context* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
247 {
248 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
249 if (ctx->Scissor.Enabled) {
250 /* We don't pipeline cliprect changes */
251 radeon_firevertices(radeon);
252 radeonUpdateScissor(ctx);
253 }
254 }
255
256 /* ================================================================
257 * SwapBuffers with client-side throttling
258 */
259
260 uint32_t radeonGetAge(radeonContextPtr radeon)
261 {
262 drm_radeon_getparam_t gp;
263 int ret;
264 uint32_t age;
265
266 gp.param = RADEON_PARAM_LAST_CLEAR;
267 gp.value = (int *)&age;
268 ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM,
269 &gp, sizeof(gp));
270 if (ret) {
271 fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__,
272 ret);
273 exit(1);
274 }
275
276 return age;
277 }
278
279 /**
280 * Check if we're about to draw into the front color buffer.
281 * If so, set the intel->front_buffer_dirty field to true.
282 */
283 void
284 radeon_check_front_buffer_rendering(struct gl_context *ctx)
285 {
286 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
287 const struct gl_framebuffer *fb = ctx->DrawBuffer;
288
289 if (fb->Name == 0) {
290 /* drawing to window system buffer */
291 if (fb->_NumColorDrawBuffers > 0) {
292 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
293 radeon->front_buffer_dirty = GL_TRUE;
294 }
295 }
296 }
297 }
298
299
300 void radeon_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
301 {
302 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
303 struct radeon_renderbuffer *rrbDepth = NULL, *rrbStencil = NULL,
304 *rrbColor = NULL;
305 uint32_t offset = 0;
306
307
308 if (!fb) {
309 /* this can happen during the initial context initialization */
310 return;
311 }
312
313 /* radeons only handle 1 color draw so far */
314 if (fb->_NumColorDrawBuffers != 1) {
315 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
316 return;
317 }
318
319 /* Do this here, note core Mesa, since this function is called from
320 * many places within the driver.
321 */
322 if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
323 /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
324 _mesa_update_framebuffer(ctx);
325 /* this updates the DrawBuffer's Width/Height if it's a FBO */
326 _mesa_update_draw_buffer_bounds(ctx);
327 }
328
329 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
330 /* this may occur when we're called by glBindFrameBuffer() during
331 * the process of someone setting up renderbuffers, etc.
332 */
333 /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
334 return;
335 }
336
337 if (fb->Name)
338 ;/* do something depthy/stencily TODO */
339
340
341 /* none */
342 if (fb->Name == 0) {
343 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
344 rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
345 radeon->front_cliprects = GL_TRUE;
346 } else {
347 rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
348 radeon->front_cliprects = GL_FALSE;
349 }
350 } else {
351 /* user FBO in theory */
352 struct radeon_renderbuffer *rrb;
353 rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[0]);
354 if (rrb) {
355 offset = rrb->draw_offset;
356 rrbColor = rrb;
357 }
358 radeon->constant_cliprect = GL_TRUE;
359 }
360
361 if (rrbColor == NULL)
362 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
363 else
364 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE);
365
366
367 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
368 rrbDepth = radeon_renderbuffer(fb->_DepthBuffer->Wrapped);
369 if (rrbDepth && rrbDepth->bo) {
370 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
371 } else {
372 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_TRUE);
373 }
374 } else {
375 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
376 rrbDepth = NULL;
377 }
378
379 if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
380 rrbStencil = radeon_renderbuffer(fb->_StencilBuffer->Wrapped);
381 if (rrbStencil && rrbStencil->bo) {
382 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
383 /* need to re-compute stencil hw state */
384 if (!rrbDepth)
385 rrbDepth = rrbStencil;
386 } else {
387 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_TRUE);
388 }
389 } else {
390 radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
391 if (ctx->Driver.Enable != NULL)
392 ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
393 else
394 ctx->NewState |= _NEW_STENCIL;
395 }
396
397 /* Update culling direction which changes depending on the
398 * orientation of the buffer:
399 */
400 if (ctx->Driver.FrontFace)
401 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
402 else
403 ctx->NewState |= _NEW_POLYGON;
404
405 /*
406 * Update depth test state
407 */
408 if (ctx->Driver.Enable) {
409 ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
410 (ctx->Depth.Test && fb->Visual.depthBits > 0));
411 /* Need to update the derived ctx->Stencil._Enabled first */
412 ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
413 (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
414 } else {
415 ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
416 }
417
418 _mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base);
419 _mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base);
420 radeon->state.color.draw_offset = offset;
421
422 #if 0
423 /* update viewport since it depends on window size */
424 if (ctx->Driver.Viewport) {
425 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
426 ctx->Viewport.Width, ctx->Viewport.Height);
427 } else {
428
429 }
430 #endif
431 ctx->NewState |= _NEW_VIEWPORT;
432
433 /* Set state we know depends on drawable parameters:
434 */
435 radeonUpdateScissor(ctx);
436 radeon->NewGLState |= _NEW_SCISSOR;
437
438 if (ctx->Driver.DepthRange)
439 ctx->Driver.DepthRange(ctx,
440 ctx->Viewport.Near,
441 ctx->Viewport.Far);
442
443 /* Update culling direction which changes depending on the
444 * orientation of the buffer:
445 */
446 if (ctx->Driver.FrontFace)
447 ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
448 else
449 ctx->NewState |= _NEW_POLYGON;
450 }
451
452 /**
453 * Called via glDrawBuffer.
454 */
455 void radeonDrawBuffer( struct gl_context *ctx, GLenum mode )
456 {
457 if (RADEON_DEBUG & RADEON_DRI)
458 fprintf(stderr, "%s %s\n", __FUNCTION__,
459 _mesa_lookup_enum_by_nr( mode ));
460
461 if (ctx->DrawBuffer->Name == 0) {
462 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
463
464 const GLboolean was_front_buffer_rendering =
465 radeon->is_front_buffer_rendering;
466
467 radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) ||
468 (mode == GL_FRONT);
469
470 /* If we weren't front-buffer rendering before but we are now, make sure
471 * that the front-buffer has actually been allocated.
472 */
473 if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) {
474 radeon_update_renderbuffers(radeon->dri.context,
475 radeon->dri.context->driDrawablePriv, GL_FALSE);
476 }
477 }
478
479 radeon_draw_buffer(ctx, ctx->DrawBuffer);
480 }
481
482 void radeonReadBuffer( struct gl_context *ctx, GLenum mode )
483 {
484 if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
485 struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
486 const GLboolean was_front_buffer_reading = rmesa->is_front_buffer_reading;
487 rmesa->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
488 || (mode == GL_FRONT);
489
490 if (!was_front_buffer_reading && rmesa->is_front_buffer_reading) {
491 radeon_update_renderbuffers(rmesa->dri.context,
492 rmesa->dri.context->driReadablePriv, GL_FALSE);
493 }
494 }
495 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
496 if (ctx->ReadBuffer == ctx->DrawBuffer) {
497 /* This will update FBO completeness status.
498 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
499 * refers to a missing renderbuffer. Calling glReadBuffer can set
500 * that straight and can make the drawing buffer complete.
501 */
502 radeon_draw_buffer(ctx, ctx->DrawBuffer);
503 }
504 }
505
506 void radeon_window_moved(radeonContextPtr radeon)
507 {
508 /* Cliprects has to be updated before doing anything else */
509 radeonSetCliprects(radeon);
510 }
511
512 void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
513 {
514 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
515 __DRIcontext *driContext = radeon->dri.context;
516 void (*old_viewport)(struct gl_context *ctx, GLint x, GLint y,
517 GLsizei w, GLsizei h);
518
519 if (!driContext->driScreenPriv->dri2.enabled)
520 return;
521
522 if (ctx->DrawBuffer->Name == 0) {
523 if (radeon->is_front_buffer_rendering) {
524 ctx->Driver.Flush(ctx);
525 }
526 radeon_update_renderbuffers(driContext, driContext->driDrawablePriv, GL_FALSE);
527 if (driContext->driDrawablePriv != driContext->driReadablePriv)
528 radeon_update_renderbuffers(driContext, driContext->driReadablePriv, GL_FALSE);
529 }
530
531 old_viewport = ctx->Driver.Viewport;
532 ctx->Driver.Viewport = NULL;
533 radeon_window_moved(radeon);
534 radeon_draw_buffer(ctx, radeon->glCtx->DrawBuffer);
535 ctx->Driver.Viewport = old_viewport;
536 }
537
538 static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state)
539 {
540 int i, j, reg, count;
541 int dwords;
542 uint32_t packet0;
543 if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) )
544 return;
545
546 dwords = (*state->check) (radeon->glCtx, state);
547
548 fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size);
549
550 if (state->cmd && radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) {
551 if (dwords > state->cmd_size)
552 dwords = state->cmd_size;
553 for (i = 0; i < dwords;) {
554 packet0 = state->cmd[i];
555 reg = (packet0 & 0x1FFF) << 2;
556 count = ((packet0 & 0x3FFF0000) >> 16) + 1;
557 fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
558 state->name, i, reg, count);
559 ++i;
560 for (j = 0; j < count && i < dwords; j++) {
561 fprintf(stderr, " %s[%d]: 0x%04x = %08x\n",
562 state->name, i, reg, state->cmd[i]);
563 reg += 4;
564 ++i;
565 }
566 }
567 }
568 }
569
570 /**
571 * Count total size for next state emit.
572 **/
573 GLuint radeonCountStateEmitSize(radeonContextPtr radeon)
574 {
575 struct radeon_state_atom *atom;
576 GLuint dwords = 0;
577 /* check if we are going to emit full state */
578
579 if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) {
580 if (!radeon->hw.is_dirty)
581 goto out;
582 foreach(atom, &radeon->hw.atomlist) {
583 if (atom->dirty) {
584 const GLuint atom_size = atom->check(radeon->glCtx, atom);
585 dwords += atom_size;
586 if (RADEON_CMDBUF && atom_size) {
587 radeon_print_state_atom(radeon, atom);
588 }
589 }
590 }
591 } else {
592 foreach(atom, &radeon->hw.atomlist) {
593 const GLuint atom_size = atom->check(radeon->glCtx, atom);
594 dwords += atom_size;
595 if (RADEON_CMDBUF && atom_size) {
596 radeon_print_state_atom(radeon, atom);
597 }
598
599 }
600 }
601 out:
602 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords);
603 return dwords;
604 }
605
606 static INLINE void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom)
607 {
608 BATCH_LOCALS(radeon);
609 int dwords;
610
611 dwords = (*atom->check) (radeon->glCtx, atom);
612 if (dwords) {
613
614 radeon_print_state_atom(radeon, atom);
615
616 if (atom->emit) {
617 (*atom->emit)(radeon->glCtx, atom);
618 } else {
619 BEGIN_BATCH_NO_AUTOSTATE(dwords);
620 OUT_BATCH_TABLE(atom->cmd, dwords);
621 END_BATCH();
622 }
623 atom->dirty = GL_FALSE;
624
625 } else {
626 radeon_print(RADEON_STATE, RADEON_VERBOSE, " skip state %s\n", atom->name);
627 }
628
629 }
630
631 static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll)
632 {
633 struct radeon_state_atom *atom;
634
635 if (radeon->vtbl.pre_emit_atoms)
636 radeon->vtbl.pre_emit_atoms(radeon);
637
638 /* Emit actual atoms */
639 if (radeon->hw.all_dirty || emitAll) {
640 foreach(atom, &radeon->hw.atomlist)
641 radeon_emit_atom( radeon, atom );
642 } else {
643 foreach(atom, &radeon->hw.atomlist) {
644 if ( atom->dirty )
645 radeon_emit_atom( radeon, atom );
646 }
647 }
648
649 COMMIT_BATCH();
650 }
651
652 static GLboolean radeon_revalidate_bos(struct gl_context *ctx)
653 {
654 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
655 int ret;
656
657 ret = radeon_cs_space_check(radeon->cmdbuf.cs);
658 if (ret == RADEON_CS_SPACE_FLUSH)
659 return GL_FALSE;
660 return GL_TRUE;
661 }
662
663 void radeonEmitState(radeonContextPtr radeon)
664 {
665 radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __FUNCTION__);
666
667 if (radeon->vtbl.pre_emit_state)
668 radeon->vtbl.pre_emit_state(radeon);
669
670 /* this code used to return here but now it emits zbs */
671 if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty)
672 return;
673
674 if (!radeon->cmdbuf.cs->cdw) {
675 if (RADEON_DEBUG & RADEON_STATE)
676 fprintf(stderr, "Begin reemit state\n");
677
678 radeonEmitAtoms(radeon, GL_TRUE);
679 } else {
680
681 if (RADEON_DEBUG & RADEON_STATE)
682 fprintf(stderr, "Begin dirty state\n");
683
684 radeonEmitAtoms(radeon, GL_FALSE);
685 }
686
687 radeon->hw.is_dirty = GL_FALSE;
688 radeon->hw.all_dirty = GL_FALSE;
689 }
690
691
692 void radeonFlush(struct gl_context *ctx)
693 {
694 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
695 if (RADEON_DEBUG & RADEON_IOCTL)
696 fprintf(stderr, "%s %d\n", __FUNCTION__, radeon->cmdbuf.cs->cdw);
697
698 /* okay if we have no cmds in the buffer &&
699 we have no DMA flush &&
700 we have no DMA buffer allocated.
701 then no point flushing anything at all.
702 */
703 if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved))
704 goto flush_front;
705
706 if (radeon->dma.flush)
707 radeon->dma.flush( ctx );
708
709 if (radeon->cmdbuf.cs->cdw)
710 rcommonFlushCmdBuf(radeon, __FUNCTION__);
711
712 flush_front:
713 if ((ctx->DrawBuffer->Name == 0) && radeon->front_buffer_dirty) {
714 __DRIscreen *const screen = radeon->radeonScreen->driScreen;
715
716 if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
717 && (screen->dri2.loader->flushFrontBuffer != NULL)) {
718 __DRIdrawable * drawable = radeon_get_drawable(radeon);
719
720 /* We set the dirty bit in radeon_prepare_render() if we're
721 * front buffer rendering once we get there.
722 */
723 radeon->front_buffer_dirty = GL_FALSE;
724
725 (*screen->dri2.loader->flushFrontBuffer)(drawable, drawable->loaderPrivate);
726 }
727 }
728 }
729
730 /* Make sure all commands have been sent to the hardware and have
731 * completed processing.
732 */
733 void radeonFinish(struct gl_context * ctx)
734 {
735 radeonContextPtr radeon = RADEON_CONTEXT(ctx);
736 struct gl_framebuffer *fb = ctx->DrawBuffer;
737 struct radeon_renderbuffer *rrb;
738 int i;
739
740 if (ctx->Driver.Flush)
741 ctx->Driver.Flush(ctx); /* +r6/r7 */
742
743 for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
744 struct radeon_renderbuffer *rrb;
745 rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]);
746 if (rrb && rrb->bo)
747 radeon_bo_wait(rrb->bo);
748 }
749 rrb = radeon_get_depthbuffer(radeon);
750 if (rrb && rrb->bo)
751 radeon_bo_wait(rrb->bo);
752 }
753
754 /* cmdbuffer */
755 /**
756 * Send the current command buffer via ioctl to the hardware.
757 */
758 int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
759 {
760 int ret = 0;
761
762 if (rmesa->cmdbuf.flushing) {
763 fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
764 exit(-1);
765 }
766 rmesa->cmdbuf.flushing = 1;
767
768 if (RADEON_DEBUG & RADEON_IOCTL) {
769 fprintf(stderr, "%s from %s - %i cliprects\n",
770 __FUNCTION__, caller, rmesa->numClipRects);
771 }
772
773 radeonEmitQueryEnd(rmesa->glCtx);
774
775 if (rmesa->cmdbuf.cs->cdw) {
776 ret = radeon_cs_emit(rmesa->cmdbuf.cs);
777 rmesa->hw.all_dirty = GL_TRUE;
778 }
779 radeon_cs_erase(rmesa->cmdbuf.cs);
780 rmesa->cmdbuf.flushing = 0;
781
782 if (radeon_revalidate_bos(rmesa->glCtx) == GL_FALSE) {
783 fprintf(stderr,"failed to revalidate buffers\n");
784 }
785
786 return ret;
787 }
788
789 int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller)
790 {
791 int ret;
792
793 radeonReleaseDmaRegions(rmesa);
794
795 ret = rcommonFlushCmdBufLocked(rmesa, caller);
796
797 if (ret) {
798 fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to "
799 "parse or rejected command stream. See dmesg "
800 "for more info.\n", ret);
801 exit(ret);
802 }
803
804 return ret;
805 }
806
807 /**
808 * Make sure that enough space is available in the command buffer
809 * by flushing if necessary.
810 *
811 * \param dwords The number of dwords we need to be free on the command buffer
812 */
813 GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
814 {
815 if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size
816 || radeon_cs_need_flush(rmesa->cmdbuf.cs)) {
817 /* If we try to flush empty buffer there is too big rendering operation. */
818 assert(rmesa->cmdbuf.cs->cdw);
819 rcommonFlushCmdBuf(rmesa, caller);
820 return GL_TRUE;
821 }
822 return GL_FALSE;
823 }
824
825 void rcommonInitCmdBuf(radeonContextPtr rmesa)
826 {
827 GLuint size;
828 struct drm_radeon_gem_info mminfo = { 0 };
829
830 /* Initialize command buffer */
831 size = 256 * driQueryOptioni(&rmesa->optionCache,
832 "command_buffer_size");
833 if (size < 2 * rmesa->hw.max_state_size) {
834 size = 2 * rmesa->hw.max_state_size + 65535;
835 }
836 if (size > 64 * 256)
837 size = 64 * 256;
838
839 radeon_print(RADEON_CS, RADEON_VERBOSE,
840 "sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t));
841 radeon_print(RADEON_CS, RADEON_VERBOSE,
842 "sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t));
843 radeon_print(RADEON_CS, RADEON_VERBOSE,
844 "Allocating %d bytes command buffer (max state is %d bytes)\n",
845 size * 4, rmesa->hw.max_state_size * 4);
846
847 rmesa->cmdbuf.csm =
848 radeon_cs_manager_gem_ctor(rmesa->radeonScreen->driScreen->fd);
849 if (rmesa->cmdbuf.csm == NULL) {
850 /* FIXME: fatal error */
851 return;
852 }
853 rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
854 assert(rmesa->cmdbuf.cs != NULL);
855 rmesa->cmdbuf.size = size;
856
857 radeon_cs_space_set_flush(rmesa->cmdbuf.cs,
858 (void (*)(void *))rmesa->glCtx->Driver.Flush, rmesa->glCtx);
859
860
861 if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO,
862 &mminfo, sizeof(mminfo))) {
863 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM,
864 mminfo.vram_visible);
865 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT,
866 mminfo.gart_size);
867 }
868 }
869
870 /**
871 * Destroy the command buffer
872 */
873 void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
874 {
875 radeon_cs_destroy(rmesa->cmdbuf.cs);
876 radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
877 }
878
879 void rcommonBeginBatch(radeonContextPtr rmesa, int n,
880 int dostate,
881 const char *file,
882 const char *function,
883 int line)
884 {
885 radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line);
886
887 radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
888 n, rmesa->cmdbuf.cs->cdw, function, line);
889
890 }
891
892 void radeonUserClear(struct gl_context *ctx, GLuint mask)
893 {
894 _mesa_meta_Clear(ctx, mask);
895 }