1/**************************************************************************
2
3Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                     VA Linux Systems Inc., Fremont, California.
5Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
6
7The Weather Channel (TM) funded Tungsten Graphics to develop the
8initial release of the Radeon 8500 driver under the XFree86 license.
9This notice must be preserved.
10
11All Rights Reserved.
12
13Permission is hereby granted, free of charge, to any person obtaining
14a copy of this software and associated documentation files (the
15"Software"), to deal in the Software without restriction, including
16without limitation the rights to use, copy, modify, merge, publish,
17distribute, sublicense, and/or sell copies of the Software, and to
18permit persons to whom the Software is furnished to do so, subject to
19the following conditions:
20
21The above copyright notice and this permission notice (including the
22next paragraph) shall be included in all copies or substantial
23portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
29LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33**************************************************************************/
34
35#include "radeon_common.h"
36#include "xmlpool.h"		/* for symbolic values of enum-type options */
37#include "utils.h"
38#include "drivers/common/meta.h"
39#include "main/context.h"
40#include "main/framebuffer.h"
41#include "main/fbobject.h"
42#include "main/renderbuffer.h"
43#include "main/state.h"
44#include "main/simple_list.h"
45#include "swrast/swrast.h"
46#include "swrast_setup/swrast_setup.h"
47#include "tnl/tnl.h"
48
49#ifndef RADEON_DEBUG
50int RADEON_DEBUG = (0);
51#endif
52
53
54static const char* get_chip_family_name(int chip_family)
55{
56	switch(chip_family) {
57#if defined(RADEON_R100)
58	case CHIP_FAMILY_R100: return "R100";
59	case CHIP_FAMILY_RV100: return "RV100";
60	case CHIP_FAMILY_RS100: return "RS100";
61	case CHIP_FAMILY_RV200: return "RV200";
62	case CHIP_FAMILY_RS200: return "RS200";
63#elif defined(RADEON_R200)
64	case CHIP_FAMILY_R200: return "R200";
65	case CHIP_FAMILY_RV250: return "RV250";
66	case CHIP_FAMILY_RS300: return "RS300";
67	case CHIP_FAMILY_RV280: return "RV280";
68#endif
69	default: return "unknown";
70	}
71}
72
73
74/* Return various strings for glGetString().
75 */
76static const GLubyte *radeonGetString(struct gl_context * ctx, GLenum name)
77{
78	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
79	static char buffer[128];
80
81	switch (name) {
82	case GL_VENDOR:
83		return (GLubyte *) "Tungsten Graphics, Inc.";
84
85	case GL_RENDERER:
86	{
87		unsigned offset;
88		GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
89			radeon->radeonScreen->AGPMode;
90		char hardwarename[32];
91
92		sprintf(hardwarename, "%s (%s %04X)",
93#if defined(RADEON_R100)
94		        "R100",
95#elif defined(RADEON_R200)
96		        "R200",
97#endif
98		        get_chip_family_name(radeon->radeonScreen->chip_family),
99		        radeon->radeonScreen->device_id);
100
101		offset = driGetRendererString(buffer, hardwarename, agp_mode);
102
103		sprintf(&buffer[offset], " %sTCL",
104			!(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
105			? "" : "NO-");
106
107		strcat(buffer, " DRI2");
108
109		return (GLubyte *) buffer;
110	}
111
112	default:
113		return NULL;
114	}
115}
116
117/* Initialize the driver's misc functions.
118 */
119static void radeonInitDriverFuncs(struct dd_function_table *functions)
120{
121	functions->GetString = radeonGetString;
122}
123
124/**
125 * Create and initialize all common fields of the context,
126 * including the Mesa context itself.
127 */
128GLboolean radeonInitContext(radeonContextPtr radeon,
129			    struct dd_function_table* functions,
130			    const struct gl_config * glVisual,
131			    __DRIcontext * driContextPriv,
132			    void *sharedContextPrivate)
133{
134	__DRIscreen *sPriv = driContextPriv->driScreenPriv;
135	radeonScreenPtr screen = (radeonScreenPtr) (sPriv->driverPrivate);
136	struct gl_context* ctx;
137	struct gl_context* shareCtx;
138	int fthrottle_mode;
139
140	/* Fill in additional standard functions. */
141	radeonInitDriverFuncs(functions);
142
143	radeon->radeonScreen = screen;
144	/* Allocate and initialize the Mesa context */
145	if (sharedContextPrivate)
146		shareCtx = ((radeonContextPtr)sharedContextPrivate)->glCtx;
147	else
148		shareCtx = NULL;
149	radeon->glCtx = _mesa_create_context(API_OPENGL, glVisual, shareCtx,
150					    functions, (void *)radeon);
151	if (!radeon->glCtx)
152		return GL_FALSE;
153
154	ctx = radeon->glCtx;
155	driContextPriv->driverPrivate = radeon;
156
157	_mesa_meta_init(ctx);
158
159	/* DRI fields */
160	radeon->dri.context = driContextPriv;
161	radeon->dri.screen = sPriv;
162	radeon->dri.fd = sPriv->fd;
163	radeon->dri.drmMinor = sPriv->drm_version.minor;
164
165	/* Setup IRQs */
166	fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode");
167	radeon->iw.irq_seq = -1;
168	radeon->irqsEmitted = 0;
169	radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS &&
170			   radeon->radeonScreen->irq);
171
172	radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
173
174	if (!radeon->do_irqs)
175		fprintf(stderr,
176			"IRQ's not enabled, falling back to %s: %d %d\n",
177			radeon->do_usleeps ? "usleeps" : "busy waits",
178			fthrottle_mode, radeon->radeonScreen->irq);
179
180        radeon->texture_depth = driQueryOptioni (&radeon->optionCache,
181					        "texture_depth");
182        if (radeon->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
183                radeon->texture_depth = ( glVisual->rgbBits > 16 ) ?
184	        DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
185
186	radeon->texture_row_align = 32;
187	radeon->texture_rect_row_align = 64;
188	radeon->texture_compressed_row_align = 32;
189
190	radeon_init_dma(radeon);
191
192	return GL_TRUE;
193}
194
195
196
197/**
198 * Destroy the command buffer and state atoms.
199 */
200static void radeon_destroy_atom_list(radeonContextPtr radeon)
201{
202	struct radeon_state_atom *atom;
203
204	foreach(atom, &radeon->hw.atomlist) {
205		FREE(atom->cmd);
206		if (atom->lastcmd)
207			FREE(atom->lastcmd);
208	}
209
210}
211
212/**
213 * Cleanup common context fields.
214 * Called by r200DestroyContext
215 */
216void radeonDestroyContext(__DRIcontext *driContextPriv )
217{
218#ifdef RADEON_BO_TRACK
219	FILE *track;
220#endif
221	GET_CURRENT_CONTEXT(ctx);
222	radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
223	radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
224
225	assert(radeon);
226
227	_mesa_meta_free(radeon->glCtx);
228
229	if (radeon == current) {
230		_mesa_make_current(NULL, NULL, NULL);
231	}
232
233	radeon_firevertices(radeon);
234	if (!is_empty_list(&radeon->dma.reserved)) {
235		rcommonFlushCmdBuf( radeon, __FUNCTION__ );
236	}
237
238	radeonFreeDmaRegions(radeon);
239	radeonReleaseArrays(radeon->glCtx, ~0);
240	if (radeon->vtbl.free_context)
241		radeon->vtbl.free_context(radeon->glCtx);
242	_swsetup_DestroyContext( radeon->glCtx );
243	_tnl_DestroyContext( radeon->glCtx );
244	_vbo_DestroyContext( radeon->glCtx );
245	_swrast_DestroyContext( radeon->glCtx );
246
247	/* free atom list */
248	/* free the Mesa context */
249	_mesa_destroy_context(radeon->glCtx);
250
251	/* _mesa_destroy_context() might result in calls to functions that
252	 * depend on the DriverCtx, so don't set it to NULL before.
253	 *
254	 * radeon->glCtx->DriverCtx = NULL;
255	 */
256	/* free the option cache */
257	driDestroyOptionCache(&radeon->optionCache);
258
259	rcommonDestroyCmdBuf(radeon);
260
261	radeon_destroy_atom_list(radeon);
262
263#ifdef RADEON_BO_TRACK
264	track = fopen("/tmp/tracklog", "w");
265	if (track) {
266		radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track);
267		fclose(track);
268	}
269#endif
270	FREE(radeon);
271}
272
273/* Force the context `c' to be unbound from its buffer.
274 */
275GLboolean radeonUnbindContext(__DRIcontext * driContextPriv)
276{
277	radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate;
278
279	if (RADEON_DEBUG & RADEON_DRI)
280		fprintf(stderr, "%s ctx %p\n", __FUNCTION__,
281			radeon->glCtx);
282
283	/* Unset current context and dispath table */
284	_mesa_make_current(NULL, NULL, NULL);
285
286	return GL_TRUE;
287}
288
289
290static unsigned
291radeon_bits_per_pixel(const struct radeon_renderbuffer *rb)
292{
293   return _mesa_get_format_bytes(rb->base.Base.Format) * 8;
294}
295
296/*
297 * Check if drawable has been invalidated by dri2InvalidateDrawable().
298 * Update renderbuffers if so. This prevents a client from accessing
299 * a backbuffer that has a swap pending but not yet completed.
300 *
301 * See intel_prepare_render for equivalent code in intel driver.
302 *
303 */
304void radeon_prepare_render(radeonContextPtr radeon)
305{
306    __DRIcontext *driContext = radeon->dri.context;
307    __DRIdrawable *drawable;
308    __DRIscreen *screen;
309
310    screen = driContext->driScreenPriv;
311    if (!screen->dri2.loader)
312        return;
313
314    drawable = driContext->driDrawablePriv;
315    if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
316	if (drawable->lastStamp != drawable->dri2.stamp)
317	    radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
318
319	/* Intel driver does the equivalent of this, no clue if it is needed:*/
320	radeon_draw_buffer(radeon->glCtx, radeon->glCtx->DrawBuffer);
321
322	driContext->dri2.draw_stamp = drawable->dri2.stamp;
323    }
324
325    drawable = driContext->driReadablePriv;
326    if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
327	if (drawable->lastStamp != drawable->dri2.stamp)
328	    radeon_update_renderbuffers(driContext, drawable, GL_FALSE);
329	driContext->dri2.read_stamp = drawable->dri2.stamp;
330    }
331
332    /* If we're currently rendering to the front buffer, the rendering
333     * that will happen next will probably dirty the front buffer.  So
334     * mark it as dirty here.
335     */
336    if (radeon->is_front_buffer_rendering)
337	radeon->front_buffer_dirty = GL_TRUE;
338}
339
340void
341radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
342			    GLboolean front_only)
343{
344	unsigned int attachments[10];
345	__DRIbuffer *buffers = NULL;
346	__DRIscreen *screen;
347	struct radeon_renderbuffer *rb;
348	int i, count;
349	struct radeon_framebuffer *draw;
350	radeonContextPtr radeon;
351	char *regname;
352	struct radeon_bo *depth_bo = NULL, *bo;
353
354	if (RADEON_DEBUG & RADEON_DRI)
355	    fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
356
357	draw = drawable->driverPrivate;
358	screen = context->driScreenPriv;
359	radeon = (radeonContextPtr) context->driverPrivate;
360
361	/* Set this up front, so that in case our buffers get invalidated
362	 * while we're getting new buffers, we don't clobber the stamp and
363	 * thus ignore the invalidate. */
364	drawable->lastStamp = drawable->dri2.stamp;
365
366	if (screen->dri2.loader
367	   && (screen->dri2.loader->base.version > 2)
368	   && (screen->dri2.loader->getBuffersWithFormat != NULL)) {
369		struct radeon_renderbuffer *depth_rb;
370		struct radeon_renderbuffer *stencil_rb;
371
372		i = 0;
373		if ((front_only || radeon->is_front_buffer_rendering ||
374		     radeon->is_front_buffer_reading ||
375		     !draw->color_rb[1])
376		    && draw->color_rb[0]) {
377			attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
378			attachments[i++] = radeon_bits_per_pixel(draw->color_rb[0]);
379		}
380
381		if (!front_only) {
382			if (draw->color_rb[1]) {
383				attachments[i++] = __DRI_BUFFER_BACK_LEFT;
384				attachments[i++] = radeon_bits_per_pixel(draw->color_rb[1]);
385			}
386
387			depth_rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
388			stencil_rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
389
390			if ((depth_rb != NULL) && (stencil_rb != NULL)) {
391				attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
392				attachments[i++] = radeon_bits_per_pixel(depth_rb);
393			} else if (depth_rb != NULL) {
394				attachments[i++] = __DRI_BUFFER_DEPTH;
395				attachments[i++] = radeon_bits_per_pixel(depth_rb);
396			} else if (stencil_rb != NULL) {
397				attachments[i++] = __DRI_BUFFER_STENCIL;
398				attachments[i++] = radeon_bits_per_pixel(stencil_rb);
399			}
400		}
401
402		buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable,
403								&drawable->w,
404								&drawable->h,
405								attachments, i / 2,
406								&count,
407								drawable->loaderPrivate);
408	} else if (screen->dri2.loader) {
409		i = 0;
410		if (draw->color_rb[0])
411			attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
412		if (!front_only) {
413			if (draw->color_rb[1])
414				attachments[i++] = __DRI_BUFFER_BACK_LEFT;
415			if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH))
416				attachments[i++] = __DRI_BUFFER_DEPTH;
417			if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL))
418				attachments[i++] = __DRI_BUFFER_STENCIL;
419		}
420
421		buffers = (*screen->dri2.loader->getBuffers)(drawable,
422								 &drawable->w,
423								 &drawable->h,
424								 attachments, i,
425								 &count,
426								 drawable->loaderPrivate);
427	}
428
429	if (buffers == NULL)
430		return;
431
432	for (i = 0; i < count; i++) {
433		switch (buffers[i].attachment) {
434		case __DRI_BUFFER_FRONT_LEFT:
435			rb = draw->color_rb[0];
436			regname = "dri2 front buffer";
437			break;
438		case __DRI_BUFFER_FAKE_FRONT_LEFT:
439			rb = draw->color_rb[0];
440			regname = "dri2 fake front buffer";
441			break;
442		case __DRI_BUFFER_BACK_LEFT:
443			rb = draw->color_rb[1];
444			regname = "dri2 back buffer";
445			break;
446		case __DRI_BUFFER_DEPTH:
447			rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
448			regname = "dri2 depth buffer";
449			break;
450		case __DRI_BUFFER_DEPTH_STENCIL:
451			rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH);
452			regname = "dri2 depth / stencil buffer";
453			break;
454		case __DRI_BUFFER_STENCIL:
455			rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
456			regname = "dri2 stencil buffer";
457			break;
458		case __DRI_BUFFER_ACCUM:
459		default:
460			fprintf(stderr,
461				"unhandled buffer attach event, attacment type %d\n",
462				buffers[i].attachment);
463			return;
464		}
465
466		if (rb == NULL)
467			continue;
468
469		if (rb->bo) {
470			uint32_t name = radeon_gem_name_bo(rb->bo);
471			if (name == buffers[i].name)
472				continue;
473		}
474
475		if (RADEON_DEBUG & RADEON_DRI)
476			fprintf(stderr,
477				"attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
478				regname, buffers[i].name, buffers[i].attachment,
479				buffers[i].cpp, buffers[i].pitch);
480
481		rb->cpp = buffers[i].cpp;
482		rb->pitch = buffers[i].pitch;
483		rb->base.Base.Width = drawable->w;
484		rb->base.Base.Height = drawable->h;
485		rb->has_surface = 0;
486
487		if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_bo) {
488			if (RADEON_DEBUG & RADEON_DRI)
489				fprintf(stderr, "(reusing depth buffer as stencil)\n");
490			bo = depth_bo;
491			radeon_bo_ref(bo);
492		} else {
493			uint32_t tiling_flags = 0, pitch = 0;
494			int ret;
495
496			bo = radeon_bo_open(radeon->radeonScreen->bom,
497						buffers[i].name,
498						0,
499						0,
500						RADEON_GEM_DOMAIN_VRAM,
501						buffers[i].flags);
502
503			if (bo == NULL) {
504				fprintf(stderr, "failed to attach %s %d\n",
505					regname, buffers[i].name);
506				continue;
507			}
508
509			ret = radeon_bo_get_tiling(bo, &tiling_flags, &pitch);
510			if (ret) {
511				fprintf(stderr,
512					"failed to get tiling for %s %d\n",
513					regname, buffers[i].name);
514				radeon_bo_unref(bo);
515				bo = NULL;
516				continue;
517			} else {
518				if (tiling_flags & RADEON_TILING_MACRO)
519					bo->flags |= RADEON_BO_FLAGS_MACRO_TILE;
520				if (tiling_flags & RADEON_TILING_MICRO)
521					bo->flags |= RADEON_BO_FLAGS_MICRO_TILE;
522			}
523		}
524
525		if (buffers[i].attachment == __DRI_BUFFER_DEPTH) {
526			if (draw->base.Visual.depthBits == 16)
527				rb->cpp = 2;
528			depth_bo = bo;
529		}
530
531		radeon_renderbuffer_set_bo(rb, bo);
532		radeon_bo_unref(bo);
533
534		if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
535			rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL);
536			if (rb != NULL) {
537				struct radeon_bo *stencil_bo = NULL;
538
539				if (rb->bo) {
540					uint32_t name = radeon_gem_name_bo(rb->bo);
541					if (name == buffers[i].name)
542						continue;
543				}
544
545				stencil_bo = bo;
546				radeon_bo_ref(stencil_bo);
547				radeon_renderbuffer_set_bo(rb, stencil_bo);
548				radeon_bo_unref(stencil_bo);
549			}
550		}
551	}
552
553	driUpdateFramebufferSize(radeon->glCtx, drawable);
554}
555
556/* Force the context `c' to be the current context and associate with it
557 * buffer `b'.
558 */
559GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv,
560			    __DRIdrawable * driDrawPriv,
561			    __DRIdrawable * driReadPriv)
562{
563	radeonContextPtr radeon;
564	GET_CURRENT_CONTEXT(curCtx);
565	struct gl_framebuffer *drfb, *readfb;
566
567	if (driContextPriv)
568		radeon = (radeonContextPtr)driContextPriv->driverPrivate;
569	else
570		radeon = NULL;
571	/* According to the glXMakeCurrent() man page: "Pending commands to
572	 * the previous context, if any, are flushed before it is released."
573	 * But only flush if we're actually changing contexts.
574	 */
575
576	if ((radeonContextPtr)curCtx && (radeonContextPtr)curCtx != radeon) {
577		_mesa_flush(curCtx);
578	}
579
580	if (!driContextPriv) {
581		if (RADEON_DEBUG & RADEON_DRI)
582			fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
583		_mesa_make_current(NULL, NULL, NULL);
584		return GL_TRUE;
585	}
586
587	if(driDrawPriv == NULL && driReadPriv == NULL) {
588		drfb = _mesa_create_framebuffer(&radeon->glCtx->Visual);
589		readfb = drfb;
590	}
591	else {
592		drfb = driDrawPriv->driverPrivate;
593		readfb = driReadPriv->driverPrivate;
594	}
595
596	if(driDrawPriv)
597	   radeon_update_renderbuffers(driContextPriv, driDrawPriv, GL_FALSE);
598	if (driDrawPriv != driReadPriv)
599	   radeon_update_renderbuffers(driContextPriv, driReadPriv, GL_FALSE);
600	_mesa_reference_renderbuffer(&radeon->state.color.rb,
601		&(radeon_get_renderbuffer(drfb, BUFFER_BACK_LEFT)->base.Base));
602	_mesa_reference_renderbuffer(&radeon->state.depth.rb,
603		&(radeon_get_renderbuffer(drfb, BUFFER_DEPTH)->base.Base));
604
605	if (RADEON_DEBUG & RADEON_DRI)
606	     fprintf(stderr, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__, radeon->glCtx, drfb, readfb);
607
608	if(driDrawPriv)
609		driUpdateFramebufferSize(radeon->glCtx, driDrawPriv);
610	if (driReadPriv != driDrawPriv)
611		driUpdateFramebufferSize(radeon->glCtx, driReadPriv);
612
613	_mesa_make_current(radeon->glCtx, drfb, readfb);
614	if (driDrawPriv == NULL && driReadPriv == NULL)
615		_mesa_reference_framebuffer(&drfb, NULL);
616
617	_mesa_update_state(radeon->glCtx);
618
619	if (radeon->glCtx->DrawBuffer == drfb) {
620		if(driDrawPriv != NULL) {
621			radeon_window_moved(radeon);
622		}
623
624		radeon_draw_buffer(radeon->glCtx, drfb);
625	}
626
627
628	if (RADEON_DEBUG & RADEON_DRI)
629		fprintf(stderr, "End %s\n", __FUNCTION__);
630
631	return GL_TRUE;
632}
633
634