183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch/**************************************************************************
283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
383750176c3ee2cea66c8a9751271026a5901be3aBen MurdochCopyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
583750176c3ee2cea66c8a9751271026a5901be3aBen MurdochThe Weather Channel (TM) funded Tungsten Graphics to develop the
683750176c3ee2cea66c8a9751271026a5901be3aBen Murdochinitial release of the Radeon 8500 driver under the XFree86 license.
783750176c3ee2cea66c8a9751271026a5901be3aBen MurdochThis notice must be preserved.
883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
983750176c3ee2cea66c8a9751271026a5901be3aBen MurdochPermission is hereby granted, free of charge, to any person obtaining
1083750176c3ee2cea66c8a9751271026a5901be3aBen Murdocha copy of this software and associated documentation files (the
1183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch"Software"), to deal in the Software without restriction, including
1283750176c3ee2cea66c8a9751271026a5901be3aBen Murdochwithout limitation the rights to use, copy, modify, merge, publish,
1383750176c3ee2cea66c8a9751271026a5901be3aBen Murdochdistribute, sublicense, and/or sell copies of the Software, and to
1483750176c3ee2cea66c8a9751271026a5901be3aBen Murdochpermit persons to whom the Software is furnished to do so, subject to
1583750176c3ee2cea66c8a9751271026a5901be3aBen Murdochthe following conditions:
1683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
1783750176c3ee2cea66c8a9751271026a5901be3aBen MurdochThe above copyright notice and this permission notice (including the
1883750176c3ee2cea66c8a9751271026a5901be3aBen Murdochnext paragraph) shall be included in all copies or substantial
1983750176c3ee2cea66c8a9751271026a5901be3aBen Murdochportions of the Software.
2083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
2183750176c3ee2cea66c8a9751271026a5901be3aBen MurdochTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2283750176c3ee2cea66c8a9751271026a5901be3aBen MurdochEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2383750176c3ee2cea66c8a9751271026a5901be3aBen MurdochMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2483750176c3ee2cea66c8a9751271026a5901be3aBen MurdochIN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
2583750176c3ee2cea66c8a9751271026a5901be3aBen MurdochLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2683750176c3ee2cea66c8a9751271026a5901be3aBen MurdochOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2783750176c3ee2cea66c8a9751271026a5901be3aBen MurdochWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
2983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch**************************************************************************/
3083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
3183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch/*
321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) * Authors:
3383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch *   Keith Whitwell <keith@tungstengraphics.com>
345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/*
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)   - Scissor implementation
3883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch   - buffer swap/copy ioctls
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch   - finish/flush
401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)   - state emission
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)   - cmdbuffer management
4283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch*/
4383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
4483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch#include <errno.h>
4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "main/glheader.h"
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "main/imports.h"
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "main/context.h"
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "main/enums.h"
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "main/fbobject.h"
50197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "main/framebuffer.h"
51197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "main/renderbuffer.h"
52197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "drivers/common/meta.h"
53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
54197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "radeon_common.h"
55e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "radeon_drm.h"
561fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "radeon_queryobj.h"
57e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
58e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)/**
591fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch * Enable verbose debug output for emit code.
601fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch * 0 no output
61e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * 1 most output
621fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch * 2 also print state alues
63e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) */
64e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#define RADEON_CMDBUF         0
651fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
66e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)/* =============================================================
671fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch * Scissoring
681fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch */
69e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
701fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch/**
7106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) * Update cliprects and scissors.
72e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) */
73e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)void radeonSetCliprects(radeonContextPtr radeon)
7406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
75e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	__DRIdrawable *const drawable = radeon_get_drawable(radeon);
76e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	__DRIdrawable *const readable = radeon_get_readable(radeon);
77e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
785d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)	if(drawable == NULL && readable == NULL)
79e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)		return;
80e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
81e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	struct radeon_framebuffer *const draw_rfb = drawable->driverPrivate;
82e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	struct radeon_framebuffer *const read_rfb = readable->driverPrivate;
83e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
84e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	if ((draw_rfb->base.Width != drawable->w) ||
855d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)	    (draw_rfb->base.Height != drawable->h)) {
86e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)		_mesa_resize_framebuffer(radeon->glCtx, &draw_rfb->base,
87e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)					 drawable->w, drawable->h);
8806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)		draw_rfb->base.Initialized = GL_TRUE;
89e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	}
90e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
91e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	if (drawable != readable) {
92e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)		if ((read_rfb->base.Width != readable->w) ||
931fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch		    (read_rfb->base.Height != readable->h)) {
941fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch			_mesa_resize_framebuffer(radeon->glCtx, &read_rfb->base,
9583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch						 readable->w, readable->h);
9683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch			read_rfb->base.Initialized = GL_TRUE;
9783750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		}
98e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	}
99e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
100e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	if (radeon->state.scissor.enabled)
101e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)		radeonUpdateScissor(radeon->glCtx);
102e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
103e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
104e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
105e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
10643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
107aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochvoid radeonUpdateScissor( struct gl_context *ctx )
108e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
109e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
11083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	GLint x = ctx->Scissor.X, y = ctx->Scissor.Y;
11183750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	GLsizei w = ctx->Scissor.Width, h = ctx->Scissor.Height;
11283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	int x1, y1, x2, y2;
11383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	int min_x, min_y, max_x, max_y;
11483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
11543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	if (!ctx->DrawBuffer)
11683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	    return;
11783750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	min_x = min_y = 0;
1188abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)	max_x = ctx->DrawBuffer->Width - 1;
11983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	max_y = ctx->DrawBuffer->Height - 1;
12083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
121bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)	if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
122fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch		x1 = x;
123aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch		y1 = ctx->DrawBuffer->Height - (y + h);
12483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		x2 = x + w - 1;
12583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		y2 = y1 + h - 1;
1268abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)	} else {
12783750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		x1 = x;
12883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		y1 = y;
129bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)		x2 = x + w - 1;
130fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch		y2 = y + h - 1;
131aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
13283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	}
13383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
13483750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	rmesa->state.scissor.rect.x1 = CLAMP(x1,  min_x, max_x);
13583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	rmesa->state.scissor.rect.y1 = CLAMP(y1,  min_y, max_y);
13602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch	rmesa->state.scissor.rect.x2 = CLAMP(x2,  min_x, max_x);
13702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch	rmesa->state.scissor.rect.y2 = CLAMP(y2,  min_y, max_y);
13802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
13902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch	if (rmesa->vtbl.update_scissor)
14002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch	   rmesa->vtbl.update_scissor(ctx);
141e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
14202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
143e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)/* =============================================================
14402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * Scissoring
14502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch */
14683750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
14783750176c3ee2cea66c8a9751271026a5901be3aBen Murdochvoid radeonScissor(struct gl_context* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
14883750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch{
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
161uint32_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 */
184void
185radeon_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
201void 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 */
355void 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
382void 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
406void radeon_window_moved(radeonContextPtr radeon)
407{
408	/* Cliprects has to be updated before doing anything else */
409	radeonSetCliprects(radeon);
410}
411
412void 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
435static 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 **/
470GLuint 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	}
498out:
499	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords);
500	return dwords;
501}
502
503static 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
528static 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
549static 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
560void 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
589void 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
609flush_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 */
630void 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 */
655int 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
685int 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 */
709GLboolean 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
721void 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 */
769void rcommonDestroyCmdBuf(radeonContextPtr rmesa)
770{
771	radeon_cs_destroy(rmesa->cmdbuf.cs);
772	radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm);
773}
774
775void 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
788void radeonUserClear(struct gl_context *ctx, GLuint mask)
789{
790   _mesa_meta_Clear(ctx, mask);
791}
792