1/**************************************************************************
2
3Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4
5The Weather Channel (TM) funded Tungsten Graphics to develop the
6initial release of the Radeon 8500 driver under the XFree86 license.
7This notice must be preserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH 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 */
73void 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
105void 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
145void 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
159uint32_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
178void radeon_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb)
179{
180	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
181	struct radeon_renderbuffer *rrbDepth = NULL, *rrbStencil = NULL,
182		*rrbColor = NULL;
183	uint32_t offset = 0;
184
185
186	if (!fb) {
187		/* this can happen during the initial context initialization */
188		return;
189	}
190
191	/* radeons only handle 1 color draw so far */
192	if (fb->_NumColorDrawBuffers != 1) {
193		radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
194		return;
195	}
196
197	/* Do this here, note core Mesa, since this function is called from
198	 * many places within the driver.
199	 */
200	if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
201		/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
202		_mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
203		/* this updates the DrawBuffer's Width/Height if it's a FBO */
204		_mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
205	}
206
207	if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
208		/* this may occur when we're called by glBindFrameBuffer() during
209		 * the process of someone setting up renderbuffers, etc.
210		 */
211		/*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
212		return;
213	}
214
215	if (fb->Name) {
216		;/* do something depthy/stencily TODO */
217        }
218
219		/* none */
220	if (fb->Name == 0) {
221		if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
222			rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
223			radeon->front_cliprects = GL_TRUE;
224		} else {
225			rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
226			radeon->front_cliprects = GL_FALSE;
227		}
228	} else {
229		/* user FBO in theory */
230		struct radeon_renderbuffer *rrb;
231		rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[0]);
232		if (rrb) {
233			offset = rrb->draw_offset;
234			rrbColor = rrb;
235		}
236	}
237
238	if (rrbColor == NULL)
239		radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE);
240	else
241		radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE);
242
243
244	if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
245		rrbDepth = radeon_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
246		if (rrbDepth && rrbDepth->bo) {
247			radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
248		} else {
249			radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_TRUE);
250		}
251	} else {
252		radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE);
253		rrbDepth = NULL;
254	}
255
256	if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
257		rrbStencil = radeon_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
258		if (rrbStencil && rrbStencil->bo) {
259			radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
260			/* need to re-compute stencil hw state */
261			if (!rrbDepth)
262				rrbDepth = rrbStencil;
263		} else {
264			radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_TRUE);
265		}
266	} else {
267		radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE);
268		if (ctx->Driver.Enable != NULL)
269			ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
270		else
271			ctx->NewState |= _NEW_STENCIL;
272	}
273
274	/* Update culling direction which changes depending on the
275	 * orientation of the buffer:
276	 */
277	if (ctx->Driver.FrontFace)
278		ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
279	else
280		ctx->NewState |= _NEW_POLYGON;
281
282	/*
283	 * Update depth test state
284	 */
285	if (ctx->Driver.Enable) {
286		ctx->Driver.Enable(ctx, GL_DEPTH_TEST,
287				   (ctx->Depth.Test && fb->Visual.depthBits > 0));
288		ctx->Driver.Enable(ctx, GL_STENCIL_TEST,
289				   (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0));
290	} else {
291		ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
292	}
293
294	_mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base.Base);
295	_mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base.Base);
296	radeon->state.color.draw_offset = offset;
297
298	ctx->NewState |= _NEW_VIEWPORT;
299
300	/* Set state we know depends on drawable parameters:
301	 */
302	radeonUpdateScissor(ctx);
303	radeon->NewGLState |= _NEW_SCISSOR;
304
305	if (ctx->Driver.DepthRange)
306		ctx->Driver.DepthRange(ctx);
307
308	/* Update culling direction which changes depending on the
309	 * orientation of the buffer:
310	 */
311	if (ctx->Driver.FrontFace)
312		ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
313	else
314		ctx->NewState |= _NEW_POLYGON;
315}
316
317/**
318 * Called via glDrawBuffer.
319 */
320void radeonDrawBuffer(struct gl_context *ctx)
321{
322	if (RADEON_DEBUG & RADEON_DRI)
323		fprintf(stderr, "%s\n", __func__);
324
325	if (_mesa_is_front_buffer_drawing(ctx->DrawBuffer)) {
326		radeonContextPtr radeon = RADEON_CONTEXT(ctx);
327
328		/* If we might be front-buffer rendering on this buffer for
329		 * the first time, invalidate our DRI drawable so we'll ask
330		 * for new buffers (including the fake front) before we start
331		 * rendering again.
332		 */
333		radeon_update_renderbuffers(radeon->driContext,
334					    radeon->driContext->driDrawablePriv,
335					    GL_FALSE);
336	}
337
338	radeon_draw_buffer(ctx, ctx->DrawBuffer);
339}
340
341void radeonReadBuffer( struct gl_context *ctx, GLenum mode )
342{
343	if (_mesa_is_front_buffer_reading(ctx->ReadBuffer)) {
344		struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
345		radeon_update_renderbuffers(rmesa->driContext,
346					    rmesa->driContext->driReadablePriv, GL_FALSE);
347	}
348	/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
349	if (ctx->ReadBuffer == ctx->DrawBuffer) {
350		/* This will update FBO completeness status.
351		 * A framebuffer will be incomplete if the GL_READ_BUFFER setting
352		 * refers to a missing renderbuffer.  Calling glReadBuffer can set
353		 * that straight and can make the drawing buffer complete.
354		 */
355		radeon_draw_buffer(ctx, ctx->DrawBuffer);
356	}
357}
358
359void radeon_window_moved(radeonContextPtr radeon)
360{
361	/* Cliprects has to be updated before doing anything else */
362	radeonSetCliprects(radeon);
363}
364
365void radeon_viewport(struct gl_context *ctx)
366{
367	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
368	__DRIcontext *driContext = radeon->driContext;
369	void (*old_viewport)(struct gl_context *ctx);
370
371	if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
372		if (_mesa_is_front_buffer_drawing(ctx->DrawBuffer)) {
373			ctx->Driver.Flush(ctx);
374		}
375		radeon_update_renderbuffers(driContext, driContext->driDrawablePriv, GL_FALSE);
376		if (driContext->driDrawablePriv != driContext->driReadablePriv)
377			radeon_update_renderbuffers(driContext, driContext->driReadablePriv, GL_FALSE);
378	}
379
380	old_viewport = ctx->Driver.Viewport;
381	ctx->Driver.Viewport = NULL;
382	radeon_window_moved(radeon);
383	radeon_draw_buffer(ctx, radeon->glCtx.DrawBuffer);
384	ctx->Driver.Viewport = old_viewport;
385}
386
387static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state)
388{
389	int i, j, reg, count;
390	int dwords;
391	uint32_t packet0;
392	if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) )
393		return;
394
395	dwords = state->check(&radeon->glCtx, state);
396
397	fprintf(stderr, "  emit %s %d/%d\n", state->name, dwords, state->cmd_size);
398
399	if (state->cmd && radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) {
400		if (dwords > state->cmd_size)
401			dwords = state->cmd_size;
402		for (i = 0; i < dwords;) {
403			packet0 = state->cmd[i];
404			reg = (packet0 & 0x1FFF) << 2;
405			count = ((packet0 & 0x3FFF0000) >> 16) + 1;
406			fprintf(stderr, "      %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
407					state->name, i, reg, count);
408			++i;
409			for (j = 0; j < count && i < dwords; j++) {
410				fprintf(stderr, "      %s[%d]: 0x%04x = %08x\n",
411						state->name, i, reg, state->cmd[i]);
412				reg += 4;
413				++i;
414			}
415		}
416	}
417}
418
419/**
420 * Count total size for next state emit.
421 **/
422GLuint radeonCountStateEmitSize(radeonContextPtr radeon)
423{
424	struct radeon_state_atom *atom;
425	GLuint dwords = 0;
426	/* check if we are going to emit full state */
427
428	if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) {
429		if (!radeon->hw.is_dirty)
430			goto out;
431		foreach(atom, &radeon->hw.atomlist) {
432			if (atom->dirty) {
433				const GLuint atom_size = atom->check(&radeon->glCtx, atom);
434				dwords += atom_size;
435				if (RADEON_CMDBUF && atom_size) {
436					radeon_print_state_atom(radeon, atom);
437				}
438			}
439		}
440	} else {
441		foreach(atom, &radeon->hw.atomlist) {
442			const GLuint atom_size = atom->check(&radeon->glCtx, atom);
443			dwords += atom_size;
444			if (RADEON_CMDBUF && atom_size) {
445				radeon_print_state_atom(radeon, atom);
446			}
447
448		}
449	}
450out:
451	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords);
452	return dwords;
453}
454
455static inline void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom)
456{
457	BATCH_LOCALS(radeon);
458	int dwords;
459
460	dwords = atom->check(&radeon->glCtx, atom);
461	if (dwords) {
462
463		radeon_print_state_atom(radeon, atom);
464
465		if (atom->emit) {
466			atom->emit(&radeon->glCtx, atom);
467		} else {
468			BEGIN_BATCH(dwords);
469			OUT_BATCH_TABLE(atom->cmd, dwords);
470			END_BATCH();
471		}
472		atom->dirty = GL_FALSE;
473
474	} else {
475		radeon_print(RADEON_STATE, RADEON_VERBOSE, "  skip state %s\n", atom->name);
476	}
477
478}
479
480static inline void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll)
481{
482	struct radeon_state_atom *atom;
483
484	/* Emit actual atoms */
485	if (radeon->hw.all_dirty || emitAll) {
486		foreach(atom, &radeon->hw.atomlist)
487			radeon_emit_atom( radeon, atom );
488	} else {
489		foreach(atom, &radeon->hw.atomlist) {
490			if ( atom->dirty )
491				radeon_emit_atom( radeon, atom );
492		}
493	}
494
495	COMMIT_BATCH();
496}
497
498void radeonEmitState(radeonContextPtr radeon)
499{
500	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __func__);
501
502	if (radeon->vtbl.pre_emit_state)
503		radeon->vtbl.pre_emit_state(radeon);
504
505	/* this code used to return here but now it emits zbs */
506	if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty)
507		return;
508
509	if (!radeon->cmdbuf.cs->cdw) {
510		if (RADEON_DEBUG & RADEON_STATE)
511			fprintf(stderr, "Begin reemit state\n");
512
513		radeonEmitAtoms(radeon, GL_TRUE);
514	} else {
515
516		if (RADEON_DEBUG & RADEON_STATE)
517			fprintf(stderr, "Begin dirty state\n");
518
519		radeonEmitAtoms(radeon, GL_FALSE);
520	}
521
522	radeon->hw.is_dirty = GL_FALSE;
523	radeon->hw.all_dirty = GL_FALSE;
524}
525
526
527void radeonFlush(struct gl_context *ctx)
528{
529	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
530	if (RADEON_DEBUG & RADEON_IOCTL)
531		fprintf(stderr, "%s %d\n", __func__, radeon->cmdbuf.cs->cdw);
532
533	/* okay if we have no cmds in the buffer &&
534	   we have no DMA flush &&
535	   we have no DMA buffer allocated.
536	   then no point flushing anything at all.
537	*/
538	if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved))
539		goto flush_front;
540
541	if (radeon->dma.flush)
542		radeon->dma.flush( ctx );
543
544	if (radeon->cmdbuf.cs->cdw)
545		rcommonFlushCmdBuf(radeon, __func__);
546
547flush_front:
548	if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && radeon->front_buffer_dirty) {
549		__DRIscreen *const screen = radeon->radeonScreen->driScreen;
550
551		if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
552			&& (screen->dri2.loader->flushFrontBuffer != NULL)) {
553			__DRIdrawable * drawable = radeon_get_drawable(radeon);
554
555			/* We set the dirty bit in radeon_prepare_render() if we're
556			 * front buffer rendering once we get there.
557			 */
558			radeon->front_buffer_dirty = GL_FALSE;
559
560			screen->dri2.loader->flushFrontBuffer(drawable, drawable->loaderPrivate);
561		}
562	}
563}
564
565/* Make sure all commands have been sent to the hardware and have
566 * completed processing.
567 */
568void radeonFinish(struct gl_context * ctx)
569{
570	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
571	struct gl_framebuffer *fb = ctx->DrawBuffer;
572	struct radeon_renderbuffer *rrb;
573	int i;
574
575	if (ctx->Driver.Flush)
576		ctx->Driver.Flush(ctx); /* +r6/r7 */
577
578	for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
579		struct radeon_renderbuffer *rrb;
580		rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]);
581		if (rrb && rrb->bo)
582			radeon_bo_wait(rrb->bo);
583	}
584	rrb = radeon_get_depthbuffer(radeon);
585	if (rrb && rrb->bo)
586		radeon_bo_wait(rrb->bo);
587}
588
589/* cmdbuffer */
590/**
591 * Send the current command buffer via ioctl to the hardware.
592 */
593int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
594{
595	int ret = 0;
596
597	if (rmesa->cmdbuf.flushing) {
598		fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n");
599		exit(-1);
600	}
601	rmesa->cmdbuf.flushing = 1;
602
603	if (RADEON_DEBUG & RADEON_IOCTL) {
604		fprintf(stderr, "%s from %s\n", __func__, caller);
605	}
606
607	radeonEmitQueryEnd(&rmesa->glCtx);
608
609	if (rmesa->cmdbuf.cs->cdw) {
610		ret = radeon_cs_emit(rmesa->cmdbuf.cs);
611		rmesa->hw.all_dirty = GL_TRUE;
612	}
613	radeon_cs_erase(rmesa->cmdbuf.cs);
614	rmesa->cmdbuf.flushing = 0;
615
616	if (!rmesa->vtbl.revalidate_all_buffers(&rmesa->glCtx))
617		fprintf(stderr,"failed to revalidate buffers\n");
618
619	return ret;
620}
621
622int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller)
623{
624	int ret;
625
626	radeonReleaseDmaRegions(rmesa);
627
628	ret = rcommonFlushCmdBufLocked(rmesa, caller);
629
630	if (ret) {
631		fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to "
632				"parse or rejected command stream. See dmesg "
633				"for more info.\n", ret);
634		exit(ret);
635	}
636
637	return ret;
638}
639
640/**
641 * Make sure that enough space is available in the command buffer
642 * by flushing if necessary.
643 *
644 * \param dwords The number of dwords we need to be free on the command buffer
645 */
646GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
647{
648   if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size
649	 || radeon_cs_need_flush(rmesa->cmdbuf.cs)) {
650      /* If we try to flush empty buffer there is too big rendering operation. */
651      assert(rmesa->cmdbuf.cs->cdw);
652      rcommonFlushCmdBuf(rmesa, caller);
653      return GL_TRUE;
654   }
655   return GL_FALSE;
656}
657
658void rcommonInitCmdBuf(radeonContextPtr rmesa)
659{
660	GLuint size;
661	struct drm_radeon_gem_info mminfo = { 0 };
662	int fd = rmesa->radeonScreen->driScreen->fd;
663
664	/* Initialize command buffer */
665	size = 256 * driQueryOptioni(&rmesa->optionCache,
666				     "command_buffer_size");
667	if (size < 2 * rmesa->hw.max_state_size) {
668		size = 2 * rmesa->hw.max_state_size + 65535;
669	}
670	if (size > 64 * 256)
671		size = 64 * 256;
672
673	radeon_print(RADEON_CS, RADEON_VERBOSE,
674			"sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t));
675	radeon_print(RADEON_CS, RADEON_VERBOSE,
676			"sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t));
677	radeon_print(RADEON_CS, RADEON_VERBOSE,
678			"Allocating %d bytes command buffer (max state is %d bytes)\n",
679			size * 4, rmesa->hw.max_state_size * 4);
680
681	rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
682	if (rmesa->cmdbuf.csm == NULL) {
683		/* FIXME: fatal error */
684		return;
685	}
686	rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
687	assert(rmesa->cmdbuf.cs != NULL);
688	rmesa->cmdbuf.size = size;
689
690	radeon_cs_space_set_flush(rmesa->cmdbuf.cs,
691				  (void (*)(void *))rmesa->glCtx.Driver.Flush, &rmesa->glCtx);
692
693
694	if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
695				 &mminfo, sizeof(mminfo))) {
696		radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM,
697				    mminfo.vram_visible);
698		radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT,
699				    mminfo.gart_size);
700	}
701}
702
703/**
704 * Destroy the command buffer
705 */
706void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
707{
708	radeon_cs_destroy(rmesa->cmdbuf.cs);
709	radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
710}
711
712void rcommonBeginBatch(radeonContextPtr rmesa, int n,
713		       const char *file,
714		       const char *function,
715		       int line)
716{
717	radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line);
718
719    radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n",
720                        n, rmesa->cmdbuf.cs->cdw, function, line);
721
722}
723
724void radeonUserClear(struct gl_context *ctx, GLuint mask)
725{
726   _mesa_meta_Clear(ctx, mask);
727}
728