radeon: Drop dri2 checks now that it's always true.
[profile/ivi/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 }