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