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  */
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 	}
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 
radeonUpdateScissor(struct gl_context * ctx)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 
radeonScissor(struct gl_context * ctx)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 
radeonGetAge(radeonContextPtr radeon)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
radeon_check_front_buffer_rendering(struct gl_context * ctx)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 
radeon_draw_buffer(struct gl_context * ctx,struct gl_framebuffer * fb)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  */
radeonDrawBuffer(struct gl_context * ctx,GLenum mode)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 
radeonReadBuffer(struct gl_context * ctx,GLenum mode)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 
radeon_window_moved(radeonContextPtr radeon)392 void radeon_window_moved(radeonContextPtr radeon)
393 {
394 	/* Cliprects has to be updated before doing anything else */
395 	radeonSetCliprects(radeon);
396 }
397 
radeon_viewport(struct gl_context * ctx)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 
radeon_print_state_atom(radeonContextPtr radeon,struct radeon_state_atom * state)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  **/
radeonCountStateEmitSize(radeonContextPtr radeon)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 
radeon_emit_atom(radeonContextPtr radeon,struct radeon_state_atom * atom)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 
radeonEmitAtoms(radeonContextPtr radeon,GLboolean emitAll)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 
radeonEmitState(radeonContextPtr radeon)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 
radeonFlush(struct gl_context * ctx)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  */
radeonFinish(struct gl_context * ctx)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  */
rcommonFlushCmdBufLocked(radeonContextPtr rmesa,const char * caller)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 
rcommonFlushCmdBuf(radeonContextPtr rmesa,const char * caller)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  */
rcommonEnsureCmdBufSpace(radeonContextPtr rmesa,int dwords,const char * caller)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 
rcommonInitCmdBuf(radeonContextPtr rmesa)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  */
rcommonDestroyCmdBuf(radeonContextPtr rmesa)739 void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
740 {
741 	radeon_cs_destroy(rmesa->cmdbuf.cs);
742 	radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
743 }
744 
rcommonBeginBatch(radeonContextPtr rmesa,int n,const char * file,const char * function,int line)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 
radeonUserClear(struct gl_context * ctx,GLuint mask)757 void radeonUserClear(struct gl_context *ctx, GLuint mask)
758 {
759    _mesa_meta_Clear(ctx, mask);
760 }
761